\n

The site is a flat vault of Markdown notes in Obsidian, rendered as a static
site, with no build framework on the pages themselves. This is how it works.

How it is built

  • Quartz turns the Obsidian vault into a static site — note pages are one
    reading column, no sidebar forest. Quartz is pinned to a specific commit, so
    an upstream change can never change this site on its own.
  • The section pages (/Notes, /Projects, /Practice-of-Product, /Travel,
    /library, /news) are not Quartz pages. A post-build step,
    build-pages.mjs, derives them from the notes and writes them as plain
    HTML/CSS/JS. No framework, no bundler — each page is a file you can read top
    to bottom, and nothing here required editing a note to make it work.
  • Everything a page shows is derived at build time from
    /api/notes.json — tags, length bands, dates, backlinks. The vault itself is
    never touched.
  • The top bar is static HTML on every page, so navigation works before any
    script runs. JavaScript only powers the interactive parts: search, the light/
    dark toggle, the tag map, and refreshing the Bluesky feed.
  • Fonts are self-hosted (Inter and IBM Plex Mono, served as woff2
    from this site). No request to a third party, no layout shift.
  • The faint topographical background is County Kerry, where I’m from. Its
    contour lines come from real SRTM elevation data for the county, rendered as
    an SVG and masked behind the content, tinted a light or dark grey to match
    the theme so it stays in the background.
  • Deploys happen on every push: GitHub Actions runs the build and publishes to
    Cloudflare. The only third-party script is Google Analytics, which loads
    asynchronously.

The principles

The whole design sits on a few rules, written in my notes:

  1. Flat storage, layered reading. One folder of notes; structure lives in
    the presentation, never the directory tree. Adding a view never moves a
    file.
  2. Derive before you demand. No view depends on metadata that does not
    exist yet. If a view needs tags, it works with the tags already inline in
    the notes.
  3. Don’t fake authority. Weak signals are shown as what they are. A
    timeline that dresses an import date up as an authoring date is worse than
    no timeline.
  4. A view is a URL. Every filtered or sorted state is a link worth sending
    to someone.
  5. Experiments are cheap, disposable, and public. They live under
    /lab, get tried on the real site, then graduate or die. An experiment is
    never allowed to become load-bearing before it graduates.
  6. Native, not embedded. Third-party embed scripts are a tax on load time
    and control. Prefer fetching a public API and rendering the result in the
    site’s own type and colour.

Stated, not derived

Some of this is hand-maintained on purpose: the few things that cannot be
derived — the homepage’s home.json, the shelf’s books.json, the folder-level
“this is a theme, not a place” calls — are stated, and the build asserts the
invariants that would otherwise break silently (links resolve, every page is
tracked, the two halves of the site show the same bar).

The design reasoning, experiment log, and the sites that influenced this
project live further back in my notes. If you use any of it for your own site,
that is exactly the point.