Modern REST API template built with Express.js and TypeScript.
- Runtime: Node.js
- Framework: Express.js 4.21+
- Language: TypeScript 5.9+
- Database: TCB managed PostgreSQL (via CloudBase JS SDK)
- Validation: Zod
- Testing: Jest + Supertest
backend/
├── src/
│ ├── __tests__/ # Test files
│ ├── config/ # Configuration
│ │ ├── database.ts # Database client
│ │ ├── env.ts # Environment validation
│ │ └── logger.ts # Pino logger setup
│ ├── middleware/ # Express middleware
│ │ ├── errorHandler.ts # Error handling
│ │ ├── logger.ts # HTTP logging
│ │ └── validation.ts # Zod validation
│ ├── modules/ # Feature modules (routes + handlers)
│ │ └── system.ts # System & health checks
│ ├── types/ # TypeScript types & Zod schemas
│ ├── app.ts # Express app setup
│ └── index.ts # Server entry point
├── .env.example # Environment template
├── package.json
└── tsconfig.json
- Node.js 18+
- npm or yarn
- Install dependencies:
cd backend
npm install- Set up environment variables:
cp .env.example .env
# Edit .env with your configurationStart the development server with hot reload:
npm run devServer will start at http://localhost:3000
Run tests:
npm testRun tests in watch mode:
npm run test:watchBuild the project:
npm run buildStart production server:
npm startGET /api/v1/- API welcome messageGET /api/v1/health- Basic health checkGET /api/v1/health/ready- Readiness check (includes database connection)GET /api/v1/health/live- Liveness checkGET /api/v1/version- API version informationGET /api/v1/ping- Simple ping endpointGET /api/v1/status- System status (uptime, memory, etc.)
Add your business logic as new modules in src/modules/. Each module combines routes and handlers in a single file for simplicity. See src/modules/README.md for detailed examples and best practices.
Create a new module src/modules/user.ts:
import { Router } from 'express'
import { db } from '../config/database.js'
export const userRouter = Router()
userRouter.get('/', async (_req, res) => {
const users = await db.collection('users').get()
res.json(users.data)
})
userRouter.post('/', async (req, res) => {
const result = await db.collection('users').add(req.body)
res.status(201).json(result)
})Register it in src/app.ts:
import { userRouter } from './modules/user.js'
app.use(`${env.API_PREFIX}/users`, userRouter)curl http://localhost:3000/api/v1/healthcurl http://localhost:3000/api/v1/health/readycurl http://localhost:3000/api/v1/status- CORS: Configured cross-origin resource sharing
- Input Validation: Zod schema validation
- Error Handling: Centralized error management
| Variable | Description | Default |
|---|---|---|
NODE_ENV |
Environment mode | development |
PORT |
Server port | 3000 |
API_PREFIX |
API route prefix | /api/v1 |
CLOUDBASE_ENV_ID |
CloudBase environment ID | - |
CLOUDBASE_SECRET_ID |
CloudBase secret ID | - |
CLOUDBASE_SECRET_KEY |
CloudBase secret key | - |
CORS_ORIGIN |
Allowed CORS origin (URL or * for all) |
* |
Note on CORS: Default is * (allow all origins). This disables credentials (cookies, authorization headers). For production, specify exact origins.
- Response compression
- Pagination for large datasets
The API uses consistent error responses:
{
"status": "error",
"message": "Error description",
"errors": [] // Optional validation errors
}HTTP Status Codes:
200- Success201- Created204- No Content400- Bad Request404- Not Found409- Conflict500- Internal Server Error
MIT