Disclaimer: This
README.mdfile was generated by an LLM (Large Language Model).
A pragmatic foundation for building maintainable REST APIs with Node.js, Express, and TypeScript, using Vertical Slice Architecture.
- Vertical Slice Architecture: Each feature is self-contained with its own endpoints, services, DTOs, mappers, and validation schemas.
- Domain Logic: Rich domain entities with factory methods and business invariants.
- Schema Validation: Request validation powered by Zod, with structured error responses.
- Global Error Handling: Centralized exception handling middleware for consistent API error responses.
- TypeScript by Default: Enjoy the benefits of static typing for more robust and maintainable code.
- Configuration Management: Type-safe, centralized environment variable management with dotenv.
- Developer-Friendly: Hot-reloading with
tsxfor a smooth development experience. - Linter & Formatter: Integrated with BiomeJS for clean and consistent code.
- Ready to Deploy: Includes scripts for building and starting a production-ready server.
- Node.js (v24 or higher)
- pnpm (v11 or higher). If you have Node.js 24+, enable it with
corepack enable.
-
Clone the repository:
git clone https://github.com/poschuler/pragmatic-nodejs-api.git
-
Navigate to the project directory:
cd pragmatic-nodejs-api -
Install the dependencies:
pnpm install
-
Create your environment file from the template:
cp .env.template .env
Variable Default Description PORT3000Port the HTTP server listens on. NODE_ENVdevelopmentCurrent environment name. DEBUGfalseEnables verbose output. All three have defaults, so the app boots without a
.envfile, but the values are validated and parsed at startup bysrc/config/config.ts.
-
Development Mode: To start the server in development mode with hot-reloading, run:
pnpm dev
The server will be available at
http://localhost:3000. -
Production Mode: To build and start the application in production mode, run:
pnpm start
| Method | Path | Description |
|---|---|---|
| GET | /health |
Health check |
| GET | /api/products |
List all products |
| POST | /api/products |
Create a new product |
curl -X POST http://localhost:3000/api/products \
-H "Content-Type: application/json" \
-d '{"name": "Product 1", "description": "Description of Product 1", "price": 9.99}'pnpm dev: Starts the application in development mode with hot-reloading.pnpm build: Compiles the TypeScript code to JavaScript in thedistdirectory.pnpm start: Builds and starts the production version of the application.pnpm biome:lint: Lints the codebase for errors.pnpm biome:lint:fix: Lints and fixes the codebase.pnpm biome:format: Formats the codebase.pnpm biome:format:fix: Formats and writes the changes to the codebase.
A
preinstallguard (only-allow pnpm) runs automatically and aborts the install if you try to usenpmoryarn.
The project follows a vertical-slice, feature-oriented directory structure.
src/
├── app.ts # Main application entry point
├── server.ts # Core Server class (Express wrapper)
├── routes.ts # Main application router & middleware composition
│
├── config/
│ └── config.ts # Environment variable management
│
├── domain/
│ └── product.entity.ts # Product domain entity with factory method
│
├── exceptions/
│ ├── validation-error.ts # ValidationError interface
│ └── validation-exception.ts # ValidationException class
│
├── middlewares/
│ └── exception-handler.middleware.ts # Global error handling middleware
│
├── shared/
│ └── validations/
│ └── validate-request-with-schema.ts # Zod schema validation utility
│
└── features/
└── products/ # Products feature module
├── products.routes.ts # Products router factory
├── products.service.ts # Products business logic service
│
├── create-product/ # Create Product endpoint (vertical slice)
│ ├── create-product.endpoint.ts
│ ├── create-product.mapper.ts
│ ├── create-product.request.ts
│ ├── create-product.response.ts
│ └── create-products.schema.ts
│
└── get-products/ # Get Products endpoint (vertical slice)
├── get-products.endpoint.ts
├── get-products.mapper.ts
└── get-products.response.ts
- Runtime: Node.js
- Framework: Express.js v5
- Language: TypeScript
- Module System: ESM (
"type": "module") - Validation: Zod
- Env Management: dotenv
- Transpiler/Runner: tsx
- Linter/Formatter: BiomeJS
- Package Manager: pnpm (pinned via the
packageManagerfield inpackage.json)
Contributions are welcome! Please read our AGENTS.md for guidelines on how to collaborate with the project, especially when using AI agents.
This project is licensed under the MIT License. See the LICENSE file for details.