Skip to content
← stanwood.dev
A wall clock above a developer's desk with code on screen

Ship Clock

stanwood.dev · production deploy tracker

One number on the wall. Days since this site last shipped — no spin, no excuses. Updates every five minutes from Vercel.

...
loading mission data

The Cadence Ladder

how to read your number · five tiers

0d
shipped today 🚀

In the zone. Daily-driver project — every day is a build day.

1–3d
fresh off the line

Active development. Healthy side-project rhythm — most indie shippers live here.

4–6d
clock is ticking

Between sprints. Not bad — but block out a shipping day before momentum slips.

1–2w
getting rusty

Probably waiting on a decision or a review. A typo fix or version bump resets the clock — momentum compounds.

14d+
dust is collecting

Abandonment risk. Even a README polish counts — ship something, anything, today.

Status labels match the counter above. The 28-day grid shows your real cadence — gaps speak louder than the headline number.

What the Number Means

useful pressure · not a scoreboard

The clock is a tiny version of deployment frequency: how often finished work reaches production. It is helpful because it keeps momentum visible, but it only works when the shipped units stay small.

Small counts scope

A copy fix, cleanup, or narrow feature can be a real ship. The clock rewards finishing, not ceremony.

Fast needs boring process

Short PRs, easy rollback, and feature flags matter more than heroic release days. The less drama around deploys, the more often they can happen.

Quality still wins judgment

A lower number is not worth a broken page. The good version is frequent, boring, reversible progress.

When the clock is high

five common reasons · the smallest move that resets it

01 scope keeps growing

The PR has been open for days. Every fix uncovers another. You can't ship until the whole thing is right.

fixCut a tracer-bullet — the smallest slice that proves the path. Stub the rest behind a feature flag, deploy, then layer in. Shipping a quarter beats sitting on the whole.

02 waiting on a review

PR's been sitting for two days. The reviewer's busy. You're blocked on the main work.

fixShip a side fix — a typo, a README polish, a dep bump. The clock resets while the big PR waits, and you stay in the habit.

03 spread too thin

Three projects, all half-done. You context-switch every hour. Nothing crosses the finish line.

fixPick one for the day and ignore the rest. A 10-line PR on the chosen project counts. Tomorrow you can switch — but ship one thing today.

04 it's not ready yet

Works locally, but the copy isn't right, the empty state's ugly, and you found one more edge case. So the branch sits another night.

fixShip behind a flag. Out the door, off by default — production-shaped feedback beats local polish, and the clock thanks you.

05 old code in the way

You can't add the new thing because the old thing is tangled. You keep planning the rewrite. Nothing ships.

fixShip a deletion. Removing dead code is a deploy too — same green tick, same clock reset. Subtraction is shipping.

The pattern across all five: the move that unsticks you is smaller than you think. Whatever lands today wins.

Build Your Own

three steps · ~30 minutes

01

Create a Vercel read token

In Vercel → Account Settings → Tokens, create a scoped read token. Grab your Project ID from the project settings URL.

02

Call the deployments API

One fetch pulls the last 25 production deploys with commit metadata attached. The rest is arithmetic.

03

Mount a counter component

Compute daysSince from deployments[0].created and display it. Poll every 5 minutes with a setInterval or use stale-while-revalidate caching.

// GET /api/ship-clock const url = `https://api.vercel.com/v6/deployments ?projectId=${VERCEL_PROJECT_ID} &target=production&limit=25&state=READY`; const res = await fetch(url, { headers: { Authorization: `Bearer ${VERCEL_TOKEN}` } }); const { deployments } = await res.json(); const lastDeploy = new Date(deployments[0].created); const daysSince = Math.floor( (Date.now() - lastDeploy.getTime()) / 86400000 );

Works with any Vercel project. Swap in GitHub Actions or Fly.io by adapting the deployment source.
Commit metadata (message, SHA, PR number) lives in deployments[0].meta.