This project sets up a TypeScript-based REST API using Express, with MongoDB as the primary database accessed via official drivers.
It enforces robust validation and documentation by leveraging Zod for schema validation and auto-generating OpenAPI docs, while ensuring maintainability through ESLint, Prettier, and path aliases.
The structure follows the Controller–Service–Repository pattern, where controllers handle requests, services manage business logic, and repositories encapsulate database access, making the system cleanly layered and scalable.
- Create a GET endpoint at /users/:id
- Endpoint created, along with an endpoint to create a user
- Bonus: Gracefully handle invalid ObjectId errors
- Middleware for zod schema validation created, example of a response for a incorrect request:
{ "message": "Validation failed. Following errors were encountered:\n{\n \"params\": \"✖ Too small: expected string to have >=24 characters\\n → at id\\n✖ Invalid ObjectId\\n → at id\"\n}" }``` - Unique twist: Only return users where the age is greater than 21
- API will only allow users over 21 to be created, and mongoose will only create user records over 21
- Express 5 for building REST APIs
- TypeScript for type safety
- MongoDB as the database, accessed via official drivers
- Zod for schema validation
- OpenAPI docs auto-generated from Zod schemas
- ESLint and Prettier for code quality and formatting
- Path aliases (
@/*) for cleaner imports - Nodemon + ts-node for live-reloading during development
- Environment variable management with
dotenvanddotenv-expand
- MongoDB is used as the primary database.
- The project connects to MongoDB using the official Node.js driver.
- You can run a local MongoDB instance using Docker Compose (see below).
src/
app.ts # Entry point
lib/ # App and router setup
config/ # Environment, OpenAPI, Zod config
controllers/ # Route controllers
middlewares/ # Express middlewares
models/ # Data models
repositories/ # Data access logic
routes/ # Route definitions
services/ # Business logic
pnpm dev— Start development server with live reload (nodemon+ts-node+ path aliases)pnpm build— Compile TypeScript to JavaScript indist/pnpm start— Run compiled server fromdist/pnpm lint— Run ESLint
- Uses
tsconfig.jsonfor main config andtsconfig.build.jsonfor builds. - Path aliases (
@/*) are enabled via"paths"intsconfig.json. - For runtime support of aliases,
tsconfig-pathsis used in the dev script.
- ESLint is configured for TypeScript and includes stylistic and import sorting rules.
- Prettier can be used for formatting (see
.prettierrc). - Trailing spaces and unused imports are checked.
- Zod schemas are used to generate OpenAPI docs.
- Docs are served at
/docsviaswagger-ui-express.
- Managed via
.envfiles and validated with Zod. - Before running the project, make sure to fill out the
.envfile with the required environment variables (e.g.,MONGODB_URI,PORT, etc.).
-
Install dependencies:
pnpm install -
Start MongoDB using Docker Compose:
docker compose up -d -
Fill out the
.envfile:
Edit.envand provide all required values. -
Start development server:
pnpm dev
-
Install dependencies:
pnpm install -
(Optional) Start MongoDB using Docker Compose:
docker compose up -dAlternatively, you can connect to an existing MongoDB instance by updating theMONGODB_URIin your.envfile. -
Ensure required environment variables are set
-
Build for production:
pnpm build -
Run production build:
pnpm start
- Use
@/*for importing fromsrc/(e.g.,import { registry } from '@/config/openapi'). - For new routes, add controllers and route definitions in
src/routes/. - API documentation is auto-generated and available