Colophon

How this site is built.

The footer says “hand-built, no page builder” and means it. This page is the receipt: what the site is made of, where it runs, and how a change gets from my editor to the URL you’re reading — every layer of it self-hosted or hand-written.

Markup
Hand-written HTML & CSS, no framework, no build step
Performance
96 mobile Lighthouse performance
Hosting
nginx in Docker on an Oracle ARM VM
Pipeline
Self-hosted Forgejo git + CI, deploys over WireGuard

The pages

Every page on hiten.dev is a hand-authored HTML file. There is no framework, no static-site generator, no build step — what you see in view source is what lives in the repository. That’s a deliberate constraint, not nostalgia: for a site this size a framework buys nothing except a toolchain to maintain, and a hand-written page keeps every byte accountable.

The type is three self-hosted variable fonts — Gabarito for display, Hanken Grotesk for body text, and Newsreader italic for asides — served as subsetted woff2 from this domain with no third-party font CDN. Critical CSS is inlined in the head, the fonts are preloaded, and images are lazy-loaded WebP. The result is a 96 mobile Lighthouse performance score without a single trick that a framework would have done “for free”.

Light and dark themes follow the system preference, every page carries skip links and passes WCAG 2.2 AA checks, and the case-study lightboxes are pure CSS :target — the only JavaScript on most pages is the analytics loader and a scroll-reveal observer.

The machine-readable layer

Alongside the human-readable pages there’s a full entity graph in JSON-LD — Person, WebSite, Article and SoftwareApplication nodes that cross-reference each other and Wikidata — plus llms.txt and llms-full.txt for AI assistants, a sitemap, Open Graph images, and speakable markup. If a crawler, an answer engine or an LLM wants to understand who I am and what I’ve built, the site hands it a structured answer rather than making it guess.

The pipeline

The source of truth lives on a Synology NAS in my home rack, versioned in a self-hosted Forgejo instance running on the same box. Pushing to master triggers a Forgejo Actions runner (also self-hosted, on the NAS) that rsyncs the site over a WireGuard tunnel to an Oracle ARM free-tier VM, then restarts the nginx container. Traefik terminates TLS with automatic certificates. From git push to live is under a minute, and no code ever touches a third-party build service.

The same pattern serves the rest of my sites — including the Slipstream demo at tracker.hiten.dev and the Astro-based ask.hiten.dev — each with its own container behind the same edge.

Analytics without the creep: traffic is measured with self-hosted Umami — no cookies, no fingerprinting, no data leaving my infrastructure. Uptime is watched by a self-hosted Uptime Kuma instance that pushes alerts over ntfy.

The workflow

The site is also a working example of how I build now: AI-assisted with discipline. Claude Code runs on a dedicated headless box on my network, each repository ships an AGENTS.md with its own conventions, and well-scoped autonomous sessions get queued and the diffs reviewed like pull requests. The judgement — architecture, positioning, what to build at all — stays human; the typing is increasingly delegated.

Back to home  ·  Selected work  ·  Get in touch