Loading reel
Home/Work/A Thousand Saturdays
Creative

a love letter that plays like a film

A gift one person sends to one other person, shaped like a short film: a 3·2·1 leader, a title card, three acts, a deck of reasons, a countdown to the next date and a set of end credits. Not one photograph or video in it — the grain, the bokeh and the light leak are all drawn by the browser.

Demonstration build. Designed and built by me to show craft — a front-end piece, not a client commission. Everything animates and works; every name, date and place in it is invented.

Type
Demonstration build
Stack
HTML · CSS · Canvas
Shape
Four pages, no images
Editor
Browser editor
portfolio-3ud.pages.dev/demo-letter

Not screenshots — the demo itself, running in both frames · open it full size ↗

Why I built it

Most of my work is websites with a job to do. This is the other corner of the craft: something one person sends to one other person, opened on a phone, probably in bed, and kept. I built it to show pacing and atmosphere — the parts of a site you feel before you read a word.

It is shaped like a short film because that is the language I already speak. A leader counts down, a title card lands, three acts run, the credits roll. The film grammar does the emotional work that a stock photograph usually fails at.

Everything is drawn, nothing is shot

There is not a single photograph or video file in the whole piece. The warm grade is layered gradients, the grain is one SVG turbulence jittering on a three-step loop, the light leak is a blend mode, and the bokeh drifting through the frame is about sixty particles on one canvas that pauses itself the moment the tab is hidden.

That is the point, not a shortcut: it opens instantly on a phone on bad signal, and there is no hero image arriving late to ruin the first three seconds.

The frame never breaks

Every page sits inside a 2.39:1 letterbox with a running timecode, a REC light and the reel slug in the corners — so moving between the four pages feels like cutting between scenes rather than clicking around a website. A sprocketed film edge down the left fills as you scroll.

Four pages, one reel

The title card holds the leader and the play button. The film runs three acts, each with its own slate line, and ends on a live countdown to the next date — it reads the date from the content file and rolls forward a year each time it passes. The reasons are a deck you swipe, drag or arrow through. The end credits close it out and give the other person somewhere to write back.

Words you can change

None of the writing is welded into the design. Every line lives in one content.json, and a loader overlays it at load with the printed words still in the HTML as the fallback, so the film reads correctly even if that file never arrives.

There is an editor at /demo-letter/edit/: a field for every line, add-a-reason, and a live preview you can flip between all four pages while you type. In the demo Publish hands you the JSON; on a real build the same call writes the file and the film updates for whoever opens it next.

On a phone, one-handed

Checked down to 360px — the title breaks between words and never mid-word, the deck takes a swipe, the letterbox bars scale with the viewport. Under prefers-reduced-motion the leader is skipped, the grain stops moving, the dust never starts, and every scene is simply there.

Under the hood

How it works

Two moving parts: an atmosphere that costs almost nothing to run, and a content layer that lets every line be rewritten without opening the code.

GradientsSVG grainCanvas dust

The atmosphere

  • The grade is layered radial gradients; the light leak is one element in mix-blend-mode:screen.
  • The grain is a single SVG turbulence stepped on a 1.1s three-frame loop — film weave, for the cost of one repaint.
  • About sixty bokeh particles on one <canvas>, sized to device pixel ratio, stopped the moment the tab hides.
  • Under prefers-reduced-motion the grain holds still and the canvas never starts.
EditorServerlesscontent.json

The words

  • Every string lives in one content.json; each page declares how far it sits from the root and loads it from there.
  • The printed words stay in the HTML as the fallback, so a failed fetch costs nothing.
  • The editor builds a field per line, adds reasons, and repaints a live preview of any of the four pages as you type.
  • Publishing goes through a small serverless function; in the demo it writes nothing.
Open the editor (demo) ↗
Build notes

The decisions behind it

01

Film grammar, not stock photos

A leader, a slate, a timecode and end credits carry the feeling. A photograph of two strangers would have killed it.

02

No media files at all

Grain, bokeh, leak and grade are drawn by the browser, so it opens instantly on a phone on bad signal.

03

Written, not coded

The words live in a JSON file with an editor over them — the film stays, the couple changes.

Need one of these for real?

Tell me what it is for and who it is going to. I will tell you what it costs and how long it takes — no charge for the conversation.

WhatsApp