How the ride site is built

A 62-day bicycle journal (route, nights, money, photos and vlogs) published as a fast static site that costs nothing to host.

2026 · Solo: design, frontend, backend, deployment · Node 22, Express, Leaflet, sharp, Cloudflare Workers static assets, node --test

The journal on a laptop: a grey map of North America with the route drawn coast to coast on the left, and the list of days, each with its number, date and route, on the right.

Why

I rode from New York to San Diego between August 2 and October 2, 2026. I wanted one place for the route, where I slept, what I spent, the photos and the daily Instagram vlogs. It had to be easy for me to update from the road, and safe to publish without leaking bank details.

How it works

Ride site architecture On my laptop, a local Express editor writes JSON files and photos. npm run publish sanitizes the data, renders image sizes and runs a leak check, producing a dist folder. The dist folder is deployed to Cloudflare Workers static assets, and browsers load it with Leaflet and OpenStreetMap tiles. Local editorExpress, my laptop JSON and photosprivate, in git npm run publishsanitize, image sizes,leak check dist/static files only Cloudflarestatic assets BrowserLeaflet, OSM tiles Ride site architecture Local Express editor, then JSON and photos, then npm run publish (sanitize, image sizes, leak check), then dist, then Cloudflare static assets, then the browser with Leaflet. Local editorExpress, my laptop JSON and photosprivate, in git npm run publishsanitize, image sizes,leak check dist/static files only Cloudflarestatic assets BrowserLeaflet, OSM tiles
Editing happens on my laptop; only a cleaned, static copy is ever published.

Decisions

A local editor and a static site

The editor is an Express app that only runs on my laptop. It writes JSON files and photos. The public site is plain HTML, CSS and JavaScript served as Cloudflare static assets. There's no server or database to attack, nothing to patch, and hosting is free.

An image pipeline built for phones

The editor accepts a whole folder of iPhone photos: it converts HEIC to JPEG, names them in order and records their size. At publish time each photo becomes three widths (800, 1600, 2400) served with srcset, keeping the color profile and stripping EXIF and GPS. Frames take the photo's own shape, so nothing is ever cropped.

Privacy by construction

The source data includes raw card statements. Publishing allowlists the public fields, drops private places and notes, then scans every file in the build for any forbidden string. If one is found, it deletes the build and fails. A leak has to get past a check that runs on every publish.

Data that can't be overwritten by accident

Every save writes a temp file and renames it, behind a write queue, so a crash never leaves half a file. An early bug let an old browser tab overwrite newer stories, so the editor now sends only the fields you actually changed.

Tested first

165+ tests run under node --test, covering the API, the publish step, statement parsing, units, the route map and the slideshow. Most were written before the code they test.

Screens

The journal on a phone: the site header, the map of the route, and below it the Chinese introduction and the start of the list of days.
On a phone the map sits above the days.
The local editor's Days tab: one row per day with its date and route, and badges for what's still missing, such as unrated places or no stay recorded.
The local editor: each day shows what's still missing; opening one lets me drop in a folder of photos, reorder them and add the vlog link.

What I'd do next