This is the first alternate.org you can read the source of while it is being built. I learned this job by clicking view source on other people’s sites, so this one is open. The code is in a public repo, along with the rules the agents follow when they work in it.
This page is the one place on the site that names tools.
It’s a Next.js 16 app, in TypeScript, that prerenders every page to static HTML. React is the shell and nothing more. The parts that move are plain DOM, Pointer Events, WebGL and Web Audio, with no framework in between.
There are six runtime dependencies: Next.js, React, React DOM, Zod, MDX and gray-matter. I kept Next.js for what it does for the content (below). It is also most of the bytes on the page (see Speed).
The type is from my Adobe Fonts kit: Argent Pixel CF for the small lines, Le Monde Livre for the display and the prose.
Everything the site says lives in content/ as files: the spine (the five phases, the milestones, every design of this site) as JSON, the chapters as MDX, my old writing as cleaned HTML. These words too. There is no database and no CMS. Two headless backends died under earlier versions of this site. Files survive.
Every file is checked against a Zod schema before every build, and again when it’s read. The validator fails the build on a milestone without a source, an old post that tries to load a picture from somewhere else, or a phase intro that links to a piece that isn’t here.
In development the site reads that folder from disk, so an edit is a reload away. In production it reads the same folder from this repo on GitHub, at a ref, and caches it under one tag. A push sends a signed webhook to /api/revalidate, the tag goes stale, and the next visit to each page regenerates it in the background. A content commit goes live in seconds without a rebuild. (A new chapter still needs a build, because chapter URLs are fixed at build time.)
Everything that colors, moves, shatters or sounds reads from tokens/: color, motion, shatter, sound and the docks. The field, the docks, the instrument and the stylesheet all read the same files, so they can’t drift apart. The CSS custom properties are generated from them and inlined in every page’s head; the field gets the same colors as linear RGB for its shader. Colors are written in OKLCH, so a halfway mix between two moods looks halfway.
A validator turns the rules into build failures. The strictest one checks text contrast through the reading column’s scrim, over the worst the field can show (a highlight clipped to white), in every color scheme, around the clock and along the whole timeline. If a token change would make a line hard to read anywhere, the build stops. It checks the instrument too: no delay longer than the modeled pedal can do, and board ratios that keep the boards in tune with each other.
The home page is one surface, not a stack of pages. It opens on Hello and runs newest first, agents down to dial-up. Scrolling travels through time.
Pressing a phase dives into it (so does a pinch, ctrl + scroll wheel, or the “dive in” control above its name). Far away it’s a phase name. Closer, set small beside it, is what the web was then, with its milestones and this site’s designs from those years. Closer still, the sources. Escape steps back out. Type stays type at every scale: diving in moves the camera and never swaps the words. That’s David Small’s pattern, zoom as navigation. It lives in lib/surface.ts.
The work page takes the same idea down a corridor: every year is a stop, from now back to 1991, and scrolling moves the camera past the years still ahead of it.
Nothing on this site appears or disappears at once. Words type in and erase the way the logotype does, and boxes (a dock’s frame, the popover) set in and withdraw in the same steps, like a line of type being set. It’s one module, lib/type.ts, timed from the dock tokens, and it is the only transition there is. Pages leave the same way: the words that are leaving type out first, and the docks, the field and the music stay.
One clock drives every word, so a page of words typing costs one timer, not one per word. With reduced motion, everything is simply there.
I made one exception. A dock lands where you drop it.
Two bars dock to the edges of the window: the nav and the timeline. Nothing else docks. They are plain DOM and Pointer Events, not React; React only mounts them. The nav drags by its grip to the top or bottom edge, so its words stay upright, and locks to a corner or the center (arrow keys move it too). The timeline takes the edge opposite.
Where the nav sits picks the field’s color scheme, and where you are on the timeline picks the color inside it. A press on the timeline travels the page there, eased, never a jump.
Each bar is a pane of broken glass: the field behind it is seen through its own small shatter, every piece shifting what’s behind it by a different amount.
The shattered glass behind everything is doooomgaze, plain WebGL with no library. It loads after the browser goes idle, only on devices that can keep it smooth, and nothing waits for it to read a word. It is never clickable. It doesn’t answer the pointer at all.
It moves only by data: the mood of whatever is nearest the middle of the screen, how fast you scroll, lingering, selecting text, pausing, the time of day, and the music. Every value chases its target on a critically damped spring, so nothing jumps. Each load gets a new seed, so it never shatters the same way twice.
A second shatter with its own seed masks the first into moving windows. At Hello my portrait shows through them. On the work page the art is cut from a circle instead of a rectangle; crossing years rushes the shards, and at the oldest year they gather back into the circle, almost whole, never quite.
A link to the site unfurls with a real frame of the field, captured from it running.
The music is dooombient, made in Web Audio. My pedals are modeled per sample in an AudioWorklet: a flanger into a Carbon Copy delay into Infinite Jets into a Fathom reverb, on three boards at once (low, mid and air), locked in ratios so they stay in tune with each other. Chords only, from bright modes, at 48 bpm, so a chord turns over about every ten seconds.
Where you are on the timeline sets the pedals. Each phase has its own settings and they blend between phases. A big jump through time surges the boards, though not much louder than at rest.
It’s off by default for now; the switch is in the ambience popover. The audio starts with begin, because browsers allow no sound before a press, so turning it on later needs no second press. The instrument and its pedal models don’t load at all until sound first starts. The volume is set very low, because most people keep theirs at 100%.
Speed is the experience, so the budgets are rules in CLAUDE.md: the first round trip under 14 KB compressed, no WebGL before first paint, the read tier under 50 KB of JavaScript, the field and the instrument after idle. Here’s where they stand, measured from the build on Oct 16, 2026.
Nothing needs JavaScript to read a word, and there is no WebGL before first paint. The field is about 14 KB gzipped and arrives after idle. The instrument is about 4 KB plus 6 KB of pedal models, and it only loads if you turn sound on.
The first round trip misses, badly, on the home page: its HTML is about 148 KB gzipped, because my old writing is inlined in the page instead of fetched when you dive in. The fonts cost a round trip to Adobe before first paint. This page’s HTML is about 11 KB, under the line.
The JavaScript misses too. The home page carries about 190 KB of it, gzipped, most of it Next.js and React. That’s the price of content that goes live without a rebuild, and I’m paying it for now.
On a phone the site reads as a column: no zoom, every phase already open at reading size. The field still runs, at a lower pixel density, sized to the whole screen so the URL bar sliding in and out never rescales it. The docks take the top and the bottom, and nothing in them can widen the page. A device asking to save data, or too slight to keep the field smooth, gets the words alone.
I direct; Claude builds. I made this with Claude Code, art-directing every step from a live browser window: I watch, and I say what to change. Claude proposes and sketches. The calls on color, mood, type, layout and behavior are mine, and when a request is ambiguous it asks me one question instead of guessing in code.
The work ran in several chats at once (research, color, the docks, the instrument, the design system), each one handing off to the next through a written doc, so the next chat starts where the last one stopped.
Every piece of the air started as a prototype: one HTML file, no libraries. Then it was ported into the repo, onto the tokens. The prototypes are still there as dated snapshots, the reference each port is measured against.
The rules are files. CLAUDE.md holds the house rules every agent follows here: what never goes in this public repo, the speed budgets, the one transition, and “leave it alone by default.” The motion rules for the field are a skill beside it, and so is the audit that keeps components and tokens from drifting. Work happens on branches and lands by pull request, in small commits written in plain language. Nothing is pushed without my go.
The repo is part of the evidence. It started on Oct 14, 2026; by the evening of Oct 16 eight pull requests had merged, and every commit that isn’t a merge is co-authored by Claude.
Things I tried and changed.
beta.alternate.org: one dark, three-column portfolio page. Portfolio of Kevin Conboy Next.js, headless WordPress, Adobe Fonts. Archived 2026-10-13
Hello :) home plus Visual and Audio case studies; byte-identical since. usable, friendly, and fun since 1999 Next.js 9, React 16.13.1, Emotion, Barlow Condensed and Yrsa. Archived 2020-08-08
Black portfolio with project tiles: Calypso, o2, NYT Markets, Polldaddy. Kevin Conboy / Denver • Colorado WordPress, Timber/Twig, Bootstrap, ACF. Archived 2016-10-05
Ghost blog of imported posts. Bilateral illusions of unilateral attention Ghost 0.6, then 0.7 with the Innocent theme. Archived 2015-09-06
Stock Twenty Fifteen blog. The bilateral illusion of unilateral attention WordPress 4.1.1. Archived 2015-04-28
Stock Twenty Thirteen blog, mostly reblogs. The bilateral illusion of unilateral attention WordPress 3.6 to 4.1, Jetpack. Archived 2014-05-17
a10 on a WordPress multisite with BuddyPress. The bilateral illusion of unilateral attention WordPress 3.4 to 3.5.1; Rosario and Questrial. Archived 2012-07-04
a8, a Twenty Eleven child theme fed by Tumblr. WordPress 3.2 to 3.3.2; Typekit. Archived 2011-07-19
alternatev6 blog with Twitter and Flickr. I now work for Automattic, the makers of WordPress (2010) WordPress 2.5 to 3.0.4; Typekit by 2010. Archived 2008-05-09
Red-accented alternateorg theme; a Mac and MP3 music blog. Blogging since before it wasn't cool WordPress 1.5 to 2.0; sIFR headings. Archived 2005-06-24
Minimal white blog with orange titles and rotating taglines. '...the bilateral delusion of unilateral attention' - DFW XHTML 1.0 and my own PHP 4. Archived 2003-04-19
alternate://v3: #6699CC blue header, polls, comment counts. alternate://v3 PHP3, MySQL, Red Hat; HTML 4.01 tables. Archived 2001-05-17
alternate://v2: readers voted 3 to 1 for the blue design. Which design would you like to see implemented? PHP3, MySQL; HTML tables. Archived 2001-02-04
Multi-author tech and culture weblog. the best news, editorial, and commentary on alternate subjects PHP3 and MySQL; HTML 4.0 tables. Archived 2000-06-10
An empty Apache directory, then a placeholder page. Lorem ipsum dolor sit amet… Apache; HTML 4.01 tables. Archived 2000-01-18