main

www — vincent.demeester.fr

Personal website and activity stream.

Architecture

org files (Emacs) → ox-tufte → site/*.html → soupault → build/ → rsync → carthage
                                                ↑
flux generate (Go) → flux/ (entries, feeds, HTML) ──→ build/flux/

Two pipelines merge into build/:

  1. Org content: org-mode → ox-tufte HTML → soupault (CSS/JS injection, plugins) → build/
  2. Flux stream: Go CLI fetches sources → renders HTML + feeds → build/flux/

Static assets (images, data) are copied directly to build/.

Key Directories

  • site/ — soupault input (handwritten pages + copies from root). Gitignored except: index.html, about.html, sandbox.html, posts/index.html
  • build/ — soupault output, the actual deployed site. Gitignored.
  • flux/ — flux tool output (entries.json, HTML, feeds). entries.json is tracked in git.
  • cmd/flux/, internal/flux/ — Go source for the flux CLI tool
  • plugins/ — soupault Lua plugins
  • scripts/ — deploy script + NixOS service config
  • Root *.html, articles/, posts/, etc. — org-exported content (source of truth)

Flux Tool (Go)

6 sources, ~936 entries:

  • GitHub merged PRs + opened issues (search API)
  • GitHub releases (tektoncd + vdemeester orgs)
  • Git log (page new/updated)
  • TIL (~/desktop/org/til.org)
  • Bookmarks (~/desktop/org/bookmarks.org)
  • Mastodon (fosstodon.org/@vdemeester — posts + boosts)

Output: flux/entries.json (store), flux/index.html (latest 50), year archives, tag pages, JSON+Atom feeds, content-only feeds, homepage snippet.

Build: go build -o bin/flux ./cmd/flux/ Run: ./bin/flux generate -v

Soupault Plugins

All pages go through soupault which injects:

  • CSS (style.css) + JS (flux.js) + viewport meta
  • Theme toggle (☀️/🌙) in floating .site-controls pill
  • Navigation links (⌘ ≋ ☉) in the same pill
  • Consistent footer with feed links
  • Heading slug anchors (§)
  • Callout transforms, tag pills, link timestamps
  • Strips old CSS (tufte.css, etc.)
  • Fediverse creator meta tag

Build Pipeline

make build runs:

  1. flux generate — fetch sources, render flux output
  2. populate-site — copy root HTML to site/ (skip files already there)
  3. inject-snippet — insert flux/home-snippet.html into site/index.html
  4. soupault — process site/build/
  5. Copy static assets + flux output → build/

make deploy = make build + rsync build/carthage.vpn

Important Notes

  • Don’t edit site/index.html without the <!-- FLUX_SNIPPET --> placeholder — the Makefile injects the flux snippet there
  • populate-site skips existing files — handwritten site/*.html pages won’t be overwritten by root copies
  • entries.json is version-controlled — TIL/bookmark entries persist across server runs where org files aren’t available
  • Slug algorithm must match soupault’sslugify() in Go uses [^a-z0-9] → hyphen (same as heading-slugs.lua)
  • Old root HTML files are source content (org exports) — don’t delete them
  • Deploy target: carthage.vpn:/var/www/vincent.demeester.fr