IkboljonMe
Writing

09.21.262 min readNext.js · Architecture

Layers and a factory in a Next.js shop

Notes from building an online shop on Next.js, Prisma and PostgreSQL — keeping route handlers thin, and letting a factory decide what a product needs.


Layers and a factory in a Next.js shop

Online-Shop is a small e-commerce system: a product catalogue with categories, a cart, order management and a REST API. It runs on Next.js 14 with API routes, PostgreSQL through Prisma, and Docker Compose. The interesting part isn't the stack — it's how the code is split.

Three layers

  • API layer — app/api/*. Route handlers parse the request and return a response. Nothing else.
  • Service layer — lib/services/*. The business logic: what an order is, when a cart is valid.
  • Data layer — Prisma. The only place that talks to the database.

The payoff is that a route handler reads like a table of contents. When something about orders changes, there is exactly one service to open, and the handlers don't move.

A factory for product types

Physical and digital products share most fields but differ where it counts: a digital product has nothing to ship. A ProductFactory creates the right type, with the validation and shipping calculation that belong to it, so the rest of the code never branches on the product kind.

One database client

Next.js development mode reloads modules constantly, and each reload can open a fresh Prisma client until the database runs out of connections. The client is created once in lib/db.ts and reused everywhere — a plain singleton, and the connection warnings disappear.

One command to run it

bash
docker-compose up --build

That starts the database and the app together. For day-to-day work I run only the database in Docker and the app locally, with migrations and a seed script to get realistic data in place.