A complete e-commerce application, built in 6 days
PhonEcommerce is a full-stack online mobile-phone store: a filtered catalog, cart, three-step checkout, order history and cancellation, a profile with addresses, and an administration panel. The frontend is Next.js 16 with React 19, Zustand, and Tailwind CSS 4; the backend is Fastify 5 on PostgreSQL with Prisma.
It is entirely my own project: 41 commits, all mine, with no fork or upstream to credit. The first commit is from 2026-05-06 and the last from 2026-05-11—a 6-day window from end to end, including the admin panel.
That number calls for explaining two things, which are the next two sections: how the backend is built (feature-based Clean Architecture, with three written ADRs) and how the work was organized (a multi-agent workflow with domain-specialized agents). The first supports the project; the second explains the timeline.
Four layers, once per feature—not once per project
The backend is organized not by file type (controllers/, services/, models/) but by feature, with
all four Clean Architecture layers inside each feature. The repository’s first commit already says so—
“initial project setup with Clean Architecture backend and feature-based frontend”—so this was not
rearranged afterward: it was the starting point.
backend/src/<feature>/
domain/ ← entities and interfaces, without external dependencies
application/ ← use cases
infrastructure/ ← Prisma repositories
presentation/ ← Fastify controllers and routesDependency direction is what makes this worthwhile. domain/ imports nothing external: it defines the
entities and, above all, repository interfaces. application/ contains use cases and depends only on
those interfaces. Prisma first appears in infrastructure/, implementing them, and Fastify appears in
presentation/. The result is that neither the ORM nor the HTTP framework touches business rules: they
are details plugged into the edges.
Making feature, rather than layer, the primary boundary is the decision itself, and it is written as
an ADR: docs/decisions/001-clean-architecture-by-features.md. Each feature works as a bounded context
with its four layers inside, so everything needed to change “stock” or “orders” lives together instead of
being spread across four distant folders in the tree.
Three written decisions, not three remembered decisions
The repository includes three ADRs under docs/decisions/: 001-clean-architecture-by-features.md, 002-jwt-with-refresh-tokens.md, and 003-prisma-postgresql.md. Writing them separates a chosen architecture from one inherited from a tutorial: each records what was decided and why, and serves as a reference when convenience tempts somebody to break the rule.
The cost: much more ceremony per endpoint
Four layers per feature means a trivial operation touches several files—entity and interface in domain, use case in application, repository in infrastructure, controller and route in presentation—where direct CRUD against Prisma might have taken one. That is this architecture's explicit cost, paid with every new feature. What it buys in return appears in the testing section.
The frontend follows the same boundary criterion, though without the layers: features/<feature>/ with
its components, hooks, services, and types; shared/ for reuse across features; and app/ for Next.js
App Router routes.
Domain-specialized agents, signing the TODO
The 6 days did not come from working more hours; they came from how the work was divided. The project was
built with a custom multi-agent workflow—the repository contains its own .agents/ folder (agents,
skills, workflows), the same pattern used to build this portfolio.
The most concrete evidence is in docs/TODO.md, where entries are signed by the agent that added them:
Added by: main-agent - 2026-05-06
added by: backend-stock-agent - 2026-05-06This is not merely a process anecdote: it follows exactly the same boundary as the architecture. A
main-agent coordinates domain-specialized agents—the signed backend-stock-agent is one of them—with
each working on its feature. Splitting the backend by bounded context lets several fronts progress without
stepping on one another: if the split were by layer, every new feature would touch the same four folders
as every other feature.
In other words, the previous section’s architecture is more than a code decision: it enabled the working method—and the timeline that resulted from it.
A complete store and administration panel, not a catalog demo
The scope did not stop at the storefront. According to the repository README, these features are complete:
Catalog with filters
A filterable product listing, the store's entry point.
Three-step checkout
The purchase flow divided into three stages rather than one form.
Order history and cancellation
Customers can view past purchases and cancel an order—the post-sale work often omitted from practice projects.
Profile with addresses
A user account with shipping-address management.
Admin panel
CRUD for products, brands, and categories; stock control with movement history; and order management.
The admin panel is the half that determines whether this is a store or a mockup: without catalog CRUD or stock control, the customer catalog would be fixed content. Here, stock also stores a movement history, not just the current number.
34 backend tests, zero frontend tests, no CI
This is where the ceremony of four layers pays off. Because use cases depend on interfaces rather than Prisma, every layer can be tested in isolation without starting a database: the backend has 34 test files running with Vitest.
The other side of the number is equally real: the frontend has 0 tests, and there is no CI—the
repository has no .github/, so those 34 tests run when somebody starts them manually, not on each push.
They are written, not automated.
I state it plainly because hiding it would not improve the case: in 6 days, coverage prioritized backend business logic, where a regression corrupts data, while everything else remained outside the cut. It is a real project with its real tradeoff, not an idealized one.
What remains after deciding before writing
Authentication is the smallest, clearest example of how this worked: JWT with a 15-minute access token
plus refresh token rotation, decided and documented in docs/decisions/002-jwt-with-refresh-tokens.md
before it existed as code. Rotation is not the default result of a JWT tutorial—it is a decision made with
an understanding of what it mitigates.
The project is finished: 41 original commits, 6 days, a feature-based Clean Architecture backend with three ADRs, a multi-agent workflow that built it, and a complete product through the admin panel. What I take away is that both halves support one another: architecture by bounded context made dividing the work between agents possible, and that division explains the timeline. Neither half alone produces 6 days.