Notes on how this thing is built. Mostly for me, partly for you if you’re wondering why there are no folders or what the moons mean.
Look and feel
- Colours ported straight out of my Obsidian vault theme, so the site and my private notes feel like the same place.
- Dark by default, muted yellow-green accent (
#c7ce64). Bit low-contrast on purpose — I wanted that colour, not a corrected version of it.
No folders, no categories
The decision I actually care about.
- Everything lives in one flat pile —
notes/. Blog post, finished project, half-thought, photo, doesn’t matter. - Only other pages are a few hand-written hubs at the root (
index,about,research) that link into the pile. - Why: category is the one property that changes as a note grows. Stray idea → script → analysis → occasionally a paper.
- If I had to file each note under
projects/orresearch/orblog/I’d have to re-file it every time it grew up. Worse, I’d catch myself deciding what a thing “is” before it’s finished — which quietly caps how far it can go. - Same reason I don’t lean on tags. A tag makes a claim: “this note is a network-analysis note.” But meaning is relational — a note means something because of what it connects to, which you only find out later. So: links > tags. When I do tag it’s late, to name a cluster that already formed.
The moons
Folders can’t show a note is growing, so something else has to. That’s the little moon next to each date.
- Every note has a
statusin frontmatter, moves along a lunar cycle as it matures:
🌑 new → 🌒 waxing → 🌓 half → 🌔 gibbous → 🌕 full
- 🌘 waning kept aside for stuff that stalled or went stale.
- Beats a “seedling / sapling / evergreen” ladder because the phases are ordered by feel, not judgement. I never have to rule on whether a note is a “sapling” — I just ask if it’s fuller than last time. Like glancing at the actual moon.
- Growing up changes the badge, never the folder. That’s the whole point of the section above. (Also a wink at the astrophotography pages.)
On the AI bit
Worth being upfront: I built a lot of this with Claude Code (Anthropic’s CLI, so it’s Claude too). Mostly the fiddly stuff —
- patching the vendored Quartz plugins (the
ContentMetamoon/status line, explorer tweaks, footer, folder pages), - wrangling the deploy + Caddy + server setup,
- and yes, it helped me rewrite this very note into something closer to how I actually talk.
I decide what goes where and what the site is. The AI is a fast pair of hands for the parts I’d otherwise procrastinate on. Feels only fair to say so on the page that explains how the thing works.
The stack
- Static site, built with Quartz 5.
- I write plain Markdown in
Obsidianflavour —[[wikilinks]],![[embeds]]for images/reports. Quartz eats the folder, spits out HTML. - The link graph at the bottom of each page comes from those wikilinks. Nothing wired by hand.
- Node 22 (via nvm), build with
npx quartz build. - Deploy is one command:
./deploy.sh→ builds →rsyncto my server → Caddy serves it over HTTPS. - No database, no CMS, no cloud build. Files go laptop → box. That’s it.
Self-hosted, on purpose
- Load a page here and your browser talks to exactly one origin: mine. Zero third-party requests.
- No CDN fonts, no analytics, no jsDelivr, nothing. Every asset is vendored and served from the same place as the text.
- Why:
- Privacy — don’t want your IP leaking to Google/some CDN just because you read a note.
- Resilience — the whole thing builds with the network unplugged. Depends on nobody’s uptime but mine.
- All 44 Quartz plugins live in the repo (
plugins/), not pulled from GitHub at build time. So it can’t rot from under me. Downside: I patch them by hand when I want something changed, which I’ve done a fair bit.
That’s the system. Files in a pile, links between them, moons for maturity, one origin serving all of it. Everything else is just writing.