Product
Why fromSpec: the case for deterministic product architecture
Prompt-to-code tools optimize for one moment: the first demo. fromSpec optimizes for the codebase you maintain after, by making a structured spec the thing you build from and code a compiled artifact of it.

You type a paragraph, a few seconds pass, and something runs. It feels like magic right up until you need to change it. Then you discover that the model invented its own data model, scattered business logic across components, and left you a diff you can't review and can't reproduce. Ask for one more feature and it rewrites half the app. The second hour with these tools rarely feels like the first.
fromSpec starts from a different premise: the thing worth generating isn't code, it's a specification. Code is downstream. If the spec is structured, reviewed, and version-controlled, the code becomes a compiled artifact of it: predictable, regenerable, and yours to own. This post is about what "deterministic" actually means in that sentence, and why it changes the economics of building with an LLM.
The prompt-to-code trap
The failure mode of prompt-to-code isn't that the output is bad. It's that the output is unconstrained. A free-form prompt gives the model latitude over everything at once: entities, routes, UI, naming, file layout. Each regeneration is a fresh roll of the dice, so:
- You can't review it. There's no artifact between your intent and 80 generated files. The design doc lives in a chat log.
- You can't reproduce it. Run the same prompt twice, get two different architectures.
- You pay for throwaway work. Every open-ended generation burns tokens producing code you'll discard on the next iteration. The cost is unbounded because the scope is unbounded.
- It drifts. The gap between what you meant and what got built widens with every prompt, because nothing pins the requirements down.
These aren't model-quality problems that a better model fixes. They're structure problems. The way out isn't a smarter prompt. It's a constrained pipeline.
What "deterministic" means here
fromSpec runs a fixed sequence of stages: spec, architecture, preview, code. Each stage takes the previous stage's approved output as its input and produces a scoped, inspectable artifact. The model is never asked to do everything at once. It's asked to do one well-defined transformation at a time, against a known input.
Determinism here doesn't mean the LLM is a pure function. Models are stochastic. It means the process is deterministic: the same approved spec drives the same architecture, the same architecture drives a preview that faithfully reflects it, and code is generated from artifacts you've already seen and signed off on. The randomness is fenced into each stage and resolved by a human checkpoint before it can compound into the next.
That fence is the whole point. In an open-ended tool, uncertainty at stage N feeds uncertainty at stage N+1 and the errors multiply. In a staged pipeline, uncertainty is contained, surfaced, and resolved before it propagates.
The spec is what you edit
Everything hangs off a structured spec, spec.json. It holds entities and their fields, use cases, flows, and branding. It's AI-suggested but human-edited, and it's versioned: a draft you shape, then a locked snapshot you build from. When you want to change the product, you change the spec. Code is never the thing you edit to redefine the system. It's the thing the system compiles to.
{
"app": "tempo",
"entities": {
"Employee": ["name", "email", "manager"],
"LeaveRequest": ["type", "from", "to", "status"]
},
"useCases": ["request_time_off", "approve_request"],
"flows": ["request_form", "approvals_queue"],
"brand": { "primary": "#1A56DB" }
}
This inversion is what makes everything downstream sane. Because the spec is explicit and diffable, a feature change is a spec change you can read in seconds, not a 60-file code diff you have to reverse-engineer. Because it's versioned, you have a real history of how the product was defined, not a chat transcript. And because it's the single input to generation, regenerating is safe: you're recompiling from an artifact you reviewed, not gambling on a new prompt.
Architecture before preview, on purpose
The stage order is deliberate, and the part people find surprising is that architecture comes before the preview.
Once the spec is locked, fromSpec derives the architecture from it: the data model, entity relationships, and the API surface. Only then does it generate the interactive preview. The reason is fidelity. A prototype rendered before the data model exists is just decoration: pretty screens with no relationship to what the code will actually do. A prototype rendered from a real ER model and route map is a faithful proxy. The forms map to real entities, the navigation maps to real flows. When you approve that preview, you're approving something the generated code will actually match.
So the pipeline reads: lock what (spec), derive how (architecture), see it (preview), build it (code). Each stage narrows the space the next one operates in.
Human checkpoints where they count
Determinism and automation are not the same thing, and fromSpec is deliberately not autonomous. You approve the spec before anything is derived from it. You approve the preview before a line of application code is generated. Nothing advances on its own. The model proposes, you decide. The checkpoints sit exactly where a wrong assumption is cheap to fix (a spec edit) instead of where it's expensive (a rewrite).
This is the opposite of the agent that runs for twenty minutes and hands you a surprise. The surprises are front-loaded into artifacts you can read.
Code as a compiled artifact
When generation runs, you get a real project in a real stack: FastAPI, React (Vite), and PostgreSQL, or Next.js, with database models, API routes, frontend pages, and capability modules (auth, payments, email) wired in. Architecture, ER, and API documentation are available alongside it, and the project ships with Docker and CI/CD scaffolding so docker compose up gives you a running app. You can push the generated code straight to your own GitHub repo.
There's no runtime dependency on fromSpec. The output is a normal codebase you own and maintain. fromSpec compiled it. It doesn't host it, gate it, or sit in its request path. If you walked away tomorrow, your app would keep running.
What determinism buys you
Three things:
- Reviewability. The unit of review is a structured spec and an architecture you can read, not an opaque code dump. Stakeholders align on the spec before money is spent on code.
- Predictable cost. Generation is scoped per stage against a fixed input, so you're not paying for open-ended regeneration loops. The spend tracks the work, not the model's mood.
- Less drift, safer iteration. Requirements are pinned in the spec before code exists, and you iterate by editing the spec and regenerating from it, not by re-prompting and hoping the model preserves what you liked.
Prompt-to-code asks the model to be an oracle. fromSpec asks it to be a compiler stage. Oracles are exciting in the demo and exhausting in the maintenance window. A compiler is boring, and boring is exactly what you want standing between an idea and the code you'll live with.