Telente Store
A modular-monolith commerce platform: 24 hexagonal modules, 150+ routes, 31 relational models — storefront, admin dashboard and API in one process.
- 24
- Feature modules
- 150+
- API routes
- 31
- Relational models
- 1
- Deployable process
- Role
- Author
- Year
- 2026
- Type
- E-commerce platform
01Overview
Telente Store is a production e-commerce platform built as a modular monolith: 24 feature modules, each with a hexagonal ports-and-adapters layout, unified by a lightweight DI container and CQRS-style command and query buses.
A single Node.js process serves a REST API with 150+ routes, a vanilla storefront with clean URLs, and a full admin dashboard for catalogue, orders, inventory, users, returns and support.
It is the project where the modular-monolith pattern I later scaled up in Zudomart was worked out.
02The problem
Commerce has an unforgiving domain model. Inventory with variants, carts, orders, payments, shipping, returns, refunds, coupons, tax rules and reviews all touch each other, and getting any transition wrong costs real money.
Most small commerce codebases collapse into a controllers folder and a services folder, at which point the order lifecycle is spread across a dozen files and nobody can say where a refund is authorised.
The goal was a codebase where each part of the domain has one obvious home and the boundaries between them are enforced by structure rather than convention.
03Architecture
- 01
24 hexagonal modules
Each module owns its domain, ports and adapters. Nothing reaches across a boundary except through a declared port, so swapping a payment provider or an email transport touches one adapter.
- 02
DI container and CQRS buses
A lightweight container wires modules together; command and query buses separate writes from reads. Routes dispatch to the bus rather than calling services directly, which keeps HTTP concerns out of the domain.
- 03
31 relational models
Prisma over MySQL 8.4 covering catalogue, variant inventory, carts, orders, payments, shipping, returns, refunds, coupons, reviews, notifications and email delivery tracking.
- 04
Storefront and admin from one process
An editorial vanilla storefront (home, listing, product detail with gallery, cart, checkout with coupons/tax/shipping, account, wishlist, returns, public order tracking) and a full admin dashboard, both served with clean-URL routing by the same Fastify instance.
- 05
Inventory as a ledger
Stock is not a number that gets updated. Every movement is an entry, with low-stock thresholds computed over the ledger — so a discrepancy can be traced instead of discovered.
- 06
Platform concerns
Paystack payments with webhook handling, email delivery through Resend/SendByte with delivery-status tracking, OTP auth, rate limiting, Helmet, CORS hardening, branded HTML error pages, and a Dockerised MySQL + backend with health checks.
04Key decisions
One process, 24 modules
A store this size does not need a service mesh. It needs internal boundaries good enough that the twenty-fifth module does not make the previous twenty-four harder to change.
TypeScript 5.9 strict, ESM, NodeNext
Strictest reasonable settings from the first commit. Retrofitting strictness onto 24 modules and 31 models is a project of its own.
Stock movements over stock counts
Storing the ledger and deriving the level means overselling is a reconstructable event rather than a mystery.
Vanilla storefront with a real design system
No framework on the client, but a genuine editorial design system in CSS. Fast pages, no hydration, and full control over checkout — the one flow where a surprise is unacceptable.
05Stack
- TypeScript 5.9
- Fastify 5
- Prisma
- MySQL 8.4
- Node.js 24
- Paystack
- Resend
- Docker
- Swagger