smoothly Transition AI-Assisted Code from Sandbox to Production
A working prototype in five minutes is a real thing now. An AI coding partner reads your repo, drops a button, wires a fetch, and you have something on screen before the coffee is cool.
The next step — turning that prototype into something that ships, gets reviewed, and survives next Tuesday's deploy — is where the momentum dies. Not because the model got worse. Because the context didn't.
The five-minute build is real, and so is the five-day cleanup
There are two modes for AI-assisted code, and they look almost identical from the outside. In one, you open a sandbox, type a prompt, and a working app appears. In the other, you open the same sandbox in your real repo, type a slightly different prompt, and the agent hallucinates a router that doesn't match your actual router, regenerates a Button you shipped three months ago, and invents an env-var convention nobody on the team has ever seen.
Both look like "AI wrote code." Only one survives contact with the codebase.
The difference is not the model. Same weights, same prompt format, same context window. The difference is what the agent knew about your repo before it started typing — and what it was allowed to assume after.
Context is the product, not the prompt
Treat the agent's context window like a budget. The model itself is a fixed cost — ~200k tokens of whatever frontier model you point at. The interesting spend is the few thousand tokens of repo-specific guidance that decide whether the output looks like your codebase or a stranger's.
Three things eat that budget badly:
- Unstated conventions. "Where does auth live?" "How do we name route handlers?" "What does the Button component accept?" If the answer isn't on disk in a place the agent reads first, the agent invents one. Then you have two Buttons, both called
Button, neither compatible. - Implicit dependencies. The agent reaches for a library you abandoned in 2024. It scaffolds a layout in a pattern the rest of the app doesn't use. It picks a state-management primitive that's three versions behind. None of this is wrong in isolation. All of it is wrong together.
- One-shot prompts. A prompt that worked in a chat window is not a prompt that works on your repo. It has no assertion that the output matches the convention. It has no canonical example to copy. It has no failure mode documented. The next session, the agent writes the same prompt from scratch and gets a different answer.
The fix for all three is the same: put the answer on disk, in a place the agent reads before it types.
11 production screens. Login, database, payments — all wired.
The SaaS Dashboard Kit ships everything already connected. Nothing to set up. Live demo at saas.otf-kit.dev.
The file-system contract
A coding agent pointed at a repo will read a small set of well-known files before doing anything else. The names vary by tool — the convention is the contract, not the filename — but the shape is identical:
- One root-level guidance file that says what this repo is, how to extend it, and what not to do.
- One tool-specific rules file that the agent loads automatically when you start a session.
- A folder of tested prompts that ship a specific pattern, with the example output committed alongside.
Here is what the root file looks like in a codebase that ships:
# This repo
A cross-platform app: web, iOS, Android — one codebase, one component name everywhere.
## How to extend, not regenerate
Before adding a new component, search for an existing one. Before adding a route, look at `src/routes/` for the canonical shape. Before adding a DB column, check `db/schema.ts` for the migration pattern.
## Conventions that are not optional
- Components live in `src/ui/<Name>.tsx`. Same name on web, iOS, Android.
- Tokens live in `src/ui/tokens.ts`. One flip, all platforms.
- Route handlers live in `src/routes/<domain>.ts`.
- Tests live next to the thing they test. No `__tests__` mirror tree.
## What not to do
- Do not scaffold a new UI library.
- Do not add a new auth middleware. Use the wrapper already in `src/auth/`.
- Do not introduce a new state library. Use the one already wired.
- Do not regenerate the Button. It exists. Read it.That file is not documentation. It is the contract the agent reads first. Every "do not" in it is a bug you prevented at the cost of three lines of markdown.
Tested prompts are the second layer
The root guidance file tells the agent what the codebase is. Tested prompts tell it how to do a specific thing in this codebase, with a known-good output to copy from. The pattern is small enough to fit on a screen:
# Prompt: add a Stripe webhook
## Goal
Add a webhook handler for `invoice.payment_succeeded` that credits the
user's account and writes an audit row.
## Preconditions
- Stripe keys in `.env.local`
- `db/schema.ts` has `invoices` and `credit_ledger`
- Existing handler in `src/actions/billing.ts`
## Steps
1. Read `src/actions/billing.ts` and copy its shape.
2. Add `handleInvoicePaid` next to the existing handlers.
3. Use the existing `withAuth` wrapper, not a new middleware.
4. Add the audit row with `db.insert(audit).values(...)`.
5. Update the test fixture in `tests/billing.test.ts`.
## Done looks like
- Handler exports `handleInvoicePaid(event: Stripe.Event)`.
- Returns `200` on success, `400` on bad signature.
- Test passes with `pnpm test billing`.
## What NOT to do
- Do not add a new webhook secret. Reuse `STRIPE_WEBHOOK_SECRET`.
- Do not call Stripe back from inside the handler.
- Do not write to the DB outside a transaction.That prompt, committed at ai/prompts/add-stripe-webhook.md, runs the same way every time. The agent reads it, follows the steps, and ships a handler that matches the rest of the billing module — not a new module that happens to compile. The next time someone on your team needs the same thing, they don't write a fresh prompt. They run the one that already worked.
The "Done looks like" section is the part that does the real work. It is an assertion the human can verify in a code review. Without it, "the prompt worked" is unverifiable; with it, "the prompt worked" means a specific file exists with a specific shape.
Extending, not regenerating
This is the part that actually moves the needle. A coding agent that knows your conventions doesn't add code — it extends an existing surface. A new screen reuses the layout shell. A new column reuses the migration pattern. A new webhook reuses the auth wrapper.
The codebase grows by accretion, not by demolition. You don't end the week with three competing Button implementations because the agent never thought of writing the first one.

