Modularity Best Practices
Import direction: routes → use-cases → domain. These practices keep Node.js codebases testable and ready for framework or persistence changes.
Search across all documentation pages
Import direction: routes → use-cases → domain. These practices keep Node.js codebases testable and ready for framework or persistence changes.
express, fastify, @nestjs/*, prisma, ioredis.infrastructure → application → domain. Never domain → infrastructure.infrastructure/.dependency-cruiser or ESLint to fail forbidden imports.shared/.export * from './infrastructure'.OrderGodService.AppError). Central HTTP mapper translates codes.findById, not findUnique.OrderRepository.ordersRouter(deps) for injection.OrdersService god class.req.body with Zod at HTTP edge before execute().routes.ts, use-cases/, optional repos/ is enough. Full hexagonal folders when second adapter appears.
Auth middleware can attach user to request. Business authorization still in use case.
Extract one use case per PR. Route calls new use case; delete old inline logic when tests pass.
Explicit types at use case boundary help. HTTP DTOs can differ from domain entities via mapper functions.
execute(deps, input) functions work. Keep same import rules.
import { prisma } from '../lib/prisma' inside route handlers.
Schema package OK; each service owns repository adapter - no shared Prisma calls from routes.
Resolvers are adapters - call use cases, do not embed SQL.
scripts/ can be loose. src/ production code follows this list.
No for week-one MVP if tech-debt ticket tracks extraction before squad #2.
Stack versions: This page was written for Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, and NestJS 11.
Reviewed by Chris St. John·Last updated Jul 16, 2026