Backend
The backend is a NestJS application structured around Domain-Driven Design, CQRS and hexagonal architecture. The goal is a codebase where every piece has an obvious home, business logic is isolated from frameworks and I/O, and the important rules are enforced automatically rather than left to discipline.
The shape of a feature
Adding a behaviour to the system almost always means the same handful of files, in the same places:
- A value object or change to an aggregate in
domain/— the business rule itself. - A command (write) or query (read) in
application/, plus its handler. - A controller method in
interfaces/that builds the command/query and dispatches it on the bus. - Optionally, a domain-event handler that emits an integration event to the outbox for other contexts to react to.
Because the structure is so regular, you — or an AI agent — can navigate any context by analogy to any other.
The pillars
- Domain-Driven Design — aggregates encapsulate state and rules; value objects make illegal states unrepresentable; domain events record what happened.
- CQRS — commands and queries are separate, each with a base handler that adds authorize → validate → handle, plus logging, tracing and metrics for free.
- Event-Driven Architecture — the transactional outbox and idempotent inbox give reliable, exactly-once messaging over Kafka.
- Repositories — the domain defines a repository interface (a port); infrastructure provides the MongoDB adapter.
- Authentication — JWT access/refresh tokens, a guard that also checks revocation, and role-based access.
- Enforced Boundaries — custom ESLint rules that fail the build when an architectural rule is broken.
Why this much structure?
It pays off in three ways:
- Legibility. Predictable layout and naming mean less time spent finding things and more spent changing them — for humans and for coding agents alike.
- Safety. The layering and the lint rules stop accidental coupling (domain reaching into infrastructure, one context importing another's internals) before it ships.
- Evolvability. Bounded contexts that communicate only through events can be split into separate services later with little ceremony.
Start with Domain-Driven Design.