Skip to content

IvelOt/portifolio

Repository files navigation

levi_blog

Personal portfolio and blog built in Rust. Terminal PC-98 aesthetic, single 1.5MB binary, ~1.8MB RAM usage.

Features

  • i18n support (PT-BR / EN-US) with separate markdown files per language
  • Tag-based filtering and full-text search (client-side JS, works on static hosting)
  • Pagination on the blog list (10 posts per page)
  • Projects section on the home page (posts tagged project, limited to 4, with link to all)
  • Tags displayed on post listings, latest post, and project cards
  • Fully static output — deploy anywhere, no server required
  • Optional dynamic server via axum for Railway / Docker
  • Boot sequence animation, CRT scanlines, glitch effects
  • Claude Code slash commands for managing posts

Deploy options

The same binary handles everything. Choose what fits your setup:

GitHub Pages (static)

Push to main and the GitHub Actions workflow builds and deploys automatically.

The build generates a complete dist/ folder — HTML, CSS, assets. Tag filtering and search run client-side via JavaScript baked into the pages.

For repos hosted at a subpath (e.g. username.github.io/repo-name/), the --base flag adjusts all links:

./levi_blog build --base /repo-name

The workflow in .github/workflows/deploy.yml already handles this. To activate:

  1. Go to Settings → Pages → Source and select GitHub Actions
  2. Push to main

Railway / Docker

docker build -t levi_blog .

docker run -d \
  --name levi_blog \
  --cpus="0.05" \
  --memory="8m" \
  -p 3000:3000 \
  levi_blog

Railway detects the Dockerfile automatically. No extra config needed — the server reads the PORT environment variable injected by Railway.

Local development

cargo build --release
./target/release/levi_blog dev --port 3000

Open http://localhost:3000.

To serve the static output without the Rust server (e.g. with Python):

./target/release/levi_blog build
python -m http.server 8080 -d dist

Requirements

  • Rust 1.85+ (edition 2024)

Creating posts

Create two files in content/posts/ with the desired slug:

content/posts/my-post.pt.md
content/posts/my-post.en.md

The filename becomes the URL: /pt/blog/my-post/

Each file follows this format:

---
title: Post Title
date: 2026-02-18
tags: project, rust
---

Markdown content here.

Posts tagged project automatically appear in the Projects section on the home page.

After creating files, rebuild:

./target/release/levi_blog build

Claude Code slash commands

Requires Claude Code installed and the project open in a session.

/post-new <slug> [languages]

Creates a new post interactively. Asks for title, topic, and tags, then writes a draft or scaffolds the structure.

/post-new my-new-post
/post-new my-new-post pt
/post-new my-new-post pt,en

/post-translate <file> [languages]

Translates an existing post to one or more languages. Adapts the content naturally — not a literal translation.

/post-translate content/posts/hello-world.pt.md en
/post-translate content/posts/my-post.en.md pt

If the target language is omitted, it infers which language is missing from the existing file.

/post-from-github <url> [languages]

Fetches a GitHub repository's README and metadata, then writes a post about it in the author's voice. Generates PT and EN by default.

/post-from-github https://github.com/user/repo
/post-from-github https://github.com/user/repo pt

Blog filtering

The blog listing at /pt/blog/ and /en/blog/ supports:

  • Tag filter: /en/blog/?tags=project or /en/blog/?tags=project,rust
  • Search: /en/blog/?q=keyword
  • Pagination: /en/blog/?page=2
  • Combined: /en/blog/?tags=rust&q=axum&page=1

All filtering happens client-side — works on GitHub Pages with no server.

Screenshots in posts

Use a grid with CSS-only lightbox (click to expand):

<div class="screenshots">
  <a href="#img1"><img src="/assets/screenshots/img.png" alt="desc"></a>
</div>

<div class="lightbox" id="img1">
  <a href="#" class="lightbox-close"></a>
  <img src="/assets/screenshots/img.png" alt="desc">
</div>

Place screenshot files in static/assets/screenshots/.

Structure

.github/
  workflows/
    deploy.yml             GitHub Actions — build and deploy to Pages
.claude/
  commands/
    post-new.md            /post-new slash command
    post-translate.md      /post-translate slash command
    post-from-github.md    /post-from-github slash command
content/
  about.pt.md              Bio in Portuguese
  about.en.md              Bio in English
  posts/
    slug.pt.md             Post in Portuguese
    slug.en.md             Post in English
static/
  style.css                Terminal PC-98 CSS
  assets/char/             Character image (home page)
  assets/screenshots/      Post screenshots
templates/                 Askama templates (compile-time)
src/
  main.rs                  CLI (build/serve/dev)
  build.rs                 Full static site generator
  server.rs                Axum server for Railway/Docker
  markdown.rs              Markdown and front matter parser

About

my simple portifolio.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors