Skip to main content

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

Package Information

{
  "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

pnpm dev
# Runs server with TSX watch mode
# Automatic reload on file changes
# Entry point: src/server.ts

Dependencies

Production Dependencies

{
  "express": "^5.2.1"
}
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": "^5.9.3",
  "tsx": "^4.21.0",
  "ts-node": "^10.9.2",
  "@types/node": "^25.0.10",
  "@types/express": "^5.0.6",
  "@types/cookie-parser": "^1.4.10",
  "@types/dotenv": "^8.2.3"
}
Complete TypeScript support with type definitions.
{
  "nodemon": "^3.1.11"
}
Automatic server restart on file changes.

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

1

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)
2

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)
  }
}
3

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
}))
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

1

Copy Template

cp .env.example .env
2

Configure Variables

Edit .env with your configuration:
PORT=5000
NODE_ENV=development
DATABASE_URL=postgresql://localhost:5432/mydb
API_KEY=your-api-key
3

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

Pre-configured 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

1

Install Dependencies

pnpm install
2

Configure Environment

cp .env.example .env
# Edit .env with your configuration
3

Start Development Server

pnpm dev
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

1

Compile TypeScript

pnpm build
Generates JavaScript in dist/ directory
2

Set Environment

export NODE_ENV=production
3

Start Server

pnpm start
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()
}

Performance Tips

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

  • 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

Build docs developers (and LLMs) love