Build a Simple E-commerce MVP with AI: A Step-by-Step Guide
If you've ever typed "build me an e-commerce app" into an AI tool, you know how it goes. You get something that runs, but it's not what you pictured. The login works differently than you wanted, the checkout has steps yo
If you've ever typed "build me an e-commerce app" into an AI tool, you know how it goes. You get something that runs, but it's not what you pictured. The login works differently than you wanted, the checkout has steps you never asked for, and half the buttons look like they came from different apps.
The problem isn't the AI. It's that you left it hundreds of decisions to guess at.
What worked for me was changing the order of things. I stopped asking for code first. Instead I ask Claude to help me write five short documents, answer its questions, and only then hand everything to Claude Code to build. The code ends up being the easy part.
This post walks through the whole process with the exact prompts I use. The stack here is Angular on the front end and ASP.NET Core on the back end, but the method works with any stack. I'll use a made-up store called QuickCart as the example. Swap in your own idea and it works the same way.
The example: QuickCart
Nothing fancy, on purpose:
- Two roles: a customer and a store owner
- The owner manages products. Customers browse, search, add to cart and check out
- Payment is cash on delivery only, so no payment gateway to set up
- Orders go Placed, Confirmed, Shipped, Delivered, and the customer can follow along
The plan
- Write a PRD (what we're building, and what we're not)
- Write a screen flow (every screen and journey)
- Lock the tech stack to exact versions
- Write a design system, and preview it as an HTML mockup
- Design the database schema and API
- Make an implementation plan and a
CLAUDE.md - Set up your accounts and local environment (this part is on you)
- Build with Claude Code
- Have separate review agents check the work
- Write a UAT plan and deploy
Before you start
You'll need a Claude account and Claude Code installed. On your machine, install the .NET SDK, Node.js (for the Angular CLI), and PostgreSQL (or have a hosted dev database ready). Make a project folder with a docs/ directory inside. Every document Claude writes goes there as a .md file, because Claude Code reads Markdown without any fuss.
The trick I use in every prompt
Every prompt below ends with some version of this:
Before writing anything, ask me every question you need answered.
For each question, propose a default answer so I can approve quickly.
Do not assume anything.
This is the single most useful habit I've picked up. Claude comes back with a numbered list of questions, each with a sensible default. You say "defaults for everything except number 3" and you're done in a minute. Here's what that looks like for the PRD:
Q1. Can guests check out without an account?
Default: No. Login (email) is required to place an order.
Q2. Can customers cancel an order?
Default: Yes, only while the status is Placed.
Q3. Is there one delivery fee or many?
Default: One flat fee, set by the owner.
Q4. Which currency and tax handling?
Default: Single currency, prices tax-inclusive.
Without this step, those answers still get decided. The AI just decides them quietly, and you find out later.
Step 1: The PRD
The PRD says what you're building. Just as important, it says what you're not building. I always list non-goals, because otherwise the AI helpfully adds reviews, coupons and a wishlist you never wanted.
Prompt:
I want to build "QuickCart", a simple online store web app.
Roles: Customer and Store Owner (admin).
- The owner manages products (name, description, price, image,
category, active/inactive).
- Customers browse, search, add to cart, check out and track orders.
- Payment: Cash on Delivery only.
- Order statuses: Placed -> Confirmed -> Shipped -> Delivered,
or Cancelled.
Out of scope: stock tracking, online payments, reviews, coupons,
refunds, multi-vendor.
Prepare a PRD/BRD. Do not include the tech stack or database.
Before writing anything, ask me every question you need answered,
with a default answer for each. Do not assume anything.
Deliverable: prd.md
The result should look something like this:
# QuickCart: Product Requirements Document
Version: 1.0 | Date: <date> | Owner: <you> | Status: Draft
## 1. Executive Summary
QuickCart is a mobile-first web store where customers order
everyday items and pay cash on delivery. One owner manages the
catalogue and fulfils orders.
## 3. Scope
### 3.1 In scope
- Product catalogue management (owner)
- Browse, search, cart, checkout (customer)
- Order lifecycle and customer-visible tracking
### 3.2 Out of scope (v1)
- Stock tracking, online payments, reviews, coupons, refunds
## 5. Functional Requirements
| ID | Requirement | Priority |
|-------|-----------------------------------------------|----------|
| FR-01 | Customer can register and log in with email | Must |
| FR-02 | Customer can add/remove/update cart items | Must |
| FR-03 | Customer can cancel an order while Placed | Should |
| FR-04 | Owner can mark a product inactive (hidden) | Must |
## 6. Acceptance Criteria
FR-03: Given an order in status Placed, when the customer taps
Cancel and confirms, then the status becomes Cancelled.
Read it properly. Changing a requirement now takes ten seconds. Changing it after the app is built takes an afternoon.
Step 2: The screen flow
The PRD tells you what the app does. The screen flow tells you what people actually see: every screen, every empty state, every "what happens if the network drops" moment.
I make Claude interview me again here, this time in four areas.
Using prd.md, create a Screen Flow document: a blueprint of every
screen and end-to-end user journey in the MVP.
Do NOT write the document yet. First interview me, grouped into:
1. Navigation architecture and transitions (primary/secondary nav,
deep links, entry and exit points)
2. State management: empty, error and loading states
3. Page data dependencies (what populates each page, what happens
if data is slow or missing)
4. Edge cases (session timeout, back button, cancel/exit modals)
For every question propose a default based on standard UX best
practice. The final document must be so complete that a first-time
user can navigate without support.
Deliverable: screen-flow.md
A good result gives every screen an ID and spells out its states:
## 1. Global Rules
- Customer: bottom tab bar (Home, Cart, Orders, Account)
- Owner: sidebar (Dashboard, Orders, Products, Account)
- Loading: skeletons for lists, inline spinner on buttons
- Network error: inline retry banner, cached data tagged
"may be outdated"
- Empty state: illustration + one line + a relevant action
- Back button during checkout: Confirm Exit modal
## CUST-04: Cart
Purpose: Review items and proceed to checkout.
Entry points: Cart tab, "Added to cart" toast action.
Data shown: items, quantity steppers, line totals, order total.
States:
- Empty: "Your cart is empty" + [Browse products]
- Loading: skeleton rows
- Error: retry banner, cart kept locally
Exit points: [Checkout] -> CUST-05, [Continue shopping] -> CUST-01
Notes: Inactive products show "No longer available" and block checkout.
Those IDs (CUST-04 and so on) turn out to be handy. You can say "fix CUST-04" later and nobody has to guess which screen you mean.
Step 3: The tech stack
This one gets handed to Claude Code, so there's no room for "latest" or ^1.2.0. Every dependency gets an exact version. It keeps builds reproducible, and it stops the AI from writing code for an API that changed two releases ago.
Create a tech stack document that locks every dependency to an
exact version number. It will be an input document for Claude Code.
Frontend: Angular (standalone components, TypeScript strict mode)
Backend: ASP.NET Core Web API on the current .NET LTS release
Database: PostgreSQL, accessed through Entity Framework Core
Auth: ASP.NET Core Identity with JWT bearer tokens
Hosting: Azure (App Service + Static Web Apps), with AWS as an
alternative
Rules:
- Pin the .NET SDK with global.json and Node/npm in package.json
"engines".
- Do not recommend any library less than 1 year old with fewer
than 10,000 GitHub stars, unless it is the official or
first-party package for a chosen platform.
- Maximise compatibility with Claude Code.
Before finalising, ask me questions with default answers.
Deliverable: tech-stack.md
I added that age and stars rule on purpose. Popular, well-documented libraries are also the ones the AI knows best, so you get fewer weird bugs. Here's the shape of the output:
## 0. Version-check rule
Before scaffolding, verify every version: `npm view <package> version`
for npm packages, `dotnet package search <name> --exact-match` (or
nuget.org) for NuGet packages. If anything differs, STOP and report
it. Never silently substitute a version. Use exact versions in
package.json (no ^ or ~) and exact <PackageReference> versions in
.csproj files.
## 1. Runtime
| Component | Locked version | Notes |
|-----------|----------------|------------------------------------|
| .NET SDK | <exact> | LTS; pinned in global.json |
| Node.js | <exact> | LTS; pinned in package.json engines|
## 2. Frontend
| Package | Locked version | Notes |
|------------------|----------------|------------------------------|
| @angular/core | <exact> | Standalone components |
| @angular/cli | <exact> | Same major as core |
| typescript | <exact> | strict mode on |
| rxjs | <exact> | Matches Angular peer range |
| tailwindcss | <exact> | Design tokens as CSS variables |
## 3. Backend (NuGet)
| Package | Locked version | Notes |
|------------------------------------------|----------------|----------------|
| Microsoft.EntityFrameworkCore | <exact> | Matches .NET |
| Npgsql.EntityFrameworkCore.PostgreSQL | <exact> | PostgreSQL |
| Microsoft.AspNetCore.Identity.EntityFrameworkCore | <exact> | Users/roles |
| Microsoft.AspNetCore.Authentication.JwtBearer | <exact> | JWT auth |
| FluentValidation.AspNetCore | <exact> | Request checks |
| xunit | <exact> | Backend tests |
## 4. Testing
| @playwright/test | <exact> | End-to-end tests |
I left the versions as <exact> because they change all the time. Claude will fill in real ones. Check them yourself with the commands in the document before building.
Step 4: The design system
Skip this and every page ends up slightly different: a different blue here, a different corner radius there. The design system is one document that answers every "how should this look" question in advance, so Claude Code never has to improvise.
I have the PRD, Screen Flow and Tech Stack documents. Create a
Design System and Content Guidelines document for Claude Code to
build every Angular page and component from. Claude Code must not
guess how anything should look or behave.
Cover Light AND Dark mode:
- Visual identity: color palette (primary, neutral, success,
warning, error), tone, direction for a trustworthy store UI
- Typography: heading/body fonts, sizes, weights, line heights
- Information density: comfortable / balanced / dense (recommend one)
- Layout: grid, spacing scale, breakpoints, navigation behaviour
- Border radius, borders, shadows, elevation as design tokens
- Every component with anatomy, dimensions, typography, spacing,
colors, states (default, hover, active, focus, disabled, loading),
accessibility and responsive behaviour: buttons, inputs, selects,
cards, tables, badges, modals, toasts, tabs, pagination, empty,
error and loading states, order-status timeline
- Charts: only where they genuinely help; say where a plain number
or table is clearer
- Loading and feedback rules: when to use skeletons vs spinners
- Explicit DO and DO NOT rules
- How tokens map to the styling approach in the tech stack
Principles: clarity over decoration, familiarity over novelty,
speed over animation.
Review all previous documents and ask me questions first, with
defaults. Do not assume anything.
Deliverable: design-system.md
The detail level is the point. Something like this:
## Color tokens (CSS variables, never inline hex)
| Token | Light | Dark | Usage |
|---------------------|-----------|-----------|-------------------|
| --color-bg | #FFFFFF | #0A0A0A | Page background |
| --color-surface | #FAFAFA | #141414 | Cards, panels |
| --color-border | #E5E5E5 | #2A2A2A | Dividers, borders |
| --color-text | #171717 | #F5F5F5 | Body text |
| --color-accent | #059669 | #10B981 | Primary actions |
## Primary Button
Height 40px | Radius 8px | Padding-x 16px | Font 14px / 500
Icon 16px | Background --color-accent | Text white
Hover: --color-accent-hover | Active: --color-accent-active
Focus: 2px ring, 2px offset | Disabled: 50% opacity, no pointer
Loading: spinner replaces icon, label stays, width unchanged
## DO NOT
- Introduce colors or spacing values that are not tokens
- Use color alone to show status (always add a label or icon)
- Create one-off component styles for a single page
See it before you build it
Once the document exists, I ask for a throwaway mockup:
Create a single-page HTML/CSS/JavaScript file that shows how my app
will look. Use the colors and iconography from design-system.md.
Show every component: all button types, dropdowns, headings, inputs,
cards, badges, tables, modals, toasts. Include a light/dark toggle.
Open it in a browser. If something looks off, fix the document now. It's far cheaper than fixing finished pages.
Step 5: The database schema and API
This is the step where mistakes hurt most, because the data model touches everything. The aim is that Claude Code follows a contract and never invents tables or endpoints on the fly.
Design the complete backend for this app (ASP.NET Core Web API +
Entity Framework Core + PostgreSQL). Cover:
- All tables, fields, relationships, foreign keys, constraints,
indexes, and the matching EF Core entities
- Authentication (ASP.NET Core Identity + JWT) and authorization
(roles and policies, and which endpoints each role may call)
- API endpoints: route, method, request/response shape, role
required, and which tables each one touches
- Business rules that must be enforced on the server (for example,
a customer may only cancel their own order while it is Placed)
- Background jobs and database-level logic, if any
- Data lifecycle: soft delete, and permanent removal after 30 days
- Audit/history requirements
Rules:
- Cross-check against the PRD, Screen Flow, Tech Stack and Design
System. List contradictions and gaps first.
- Separate what belongs in the database from what is only a
PRD requirement. Do not copy product concepts into tables
without validating them.
- Evaluate storage for a startup: PostgreSQL vs file/object storage
vs a document store. Do not add infrastructure without a clear
reason.
- Use EF Core migrations as the source of schema changes.
Claude Code must not have to guess the schema or the API. Ask me
every question first, with defaults.
Deliverable: backend-design.md
Two of those rules do a lot of work. The cross-check catches contradictions between your earlier documents. And the "separate PRD from database" rule stops Claude from turning every sentence in the PRD into a table. For a startup, the answer to the storage question is almost always plain PostgreSQL plus file or blob storage for product images. No extra database needed.
An excerpt of the output:
## Storage decision
PostgreSQL for all relational data. Product images in blob storage
(Azure Blob Storage or S3), with only the image URL kept in the
database. No document database: no requirement needs it.
## Table: orders
create table orders (
id uuid primary key default gen_random_uuid(),
customer_id uuid not null references users(id),
status text not null default 'placed'
check (status in ('placed','confirmed','shipped',
'delivered','cancelled')),
total_amount numeric(10,2) not null check (total_amount >= 0),
delivery_address text not null,
placed_at timestamptz not null default now(),
deleted_at timestamptz
);
create index on orders (customer_id, placed_at desc);
## Authorization: orders
- Customer: GET /api/orders returns only rows where
customer_id = the user id in the JWT
- Customer: POST /api/orders/{id}/cancel allowed only for own
orders with status 'placed'
- Owner (role "Owner"): GET and PATCH on all orders
- Enforced in the API with authorization policies and an
ownership check in the service layer. Never trust an id
sent by the client.
## Design note: PRD vs database
The PRD says "order tracking". In the database this is a history
table (order_status_history) so the timeline can show timestamps;
a single status column cannot do that.
## Data lifecycle
Soft delete uses deleted_at plus an EF Core global query filter.
A background service (IHostedService) hard-deletes rows older than
30 days once a day.
Step 6: The implementation plan
Now you ask for a phased build plan. The most important line in this prompt is the one about what Claude Code should do when it hits something the documents don't cover. It should stop and ask you.
Using all five documents, create a sequenced, step-by-step
implementation plan that Claude Code will follow to build the app
from initialization to deployment, in phases.
Rules:
- If Claude Code reaches a decision not covered by the documents,
it must stop and ask me. It must never guess.
- Include environment setup (.NET SDK, Node version, local
PostgreSQL, secrets handling, local run and test commands).
- Each phase ends with a testable checkpoint.
- Backend and frontend work for the same feature belong in the
same phase.
Deliverables: implementation-plan.md and CLAUDE.md
CLAUDE.md is the file Claude Code reads automatically at the start of every session. Keep it short and have it point at everything else:
# CLAUDE.md
Read before doing anything: docs/prd.md, docs/screen-flow.md,
docs/tech-stack.md, docs/design-system.md, docs/backend-design.md,
docs/implementation-plan.md
## Rules
- Follow implementation-plan.md phase by phase.
- Use only the exact versions in tech-stack.md.
- Use only tokens and components from design-system.md.
- All authorization is enforced in the API, never only in Angular.
- If anything is not covered by the docs: STOP and ask me.
- Never commit secrets. Use dotnet user-secrets or environment
variables. appsettings.Development.json is git-ignored.
## Layout
/api (ASP.NET Core) /web (Angular) /docs
## Phases
1. Scaffold + tooling 2. Auth + roles 3. Product catalogue
4. Cart + checkout 5. Orders + tracking 6. Polish + deploy
Step 7: The part you have to do yourself
Claude can't set up your machine or your accounts. Before building:
- Install the .NET SDK, Node.js and PostgreSQL, and create an empty database for development
- Put the database connection string and a long random JWT signing key into
dotnet user-secrets(or environment variables), not into source files - Make sure
appsettings.Development.jsonand any.envfiles are in.gitignorebefore your first commit - Never paste secrets into a chat
A word of caution: if you ever give Claude Code access to a production database, keep an eye on what it runs. For anything real, use a separate development database.
Step 8: Build it
Open the project in Claude Code and tell it your real-world constraints. Constraints are what keep an MVP small. Mine were a time limit and keeping login as simple as possible.
Implement the plan in CLAUDE.md, with these adjustments:
1. Use email and password login with ASP.NET Core Identity and JWT
(no social or phone login).
2. Build the minimum version of each phase so we can finish in
about 1 to 1.5 hours.
3. Read the database connection string and JWT key from user-secrets
or environment variables. Use my local PostgreSQL, no Docker.
4. Work phase by phase. After each phase, tell me what to test and
which commands to run (dotnet run, ng serve).
5. If a decision is not covered by the documents, stop and ask me.
Pay close attention to the first phase. If Claude Code follows your documents there, it will keep following them. If it drifts, fix the document and not just the code, otherwise the same mistake comes back in the next phase.
Step 9: Get a second opinion
The agent that wrote the code is a bad judge of it. So I ask Claude Code to spin up separate subagents, each with one narrow job and a fresh context.
Spawn four subagents to review the app independently:
1. UI/UX auditor: compare every Angular page to design-system.md
and screen-flow.md (tokens, states, accessibility, responsive).
2. Code review auditor: structure of both the API and the Angular
app, duplication, error handling, dead code, type safety,
async/await and RxJS subscription leaks.
3. SQA: functional gaps against prd.md acceptance criteria, missing
unit and end-to-end tests, edge cases.
4. Security reviewer: authorization policy gaps, insecure direct
object access (can user A read user B's order?), JWT settings,
CORS, input validation, exposed secrets, SQL injection and XSS.
Each agent reports findings by severity (critical, high, medium,
low) with file paths. Then give me one consolidated fix plan
ordered by priority. Do not change code yet.
Read the plan before anything gets changed. For an MVP, fixing the critical and high items is usually enough.
Step 10: Test it and ship it
First, a UAT (user acceptance testing) plan:
Write a User Acceptance Test (UAT) plan for this app. For each
role (Customer, Store Owner), list test cases with: ID, scenario,
preconditions, steps, expected result, and a pass/fail column.
Cover the happy path, validation errors, empty states, permission
checks and cancelling an order. Base it on prd.md and
screen-flow.md.
Then actually run it. Do it on your phone as well as your laptop, because mobile is where layout bugs hide.
Then the deployment guide:
Write a step-by-step guide to deploy this Angular + ASP.NET Core +
PostgreSQL app to Azure (App Service for the API, Static Web Apps
for Angular, Azure Database for PostgreSQL) and to AWS (for example
Elastic Beanstalk or App Runner for the API, S3 + CloudFront for
Angular, RDS for PostgreSQL). Include: connecting the Git
repository, CI/CD with GitHub Actions, environment variables and
secrets, running EF Core migrations safely, CORS settings, custom
domain and HTTPS, and a post-deploy smoke test checklist.
Two things people forget every time: updating the CORS settings so the deployed Angular URL can call the API, and running the EF Core migrations against the production database. If everything works locally but the deployed site shows network errors, check those first.
What I'd tell my past self
- Let the AI interview you. Approving defaults is fast, and it surfaces decisions you didn't know you were making.
- Keep one topic per document. A PRD isn't a schema, and a schema isn't a design system.
- Pin versions and write down non-goals. Both shrink what the AI can guess at.
- Tell it when to stop and ask. Silent guesses cause most of the rework.
- Enforce authorization in the API, not just the UI. Ask a reviewer agent to try to break it.
- When something's wrong, fix the document too, not only the code.
- Keep the scope small. Cut features before you cut quality.
Wrapping up
AI-assisted development isn't really about typing less. It's about making your decisions early, in writing, so the build stops being a guessing game. Take the prompts above, swap QuickCart for your own idea, and read each document before you move to the next.
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes โ full credit and traffic to the original publisher.