Shipping a Real Product in 24 Hours
Why I still build products against a one-day clock, and the habits that make it work: cutting scope hard, using the same stack every time, letting agents do the heavy lifting, leaning on a design system, and agreeing on what 'done' means before I start.
8 min read
Earlier this month I started a new product at 9:14 on a Thursday night. By 6:03 the next evening it had a working core loop, a real database, authentication, a calm interface, and a setup script that a new engineer could run with one command. That's about 21 hours from the first commit to the last commit of that push.
It was a governance runtime. It sits between what a company says it does and what it actually does, and it records a tamper-evident receipt for every decision. That isn't a toy problem. Alongside the code there's a decision dossier that explains why the product is shaped the way it is.
I don't do this to show off. A one-day build is the best way I know to find out whether an idea is real, and it keeps me honest about how I work for the rest of the year. Here's why it matters, and how I actually do it.
Why speed is a design tool#
Most ideas don't die because they're bad. They die because they spend months as slides, and by the time anyone touches them, the energy is gone. A working product changes the conversation. People stop debating the idea and start reacting to the thing.
Speed also flushes out assumptions. In the first few hours of any build I usually find out that the hard part isn't where I expected. The governance runtime is a good example. I assumed the interface would be the work. It turned out the real problem was concurrency: queues, a ledger, timeout sweeps and webhook fan-out all lived on the server. That one finding shaped the whole product, and it led to a clear rule in the dossier: don't add a client-side cache to solve a problem the product doesn't have.
The third reason is personal. When you know you can ship something real in a day, you stop being afraid of starting. That changes how you lead, too. You stop asking a team "how long will this take" and start asking "what is the smallest true version of this."
What speed isn't is permission to be sloppy. A 24-hour build that leaks secrets, skips auth or fakes its data teaches you nothing. I hold the core to production standards, keep it small, and leave everything else out.
Decide what "done" means before you write a line#
Every fast build I've seen go wrong went wrong here. Someone started coding and only later decided what they were trying to prove.
Before I open an editor, I write three things down:
- The one loop that has to work. For the governance runtime, that was: a request comes in, a policy decides, the decision is recorded with proof, and a human can see it. If that loop works end to end, the build is a success. If it doesn't, nothing else matters.
- What I'm explicitly not building. I write this as a list, because a list is harder to quietly ignore. Billing, team management, settings pages, marketing pages, an admin console. They all go on it.
- The demo sentence. One sentence I could say while showing the screen. If I can't say it, I don't understand the product yet.
"Done" means the loop runs against real infrastructure, a second person could set it up without me, and the demo sentence is true. It doesn't mean feature complete, and it doesn't mean pretty everywhere. It means honest.
Scope cuts that actually work#
Cutting scope sounds easy until you're three hours in and a nice feature is right there. These are the cuts I make every time:
- One user type. Roles and permissions come later. Build for the person who feels the pain most.
- One happy path, with real error handling on it. I don't build five flows half way. I build one flow all the way, including what happens when it fails.
- Seeded data instead of import tools. A script that loads realistic sample data is an hour of work. An import wizard is a week.
- No settings. Every setting is a decision you haven't made yet. Make it, hard-code it, and write it down.
- No notifications. If the loop needs a human, show it on the screen they're already looking at.
- Fake nothing in the core loop. You can fake everything around it.
The last one is the rule that keeps a fast build from becoming a demo. Mock the edges and keep the middle real.
Stack defaults: stop choosing#
A one-day build has no time for a framework debate. I use the same defaults every time, so the only new thing in the project is the product itself.
Right now that means:
- Next.js with the App Router and TypeScript for the app and its API routes.
- Tailwind for styling, with a small set of design tokens set on day one.
- Postgres, accessed through a typed ORM, with migrations from the first hour.
- A hosted auth provider, so I never write a login form under time pressure.
- Secrets in a real secret manager, pulled by a setup script, never pasted into a file.
- One setup command that installs, authenticates, starts the database, migrates and boots the app.
That last item gets underrated. On the governance runtime, the README tells a new engineer to run one command. It installs dependencies, opens a browser to authenticate for secrets, starts Postgres, runs migrations, and optionally boots the app. Writing it took less time than explaining the setup to one person would have. It's also the first thing an agent needs if it's going to help.
These defaults aren't the best possible stack. They're the stack I don't have to think about. That's the point.
Agents do the volume, I do the judgment#
This is the part that has changed most in the last two years. When I started doing fast builds, the bottleneck was typing. Now it's deciding.
My split looks like this:
- I write the plan and the contract. The loop, the data model, the not-building list, and the acceptance checks. Agents are only as good as what they're handed, so this is where my hours go.
- Agents write the volume. CRUD routes, migrations, form screens, test scaffolds and the README draft. That work is well understood and easy to check.
- Deterministic checks gate everything. Type checks, lint, tests and a secret scan run on every change. When an agent's change fails a check, it goes back with the failure attached. It doesn't get waved through.
- I review the seams. Auth boundaries, data access and anything that touches money or proof. Those parts I read line by line.
I wrote about the loop behind this in The Agent Loop That Ships Its Own Code. The short version: agents make speed cheap, but they don't make judgment cheap. A fast build with agents is still a build where one person decides what matters.
The design system is the shortcut#
The fastest way to make a one-day product feel considered is to not design it from scratch.
I start every build with a short design brief and a token set. For the governance runtime the brief was one line: a calm, high-legibility interface where proof is the hero. One warm coral accent means "go," and a reserved set of semantic colors makes every verdict unmistakable. That sentence answered dozens of small decisions before they came up.
From there:
- Tokens first. Color, type scale, spacing and radius go into the theme in the first hour. Nothing gets a one-off value.
- Primitives from a library. Buttons, inputs, dialogs and tables come from a component kit I already trust. I restyle them. I don't rebuild them.
- Two page templates. A list view and a detail view cover most of a young product.
- States before screens. Empty, loading, error and success get designed for the core loop. They're what make a product feel real.
A design system isn't paperwork you produce after a product succeeds. In a fast build it's the thing that lets one person ship an interface that looks like a team made it.
How I run the 24 hours#
The exact shape changes with the product, but the rhythm is steady:
- Hours 0 to 2: write it down. The loop, the not-building list, the demo sentence, the data model and the design brief.
- Hours 2 to 4: the skeleton. Repo, setup script, auth, database, tokens and an empty shell deployed somewhere real. Deploying early is non-negotiable. If deployment is going to hurt, I want to know at hour four, not hour twenty.
- Hours 4 to 14: the loop. Build the core loop end to end, ugly first, then make it correct. Agents handle the volume while I keep the seams honest.
- Hours 14 to 18: the states. Empty, error and loading states, seed data, and the one screen a person sees first.
- Hours 18 to 22: the proof. A clean setup from scratch on a fresh machine, the tests that protect the loop, and the README.
- Last hours: write the decisions down. What I chose, what I rejected, and why.
I also sleep. A tired build makes more mess than it saves.
What "done" looked like#
At the end of the governance build I could open the app, send a request through a policy, watch it get decided, and open the receipt that proved what happened. A new engineer could clone the repo and get there with one command. The decision dossier explained why the system fails closed and captures evidence before it acts, so the next person wouldn't undo those choices by accident.
A lot was still missing. Most of it was on the not-building list, which meant it was missing on purpose.
The lessons that carry over#
Fast builds have changed how I run long ones:
- Write the not-building list on every project. It's the cheapest scope control there is.
- Make setup one command. For people and for agents.
- Deploy on day one. Every week a project goes without a real deploy, the first deploy gets harder.
- Hold the core to production standards and let the edges be rough. Teams usually do the opposite: they polish the edges and leave the core fragile.
- Write decisions down while they're fresh. The dossier from a one-day build is often worth more than the code.
The takeaway#
Shipping in 24 hours isn't about heroics. It's about removing every decision that doesn't matter, so the few that do get your full attention. Agents and a good design system make that far more possible than it used to be. What they can't do is decide what the product is. That part is still the job, and it's the part I enjoy most.
Related
- Engineering
Nothing Goes Live Because It Exists
In my agent rig, prompts, routes, skills and even fine-tuned models all start in shadow. Promotion is a separate, evidence-backed step that a person takes. Here's the lifecycle, and why it matters more as the number of moving parts grows.
Agents · AI · Local LLMs · Delivery6 min read
- Engineering
The Art of the Rock Tumbler: Polishing Loops for Code and Agents
A rock tumbler doesn't make a stone smooth in one pass. It uses coarse grit, then finer grit, then polish, and checks between stages. That's how I build agent loops in Starship: bounded retries, deterministic gates, and lessons that are only allowed to hurt once.
Agents · AI · Architecture · Delivery7 min read
- Engineering
The Agent Loop That Ships Its Own Code
How Starship's coding agents go from a planned task to a merged pull request without a human driving each step, and the gates, retries and postmortems that make that safe to leave running.
AI · Agents · Architecture · Delivery6 min read