Deployment

The built site is a folder of static files. There’s no server-side component, no runtime configuration, and no rebuild required to deploy to a new path. The relativize pass rewrites every internal URL to be page-relative, so _site/ works under any URL prefix.

Build

pnpm build runs Eleventy, which writes the site under _site/ (or whatever --output you pass). After Eleventy completes, a few more artifacts are produced:

  • _site/symbols.json — the API symbol manifest for the fuzzysort index. See Search → API symbols.

  • _site/assets/apidocs/pagefind/ — the Pagefind prose index. See Search → Prose search.

  • A Markdown sibling for every page (_site/foo.md next to _site/foo/index.html), plus _site/llms.txt (an index) and _site/llms-full.txt (every page concatenated in navigation order) — plain-text renderings for LLM consumption.

These all run from the same eleventy.after hook, so the output directory is fully self-contained the moment the build command exits.

Portable URLs

The relativize pass walks every emitted HTML page after the layout and content pipeline are done. For each absolute URL it finds, it computes the page-relative equivalent and rewrites the attribute:

PageOriginalRewritten
/ /code-blocks/ ./code-blocks/
/code-blocks/ /images/ ../images/
/code-blocks/ /assets/apidocs/css/apidocs.css ../assets/apidocs/css/apidocs.css

The rewrite covers href, src, and srcset attributes. Absolute URLs to external hosts are left alone. Protocol-relative URLs (//cdn.example.com/...) are left alone too — they’re explicitly anchored to the current scheme.

Verifying the build

Two checks confirm the site is portable:

  1. No leading-slash URLs survive in emitted HTML. From the project root (the --include skips the .md siblings, whose links stay absolute by design):

    grep -rE 'href="/|src="/' --include='*.html' _site/ && echo "FAILED" || echo "OK"
  2. Serving the directory from any prefix renders correctly. The quickest local test:

    python3 -m http.server -d _site 8000
    # visit http://localhost:8000/ — site loads
    # move _site under some/prefix/ on another server and load
    # http://that-server/some/prefix/ — site still loads

If both checks pass, the build is portable to any subpath without rebuilding. That includes deploying preview branches under https://example.com/pr-1234/ or shipping the site bundled inside a desktop app at a file:// path.

Common hosts

Static file servers

Nginx, Caddy, or anything that serves a directory. No special configuration — point the document root at _site/.

GitHub Pages, Cloudflare Pages, Netlify, Vercel

Each has its own build command field; set it to pnpm build and the publish directory to _site. No further config.

S3 + CloudFront (or equivalent)

Sync _site/ to the bucket; serve via the CDN. Set index.html as the default document so directory URLs resolve correctly.

Inside another app

Because URLs are relative, you can mount the site at /docs/ of an existing application without rebuilding. Whatever serves your /docs/ route just needs to respect index.html at directory paths.

Speculation rules prefetch

The layout includes a <script type="speculationrules"> block that asks the browser to prefetch every same-origin link on hover/focus, at “moderate” eagerness. On a static host that means navigations between docs feel near-instantaneous: the next page is already in cache by the time the click registers.

Combined with cross-document View Transitions, the result is a feel that’s closer to an SPA than a static site — without shipping any router code.