Add new blog post documenting a week using the Pi CLI agent for 100% agentic development. Include AI agent configuration with custom prompts and skills to streamline content creation workflow. - Publish "Week with my-pi-agent" article with Pi logo and screenshot assets - Add .pi/ configuration with new-blog-post prompt and review-article skill - Create AGENTS.md with comprehensive project documentation for AI assistants - Fix SVG rendering to skip unsupported dimension extraction in markdown filter - Update picture generator to handle SVG files with simple img tag - Update syntect dependency to 5.3.0 with default-fancy features - Swap featured segment from older post to new Pi agent article
8.0 KiB
AGENTS.md
Project Overview
Personal website and blog hosted at https://michalvanko.dev. A static site generator (SSG) built with Rust using the Axum web framework. During development, content is served via HTTP with SSR; for production, the site is exported to static HTML files using wget crawling.
Technology Stack:
- Backend: Rust, Axum web framework, Tokio async runtime
- Templating: Askama (compile-time template engine)
- Styling: Tailwind CSS v4
- Content: Markdown with YAML front matter (gray_matter), parsed with pulldown-cmark
- CMS: Decap CMS (formerly Netlify CMS) for content management
- Build Tool: Just (command runner, similar to make)
- Deployment: Caddy reverse proxy, rsync to remote server
Architecture
Directory Structure
├── src/ # Rust source code (~40 files, ~2090 lines)
│ ├── main.rs # Entry point, sets up Axum server with static file serving
│ ├── router.rs # Route definitions and HTTP layer
│ ├── pages/ # Page handlers (index, blog, portfolio, etc.)
│ ├── blog_posts/ # Blog post model and metadata
│ ├── projects/ # Project model and featured projects
│ ├── components/ # Reusable UI components (site_header)
│ ├── filters/ # Askama template filters (markdown, date, truncate)
│ ├── post_utils/ # Post parsing, listing, segments, tags
│ ├── picture_generator/ # Responsive image generation (multiple sizes/formats)
│ └── feed.rs # RSS feed generation
├── templates/ # Askama HTML templates
│ ├── base.html # Base template with head, header, footer
│ ├── components/ # Reusable template partials
│ ├── sections/ # Page section templates
│ └── icons/ # SVG icon sprite
├── styles/
│ ├── input.css # Tailwind source with custom theme
│ └── output.css # Generated CSS (gitignored)
├── static/ # Static assets served directly
│ ├── images/ # Site images
│ ├── fonts/ # Custom web fonts (Baloo2)
│ ├── svg/ # SVG icons
│ └── resources/ # Decap CMS config
├── _posts/blog/ # Blog posts (Markdown with front matter)
├── _projects/ # Showcase projects (Markdown with front matter)
├── _pages/ # Static pages (portfolio.md)
├── generated_images/ # Auto-generated responsive images (gitignored)
├── dist/ # SSG output folder (gitignored)
└── target/ # Rust build artifacts (gitignored)
Key Entry Points
src/main.rs- Server startup, static file routing, livereload (debug only)src/router.rs- All route definitions, maps URLs to page handlerssrc/pages/index.rs- Homepage, demonstrates async data loading pattern
Data Flow
- Content Loading: Markdown files in
_posts/,_projects/,_pages/are parsed at runtime - Front Matter: YAML metadata extracted via
gray_mattercrate - Template Rendering: Askama templates receive structs with data
- Image Generation: Images auto-generated in multiple sizes on first request
- SSG Export:
wgetcrawls running server, saves HTML todist/
Code Conventions
Rust Patterns
- Module Organization: Each domain has a
mod.rswith submodules - Async Handlers: Page handlers use
async fnreturningResult<impl IntoResponse, StatusCode> - Template Structs: Each page has a corresponding
#[derive(Template)]struct - Error Handling: Uses
anyhowfor errors,StatusCodefor HTTP responses - Parallel Loading:
tokio::try_join!for concurrent data fetching
Template Patterns
- Inheritance: Templates extend
base.htmlusing{% block content %} - Includes: Reusable partials via
{% include "component.html" %} - Filters: Custom filters in
src/filters/(e.g.,{{ content|markdown }}) - Configuration:
askama.tomlsets template directory and whitespace handling
Naming Conventions
- Files: snake_case for Rust files, kebab-case for templates
- Routes: kebab-case URLs (
/blog,/showcase/m-logo-svg) - Front Matter: snake_case fields in YAML
Configuration Files
| File | Purpose |
|---|---|
Cargo.toml |
Rust dependencies, package metadata |
askama.toml |
Template directory config |
.prettierrc |
JS/JSON formatting (trailing commas, 2-space, single quotes) |
.nvmrc |
Node.js version: lts/* |
.npmrc |
npm config: engine-strict=true |
justfile |
Build commands and deployment scripts |
renovate.json |
Dependency update automation |
static/resources/config.yml |
Decap CMS configuration |
Setup Requirements
Prerequisites
- Rust: Stable toolchain (uses edition 2021)
- Node.js: LTS version (for Tailwind CSS, Decap CMS)
- Just: Command runner (
cargo install justor system package) - cargo-watch: For development hot reload (
cargo install cargo-watch)
Environment Variables
PORT- Server port (default: 3080)RUST_LOG- Logging level (default:axum_server=debug,tower_http=debug)TARGET- Build target mode (used injust prod)
Development Setup
# Install dependencies
npm install
# Run development server (starts all services in parallel)
just dev
# This runs: server_dev, tailwind watch, decap_server
# Or run individually:
just server_dev # Rust server with hot reload
just tailwind # CSS watch mode
just decap_server # Local CMS backend
Common Commands
just test # Run Rust tests
just test_watch # Run tests with watch mode
just prod # Run server in release mode
just export # Generate static site to dist/
just deploy # rsync dist/ to remote server
Important Files
Configuration
Cargo.toml- Rust dependencies (axum, askama, pulldown-cmark, etc.)justfile- All build/dev/deploy commandsstatic/resources/config.yml- Decap CMS collections and fieldsstyles/input.css- Tailwind theme customization (colors, fonts, spacing)
CI/CD
.gitea/workflows/test.yaml- Runscargo teston push/PR.gitea/workflows/release.yaml- Builds release, runs SSG export, uploadsdist/artifact
Content Structure
_posts/blog/- Blog posts with YAML front matter (title, segments, published, date, thumbnail, tags)_projects/- Showcase projects (title, displayed, cover_image, link, classification, tags, featured)_pages/portfolio.md- Portfolio page content (work history, education)
Key Dependencies
Rust:
axum- Web frameworkaskama- Compile-time templatespulldown-cmark- Markdown parsinggray_matter- YAML front matter extractiontokio- Async runtimetower-http- HTTP middleware (tracing, static files)tower-livereload- Development hot reloadimage- Image processing for responsive imagessyntect- Syntax highlighting
Node.js:
tailwindcssv4 - CSS framework@tailwindcss/cli- Tailwind CLI
Notes for Agents
-
Template Changes: Askama templates are compiled into Rust code. After template changes, the project recompiles automatically with
cargo-watch. -
Adding Routes: Add handler in
src/pages/, register insrc/router.rs, create template intemplates/. -
Content Model: All content uses YAML front matter. See
static/resources/config.ymlfor field definitions. -
Image Handling: Images are auto-generated in multiple sizes. The
picture_generatormodule creates responsive<picture>elements. -
Debug vs Release: Debug builds include livereload. Release builds are optimized for production.
-
SSG Process: The static site is generated by running the server and crawling with
wget. All linked content must be discoverable from the homepage.