A blog built with Elm and Pico CSS
No backend — Elm renders markdown posts with syntax highlighting, deployed as a static SPA on GitHub Pages.
- Elm 0.19 — routing, rendering, the whole thing
- Pico CSS — classless CSS framework
- IBM Plex — Sans + Mono
- elm-markdown + elm-syntax-highlight — markdown and code blocks
npm install
make watch
Requires Node.js 22+ (see .tool-versions) and jq for make post.
make help # list all targets
make build # compile, minify → build/
make watch # dev server with live reload
make format # elm-format on src/
make clean # remove build artifacts
make post # create a new post
src/
Main.elm # entry point, routing, update loop
Post.elm # post type, decoder, HTTP
Route.elm # URL parsing, page types
View.elm # all views and components
Render.elm # markdown renderer with syntax highlighting
Icon.elm # inline SVG icons
public/
index.html # shell, theme detection + toggle
style.css # Carina Nebula theme, Pico overrides
favicon.svg
posts/
index.json # post metadata
*.md # post content
make post prompts for a title, generates a slug, creates the markdown file
and adds the entry to posts/index.json.
Push to main triggers a GitHub Action that builds and deploys to GitHub Pages.
See .github/workflows/deploy.yml.
All post metadata lives in a single index.json (~150 bytes per entry).
Past ~300 posts, consider splitting by year (posts/2025/index.json, etc.)
and loading on demand.