← Engineering log

27 September 2026 · 4 min read

Deploying my own past

The time machine runs every earlier version of this site, live. Getting 18-month-old commits deployed again took a detour through a security block.

This site started in March 2025 as a gradient and a name. The time machine shows every version since, and you can scroll and click around each one, because each is still running. The hard part wasn't the page; it was getting code from a year and a half ago deployed again without disturbing the current site.

Choosing the versions

I took the last commit of each month, then dropped the months whose changes were text alone (April and July 2025): a version that looks identical to the one before adds a stop, not a story. September, October and December 2025 had no commits. That left five past versions and today.

One project each, from a worktree

Each version is its own small Vercel project, deployed from a git worktree of that commit in a scratch folder. The working copy never moves, and the live site's project and settings are never touched. Deploying each as its own production site also gives it a public address, where a preview of the main project would sit behind a login.

The block

March and May deployed first time. June, August and November came back with:

Error: Vulnerable version of Next.js detected, please update immediately.

They were on Next.js 15.2.4, which has a known security hole, and Vercel refuses to deploy it. The fix was a patch update in each throwaway copy only, to 15.2.8, the version the live site runs, moving nothing but Next and its own packages:

pnpm add next@15.2.8 --lockfile-only

The repository's history stays exactly as it was; the patch lives only in what was deployed. Nothing visible changes between 15.2.4 and 15.2.8.

Screenshots first, then the real thing

My first version showed screenshots. The heroes barely changed from March to August, so each screenshot was the whole page instead, stitched from screens taken while scrolling, with the small floating parts (nav bars, buttons) hidden after the first screen so they wouldn't repeat down the page. Page length turned out to tell the story best: 4,586 pixels in March, 13,653 today. Those lengths are the bars over the slider.

But a screenshot of a site is a poor substitute for the site. Nothing blocked framing the old deployments, so the time machine now runs each version in a frame:

  • Only the version selected loads, since each is a full site
  • On a desktop it renders at 1440 pixels wide and is scaled down with a CSS transform, so you see its desktop design rather than its tablet layout; on a phone, at the phone's width
  • A small still of its first screen (under 45 KB) shows until the frame reports it has loaded
  • Today's version is framed with the terminal's embed flag, which skips the entry screen

The trade-off is weight: moving to November downloads that whole old site, 3D effects included, where a screenshot was a few hundred kilobytes. Loading one version at a time keeps that reasonable.