From one sentence to a build-ready spec: a worked example (ShopStock)
Most PRD generators hand you a document. The document is fine. Then your coding agent builds the database anyway — and three days later the tables don't match the document, the API payloads changed shape twice, and nobod
Most PRD generators hand you a document. The document is fine. Then your coding agent builds the database anyway — and three days later the tables don't match the document, the API payloads changed shape twice, and nobody wrote the security rules down.
I wanted to see what the output looks like when the spec, the schema, the contracts and the agent rules are generated together and actually agree with each other. So here is one full worked example, end to end. The product is fictional — a stock list app for small shop owners in Bangladesh — but every excerpt below is from the real sample suite that ships with the generator's free template.
The input: one sentence
A stock list app for small shop owners in Bangladesh that replaces the paper stock notebook, works offline-first on cheap Android phones, and understands products by name, not codes.
That's it. That is the whole brief.
File 1: PRODUCT_REQUIREMENTS.md — the PRD
The PRD turns that sentence into decisions a builder can test. It names the problem with evidence marked as what it is — the sample is honest that its interview numbers are example data:
Problem: shop owners track stock in paper notebooks; when a notebook is lost or a helper sells from memory, stock counts drift and reordering is guesswork.
Evidence (example data): 6 of 8 owners interviewed said they discovered a stock-out only when a customer asked.
Then goals with a measure attached ("Owners trust the count — weekly count-vs-app spot checks that match — 90% match by week 4"), two roles with a hard boundary (staff can record sales and stock-in, but must never change prices or delete products; an owner must never see another shop's data), and numbered requirements, each with an acceptance check:
- FR-1 — create a product with name and stock count. Check: create "Rice 5kg, stock 20" → appears in list with stock 20.
- FR-2 — stock decreases when a sale is recorded. Check: record sale of 2 → stock 20 becomes 18.
- FR-3 — a sale larger than current stock is prevented. Check: try to sell 25 of 18 → blocked with a clear message.
- FR-4 — staff cannot change prices. Check: in a staff session the price field is not editable.
Edge cases are written down before code exists: stock hitting exactly 0 (shows "Out of stock", stays visible), two staff selling the same product at the same time (counts must not go negative; the second sale is re-checked against the fresh count), and a new user with no products (one clear action — "Add your first product").
File 2: UI_UX_SPECIFICATION.md — the screens
The PRD says what must happen; the UI spec says what the user sees. The product list, the sale flow, the offline "not yet synced" state from Journey 1, the out-of-stock state, the empty state — each screen with its states and what each button does, so the agent doesn't invent a layout that contradicts the requirements. (The full spec is in the sample suite linked below.)
File 3: TECHNICAL_ARCHITECTURE.md — schema + API contracts
This is the file a prose PRD never produces, and the one that matters most. Four tables:
create table public.shops ( ... );
create table public.shop_members ( ... );
create table public.products ( ... );
create table public.stock_movements ( ... );
Multi-tenancy is in the schema on day one, not patched later. Row Level Security is enabled on every table, and every policy uses the same helper rule — "the current user is a member of the shop this row belongs to":
create policy "members manage their shop products"
on public.products for all
using (exists (select 1 from public.shop_members m
where m.shop_id = products.shop_id and m.user_id = auth.uid()))
with check (exists (select 1 from public.shop_members m
where m.shop_id = products.shop_id and m.user_id = auth.uid()));
The API contracts are agreed before code exists, and each one points back to the requirement it implements:
POST /api/products — create a product (FR-1)
Auth: shop member (owner or staff); price changes: owner only (FR-4)
Request: { shopId: uuid, name: string (1–120), price: number ≥ 0, stock: integer ≥ 0 }
Success: 201 → { id, shopId, name, price, stock, createdAt }
Errors: 403 → not a member of this shop · 422 → validation failed
const CreateProduct = z.object({
shopId: z.string().uuid(),
name: z.string().min(1).max(120),
price: z.number().nonnegative(),
stock: z.number().int().nonnegative(),
});
POST /api/sales — record a sale (FR-2, FR-3)
Request: { productId: uuid, quantity: integer ≥ 1 }
Success: 200 → { productId, newStock }
Errors: 409 → quantity exceeds current stock (stock is never allowed to go negative)
Note what the 409 does: the "never go negative" rule from FR-3 lives in the contract, not just in prose. And the list endpoint says explicitly that RLS enforces the same rule at the database layer — the API and the schema are saying the same thing.
File 4: AI_AGENT_IMPLEMENTATION.md — the rules for Cursor / Claude Code
The last file is the one you paste into .cursor/rules or CLAUDE.md. The sample's rules are short and strict:
- Build only what the PRD requires (FR-1…FR-4). If a requirement is unclear, stop and ask — do not invent behaviour.
- Use the table and column names in the schema exactly (
shops,shop_members,products,stock_movements). Never invent a column or relationship. - Use the request/response shapes in the contracts exactly. Never change a payload without updating that file first and saying so.
- Row Level Security is the security boundary: never bypass it, and never use the service-role key in a user-facing endpoint.
- Stock must never go negative. Enforce it in the database check constraint and return the contract's 409 error from the sales endpoint.
- FR-4 is a hard rule: staff sessions must not be able to change prices — hide the field in the UI and reject it in the API.
- After building each requirement, run its acceptance check from the PRD and report the result before moving on.
- If the PRD, schema and contracts disagree, report the conflict instead of choosing silently.
Rule 8 is the one I care about most. A coding agent that invents a table name is a bug you find in week two. An agent that quietly picks one side of a contradiction is a bug you find in production.
The check you can run yourself
Before handing any generated suite to an agent, run this agreement test — it takes two minutes:
- Every table name in the agent rules appears in the schema, spelled the same way.
- Every endpoint's request shape matches a Zod schema, and every Zod field matches a column.
- Every "must never" in the PRD (staff can't change prices, owners can't see other shops) appears twice: once in the UI spec, once enforced in the schema or the contract.
- Every requirement has an acceptance check you could run by hand — "sell 2, stock 20 becomes 18" — not "works correctly".
If a suite passes that test, the agent has very little room to improvise. If it fails, fix the spec, not the code.
Try it
The full ShopStock sample suite — all four files — is free in the template repo: https://github.com/web-dev-mehedi/ai-prd-template
And the generator that produced this shape of output is live, with 50 free credits on signup and plans from ৳99/month (bKash/Nagad): https://webdevmehedi.com/ai-prd-generator
What do you hand your coding agent before a build — a document, or a contract? Genuinely curious what other people's specs look like.
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.