Overview
The TailStack Node package is a standalone, production-grade backend architecture template built with Express 5 and TypeScript. It provides a secure, scalable, and performance-optimized foundation for building REST APIs, microservices, and backend applications.
Ideal For
REST APIs
Microservices
Backend-for-Frontend (BFF) patterns
GraphQL servers
Real-time applications
{
"name" : "Server" ,
"version" : "1.0.0" ,
"packageManager" : "[email protected] " ,
"license" : "ISC"
}
Technical Stack
Express 5 Fast, unopinionated, minimalist web framework
TypeScript 5.9 Full type safety for backend logic
Node Cluster Multi-core system utilization
TSX Modern TypeScript execution engine
Project Structure
node/
├── src/
│ ├── cluster/ # Node cluster implementation
│ ├── config/ # Configuration management
│ ├── constant/ # Constants and enums
│ ├── controller/ # Route controllers
│ ├── middlewares/ # Express middlewares
│ ├── routes/ # API route definitions
│ ├── services/ # Business logic layer
│ ├── types/ # TypeScript type definitions
│ ├── app.ts # Express application setup
│ └── server.ts # Server entry point
├── dist/ # Compiled JavaScript output
├── .env.example # Environment variable template
├── tsconfig.json # TypeScript configuration
└── package.json # Dependencies and scripts
Available Scripts
Development Mode
Production Build
Start Production Server
Run Tests
pnpm dev
# Runs server with TSX watch mode
# Automatic reload on file changes
# Entry point: src/server.ts
Dependencies
Production Dependencies
Express 5 with improved performance and modern features.
{
"cors" : "^2.8.6" ,
"cookie-parser" : "^1.4.7"
}
CORS : Cross-Origin Resource Sharing configuration
Cookie Parser : Parse cookie headers and populate req.cookies
{
"dotenv" : "^17.2.3" ,
"axios" : "^1.7.9"
}
Dotenv : Load environment variables from .env file
Axios : HTTP client for external API calls
Development Dependencies
TypeScript Configuration
{
"compilerOptions" : {
"target" : "ES2022" ,
"module" : "ES2022" ,
"moduleResolution" : "bundler" ,
"esModuleInterop" : true ,
"resolveJsonModule" : true ,
"outDir" : "dist" ,
"strict" : true ,
"skipLibCheck" : true ,
"forceConsistentCasingInFileNames" : true ,
"baseUrl" : "." ,
"paths" : {
"@/*" : [ "./src/*" ]
}
}
}
Key Features
Path Aliases : Use @/ to import from src/ directory
ES2022 Target : Modern JavaScript features
Strict Mode : Maximum type safety
JSON Imports : Import JSON files directly
Architecture Patterns
Layered Architecture
Routes Layer
Define API endpoints and HTTP methods // src/routes/user.routes.ts
import { Router } from 'express'
import { UserController } from '@/controller/user.controller'
const router = Router ()
router . get ( '/users' , UserController . getAll )
router . post ( '/users' , UserController . create )
Controller Layer
Handle HTTP requests and responses // src/controller/user.controller.ts
import { Request , Response } from 'express'
import { UserService } from '@/services/user.service'
export class UserController {
static async getAll ( req : Request , res : Response ) {
const users = await UserService . getAllUsers ()
res . json ( users )
}
}
Service Layer
Implement business logic and data access // src/services/user.service.ts
export class UserService {
static async getAllUsers () {
// Business logic here
return users
}
}
Middleware Stack
The src/middlewares/ directory contains Express middlewares:
Authentication JWT verification and user authentication
Validation Request body and parameter validation
Error Handling Centralized error handling and formatting
Logging Request/response logging
Node Cluster Implementation
The Node package includes cluster support for utilizing multi-core systems and maximizing performance.
Located in src/cluster/, the cluster implementation:
Spawns worker processes for each CPU core
Handles worker crashes and restarts
Distributes incoming connections
Improves throughput and reliability
Example Cluster Setup
// src/cluster/master.ts
import cluster from 'cluster'
import os from 'os'
if ( cluster . isPrimary ) {
const numCPUs = os . cpus (). length
for ( let i = 0 ; i < numCPUs ; i ++ ) {
cluster . fork ()
}
cluster . on ( 'exit' , ( worker ) => {
console . log ( `Worker ${ worker . process . pid } died, restarting...` )
cluster . fork ()
})
} else {
// Start Express server in worker
import ( './server' )
}
Security Features
Pre-configured CORS middleware for cross-origin requests: import cors from 'cors'
app . use ( cors ({
origin: process . env . ALLOWED_ORIGINS ?. split ( ',' ),
credentials: true
}))
Secure cookie parsing and handling: import cookieParser from 'cookie-parser'
app . use ( cookieParser ( process . env . COOKIE_SECRET ))
Sensitive configuration managed through environment variables: # .env.example
PORT = 5000
NODE_ENV = development
ALLOWED_ORIGINS = http://localhost:5173
COOKIE_SECRET = your-secret-here
Environment Configuration
Setting Up Environment Variables
Configure Variables
Edit .env with your configuration: PORT = 5000
NODE_ENV = development
DATABASE_URL = postgresql://localhost:5432/mydb
API_KEY = your-api-key
Load in Application
// src/config/env.ts
import dotenv from 'dotenv'
dotenv . config ()
export const config = {
port: process . env . PORT || 5000 ,
nodeEnv: process . env . NODE_ENV || 'development'
}
Never commit .env files to version control. Always use .env.example as a template.
API Route Organization
Route Structure
// src/routes/index.ts
import { Router } from 'express'
import userRoutes from './user.routes'
import authRoutes from './auth.routes'
const router = Router ()
router . use ( '/api/users' , userRoutes )
router . use ( '/api/auth' , authRoutes )
export default router
Route Naming Conventions
Resource Routes /api/users
/api/products
/api/orders
Action Routes /api/auth/login
/api/auth/register
/api/users/:id/activate
Agent Skills
Comprehensive guidance for building production-ready Node.js applications. Covers:
Scalable architecture patterns
Express best practices
Error handling strategies
Security implementations
Performance optimization
Testing strategies
Official Documentation
Supported AI Agents
Gemini
Claude
Codex
Cursor
OpenCode
Trae
Development Workflow
Getting Started
Configure Environment
cp .env.example .env
# Edit .env with your configuration
Start Development Server
Server starts on http://localhost:5000 (or configured PORT)
Hot Reload
The development server uses TSX watch mode for instant reload:
Watches all TypeScript files in src/
Automatically restarts on file changes
Preserves console output between restarts
Production Deployment
Build Process
Compile TypeScript
Generates JavaScript in dist/ directory
Set Environment
export NODE_ENV = production
Start Server
Runs compiled code from dist/server.js
Production Optimizations
Cluster Mode Use all CPU cores for maximum throughput
Process Manager Deploy with PM2 or similar for auto-restart
Reverse Proxy Use Nginx or similar for load balancing
Environment Config Use production environment variables
Best Practices
Error Handling
// src/middlewares/error.middleware.ts
import { Request , Response , NextFunction } from 'express'
export const errorHandler = (
err : Error ,
req : Request ,
res : Response ,
next : NextFunction
) => {
console . error ( err . stack )
res . status ( 500 ). json ({
error: {
message: process . env . NODE_ENV === 'production'
? 'Internal server error'
: err . message
}
})
}
Async Route Handlers
// Wrap async functions to catch errors
const asyncHandler = ( fn : Function ) => (
req : Request ,
res : Response ,
next : NextFunction
) => {
Promise . resolve ( fn ( req , res , next )). catch ( next )
}
router . get ( '/users' , asyncHandler ( async ( req , res ) => {
const users = await UserService . getAll ()
res . json ( users )
}))
Request Validation
// src/middlewares/validate.middleware.ts
import { Request , Response , NextFunction } from 'express'
export const validateUser = (
req : Request ,
res : Response ,
next : NextFunction
) => {
const { email , password } = req . body
if ( ! email || ! password ) {
return res . status ( 400 ). json ({
error: 'Email and password are required'
})
}
next ()
}
import compression from 'compression'
app . use ( compression ())
import apicache from 'apicache'
const cache = apicache . middleware
router . get ( '/users' , cache ( '5 minutes' ), getUsers )
import rateLimit from 'express-rate-limit'
const limiter = rateLimit ({
windowMs: 15 * 60 * 1000 ,
max: 100
})
app . use ( '/api/' , limiter )
Testing
Recommended Testing Stack
Jest : Test framework
Supertest : HTTP assertion library
ts-jest : TypeScript support for Jest
pnpm add -D jest supertest @types/jest @types/supertest ts-jest
Example Test
// src/__tests__/user.test.ts
import request from 'supertest'
import app from '../app'
describe ( 'User API' , () => {
it ( 'GET /api/users returns users' , async () => {
const response = await request ( app )
. get ( '/api/users' )
. expect ( 200 )
expect ( Array . isArray ( response . body )). toBe ( true )
})
})
Next Steps
Core Package Learn about the full monorepo architecture
React Package Connect to the frontend application
Backend Routing Learn about API routing patterns
Deployment Deploy your Node.js application