The two paths look identical at ten lines. At a thousand, one is a codebase you can hand to the next engineer. The other is a codebase that needs to be rewritten before anyone can read it.
How to put this in place today
If you are starting from scratch, the order matters:
-
Write the root guidance file first. Even if it is a stub. The agent will read it on the first session and behave differently because of it.
-
Add the tool-specific rules file. One for each agent your team uses —
.cursorrulesfor Cursor, aCLAUDE.mdreferenced by Claude Code, and so on. Keep them in sync. Divergence is worse than absence. -
Pick three high-frequency tasks. "Add a webhook." "Add a screen." "Add a column." Write a tested prompt for each. Commit them next to the code they touch.
-
Wire the prompts into the agent's discovery path. Most agents pick up
ai/prompts/if you mention it in the root file. Reference it explicitly:## Prompts Before doing anything non-trivial, check `ai/prompts/` for a tested pattern. If one matches, follow it. If none matches, write one before you commit. -
Treat the prompts as code. Review them in PRs. Update them when the convention changes. Delete them when the pattern is replaced.
The whole investment is one afternoon for the root file, another afternoon for the first three prompts. The payoff is a coding partner that gets measurably better over the next quarter — not because the model got smarter, but because the contract on disk got sharper.
What this gets you
The honest version: it gets you a coding partner that improves as the codebase does. The same prompt, run six months later, still produces the same shape of output. The same agent, asked to add a new feature, picks up the existing pattern instead of inventing a new one. The next engineer who joins the team reads CLAUDE.md and ai/prompts/ and understands the codebase in an afternoon — because the agent's instructions to itself are also documentation for the humans.
The more durable version: it gets you a codebase that survives model churn. When the next model ships and the old one gets deprioritized, the contract on disk does not change. The agent reads the same files, follows the same prompts, and ships the same shape of code. The model is the variable you swap. The conventions are the constant.
Both versions are true. The second one is the more useful one to plan around.
The part underneath the churn
The model layer is going to keep changing. Faster, slower, cheaper, smarter — the shape of the next twelve months is a parade of releases, and each one will look like a productivity enable for about a week.
The layer that doesn't change is the contract on disk. The CLAUDE.md that says "this is how we name things." The .cursorrules that says "this is the auth pattern." The ai/prompts/add-stripe-webhook.md that ships the same handler every time.
That is the part worth investing in. Not because the model is bad — the model is genuinely good right now — but because the model is a variable, and variables are cheap. The constants are what compound.
OTF kits ship with that contract already written. Every full-stack kit — SaaS Dashboard, Fitness, Booking — includes a CLAUDE.md, a .cursorrules, and a folder of tested prompts at ai/prompts/, wired into the discovery path so any of the major coding agents picks them up on first contact. The idea is the same as the rest of the kit: the work you do once is the work nobody has to redo. When the model ships next month's release, your codebase doesn't notice, because the agent that extends it is reading the same file it read last month.
Ship the product, not the setup.
- 11 production screens — auth, billing, team, analytics, settings
- Real database, payments, and login — all wired on day 1
- AI configs pre-tuned so your agent extends instead of regenerates