Projects Build

Building ena.is

One domain, one app, and a token system that lets every section keep its own light.

Aug 20, 2026 · 4 min read

ena.is is one SvelteKit app behind one domain. No microsites, no separate blog engine, no static-site generator bolted to the side — the galleries, this feed, the account system, and a few diversions all compile from the same repository and ship as a single Node process. That constraint is the whole architecture, and most of what follows is the story of making one app feel like several places.

One app, one box

The stack is deliberately short: SvelteKit 2 on Svelte 5, Tailwind 4, Prisma over Postgres, and adapter-node so the build is just a server you can run anywhere. Hosting is a single Railway service; DNS sits on Bunny. There is no CDN build pipeline or edge anything yet — the site is small enough that a well-behaved Node process and honest cache headers do the job.

Tokens before pages

The first real design work was not a page, it was a palette contract. Every color on the site is an OKLCH token — base, surface, fg, line, an accent — declared once as light values and re-bound under a .dark class for the dark theme. Components never pick colors; they consume utilities like bg-surface and text-fg-muted and inherit whatever the theme says those mean.

The accent is a periwinkle at hue 265, and that single number quietly runs the brand: the front page's aurora drifts through its neighbours, links lean on it, and the tint on this very page is the same hue turned nearly all the way down.

Rooms with their own light

SvelteKit's route groups made the site's favorite trick cheap: sections that keep their own atmosphere. The main pages follow the visitor's theme toggle. The photography wing ignores it — galleries render on a near-black ground no matter what, because photographs deserve a darkroom. This section ignores it in the opposite direction and stays paper-light, because long text deserves a page.

Each of those is just a layout in its own route group, pinning its own color-scheme and palette. Walking from the front door into a gallery and then into a write-up should feel like moving between rooms in the same house — same bones, different light.

The parts you don't see

Accounts run on better-auth; sessions, API keys, and a QR hand-off flow hang off it. The Postgres instance is shared with a Discord bot that predates the site, which imposes a useful discipline: no casual schema pushes, only deliberate, targeted migrations — the database is a treaty, not a scratchpad.

Still to come

The galleries currently hold stand-in images while the real photo pipeline — originals in a bucket, a proper upload flow, metadata in the database — gets built. That build will get its own write-up here when it ships, which is rather the point of this page.