Platen

Set your address. Pull the press.

Fig. 1 — Platen, live captureOpen the live demo ↗12 s loop · recorded frame by frame on GPU

Field notes

A newsletter sign-up that is a tabletop letterpress. Your email sets in lead type, backwards as type does; pull the lever and the roller inks it, the platen closes, and your address comes out printed. How hard you pull is how deep it bites.

  • 3D
  • Pointer interaction
  • Dark theme

Platen is the sign-up page of Halfmeasure, a fictional fortnightly letter about building small software. On the left, the pitch is printed on a cream broadside with a red wood-type masthead. On the right stands a clamshell press in a dark print shop. Type your email and each character drops into the bed as a lead sort, mirrored, the way real type reads. Drag the lever down: the roller inks the line, the platen shuts, and when it opens your address is printed on the sheet in the ink you picked, black, vermilion or blue. Stop short and the sheet never touches the type; pull lightly for a faint kiss impression, all the way for a deep bite.

There is no canvas: the press is HTML under CSS 3D transforms, and the form is a real email field with three ink radios and a lever button. The platen stays shut while your server answers, so the wait is the press holding down, not a spinner. One file, subscribe.ts, is the seam for your backend; the demo sends nothing and says so, and an address ending in @fail.test shows the failed print, with the type still set to pull again. A 12-second tour sets an address, prints it in vermilion and lifts the type out; reduced motion cuts to each end state. Every word lives in copy.ts.

How it's built

  • One number drives the lever and the platen: the platen closes over the first 70% of the lever's travel, and whatever you pull past that is pressure. The depth sets the print's opacity, its deboss and, below 0.3, an SVG filter that cuts patchy holes.
  • Ink first: the platen cannot close past 40 degrees while the roller is still on the bed, so a fast drag never shuts it on the roller. It catches up once the roller has cleared.
  • The request starts on contact and the platen holds down until the reply arrives, so the wait is part of the machine. A failed reply still opens the press, with the sheet slipped and the type left inked to pull again.
  • The type is laid out from the font's real advances, measured once the fonts are in, and mirrored as one line, so the roller meets the last letter first. A deleted sort pops back out at its own size; the line is a zero-width anchor, so the rest recentre without dragging it along.
  • One frame from one clock: the state keeps when the type was set, the pull started, the lever was let go and the server answered, never how far along anything is. The tour sets, prints and lifts the type, so second 12 equals second 0.

Inside the prompt

Every file below is written out in full, so your agent creates the project exactly — no guessing, no missing pieces.

platen-newsletter/
├─ .gitignore
├─ check.ts
├─ index.html
├─ package.json
├─ tsconfig.json
├─ vite.config.ts
└─ src/
   ├─ App.tsx
   ├─ index.css
   ├─ main.tsx
   ├─ vite-env.d.ts
   ├─ components/
   │  ├─ Broadside.tsx
   │  ├─ Press.tsx
   │  └─ Slip.tsx
   └─ lib/
      ├─ copy.ts
      ├─ layout.ts
      ├─ live.ts
      ├─ loop.ts
      ├─ pose.ts
      ├─ subscribe.ts
      ├─ time.ts
      └─ timeline.ts

Recut it

  • Replace the newsletter's name, pitch, back issues and every stringsrc/lib/copy.ts + index.html → PRODUCT / BROADSIDE / COPY / <title>
  • Connect your email providersrc/lib/subscribe.ts → subscribe()
  • Change the inks or the tour's addresssrc/lib/copy.ts → INKS / TOUR
  • Retime the roller, the press, the drop or the liftsrc/lib/timeline.ts → ROLL, AUTO, OPEN_DUR, DROP, LIFT
  • Change where the sheet meets the type, or how hard a click pressessrc/lib/timeline.ts → CONTACT, AUTO_DEPTH
  • Change the toursrc/lib/timeline.ts → TOUR_PULL, TOUR_REPLY, TOUR_AGAIN
  • Resize the bed or the type's rangesrc/lib/layout.ts → BED, FS
  • Change the camera angle or the lever's drag lengthsrc/components/Press.tsx → VIEW, DRAG
  • Recolour the shop, the paper and the metal, or change the fontssrc/index.css + index.html → @theme

Also in the vault