Back to Skills

nodejs-express-server

aj-geddes
Updated Today
20 views
7
7
View on GitHub
Metaaiapidesigndata

About

Build production-ready Express.js servers with middleware, authentication, routing, and database integration. Use when creating REST APIs, managing requests/responses, implementing middleware chains, and handling server logic.

Documentation

Node.js Express Server

Overview

Create robust Express.js applications with proper routing, middleware chains, authentication mechanisms, and database integration following industry best practices.

When to Use

  • Building REST APIs with Node.js
  • Implementing server-side request handling
  • Creating middleware chains for cross-cutting concerns
  • Managing authentication and authorization
  • Connecting to databases from Node.js
  • Implementing error handling and logging

Instructions

1. Basic Express Setup

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

// Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Routes
app.get('/health', (req, res) => {
  res.json({ status: 'OK', timestamp: new Date().toISOString() });
});

// Error handling
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(err.status || 500).json({
    error: err.message,
    requestId: req.id
  });
});

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

2. Middleware Chain Implementation

// Logging middleware
const logger = (req, res, next) => {
  const start = Date.now();
  res.on('finish', () => {
    const duration = Date.now() - start;
    console.log(`${req.method} ${req.path} ${res.statusCode} ${duration}ms`);
  });
  next();
};

// Authentication middleware
const authenticateToken = (req, res, next) => {
  const token = req.headers['authorization']?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'No token' });

  jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
    if (err) return res.status(403).json({ error: 'Invalid token' });
    req.user = user;
    next();
  });
};

// Error catching middleware wrapper
const asyncHandler = (fn) => (req, res, next) => {
  Promise.resolve(fn(req, res, next)).catch(next);
};

app.use(logger);
app.use(express.json());
app.get('/protected', authenticateToken, (req, res) => {
  res.json({ user: req.user });
});

3. Database Integration (PostgreSQL with Sequelize)

const { Sequelize, DataTypes } = require('sequelize');

const sequelize = new Sequelize(
  process.env.DB_NAME,
  process.env.DB_USER,
  process.env.DB_PASS,
  {
    host: process.env.DB_HOST,
    dialect: 'postgres',
    logging: false
  }
);

const User = sequelize.define('User', {
  id: {
    type: DataTypes.UUID,
    defaultValue: DataTypes.UUIDV4,
    primaryKey: true
  },
  email: {
    type: DataTypes.STRING,
    unique: true,
    allowNull: false
  },
  password: DataTypes.STRING,
  role: {
    type: DataTypes.ENUM('user', 'admin'),
    defaultValue: 'user'
  }
}, {
  timestamps: true
});

// Sync database
sequelize.sync({ alter: true });

4. Authentication with JWT

const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');

const generateToken = (userId) => {
  return jwt.sign(
    { userId, iat: Math.floor(Date.now() / 1000) },
    process.env.JWT_SECRET,
    { expiresIn: '24h' }
  );
};

app.post('/login', asyncHandler(async (req, res) => {
  const { email, password } = req.body;
  const user = await User.findOne({ where: { email } });

  if (!user) return res.status(404).json({ error: 'User not found' });

  const validPassword = await bcrypt.compare(password, user.password);
  if (!validPassword) return res.status(401).json({ error: 'Invalid password' });

  const token = generateToken(user.id);
  res.json({ token, user: { id: user.id, email: user.email } });
}));

5. RESTful Routes with CRUD Operations

const userRouter = express.Router();

// GET all users (with pagination)
userRouter.get('/', authenticateToken, asyncHandler(async (req, res) => {
  const { page = 1, limit = 20 } = req.query;
  const users = await User.findAndCountAll({
    offset: (page - 1) * limit,
    limit: parseInt(limit)
  });

  res.json({
    data: users.rows,
    pagination: { page, limit, total: users.count }
  });
}));

// GET single user
userRouter.get('/:id', authenticateToken, asyncHandler(async (req, res) => {
  const user = await User.findByPk(req.params.id);
  if (!user) return res.status(404).json({ error: 'Not found' });
  res.json({ data: user });
}));

// POST create user
userRouter.post('/', asyncHandler(async (req, res) => {
  const { email, password } = req.body;
  const hashedPassword = await bcrypt.hash(password, 10);

  const user = await User.create({
    email,
    password: hashedPassword
  });

  res.status(201).json({ data: user });
}));

// PATCH update user
userRouter.patch('/:id', authenticateToken, asyncHandler(async (req, res) => {
  const user = await User.findByPk(req.params.id);
  if (!user) return res.status(404).json({ error: 'Not found' });

  await user.update(req.body, {
    fields: ['email', 'role']
  });

  res.json({ data: user });
}));

// DELETE user
userRouter.delete('/:id', authenticateToken, asyncHandler(async (req, res) => {
  const user = await User.findByPk(req.params.id);
  if (!user) return res.status(404).json({ error: 'Not found' });

  await user.destroy();
  res.status(204).send();
}));

app.use('/api/users', userRouter);

6. Error Handling Middleware

class AppError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.statusCode = statusCode;
    Error.captureStackTrace(this, this.constructor);
  }
}

app.use((err, req, res, next) => {
  err.statusCode = err.statusCode || 500;

  if (err.name === 'SequelizeValidationError') {
    return res.status(400).json({
      error: 'Validation failed',
      details: err.errors.map(e => ({ field: e.path, message: e.message }))
    });
  }

  if (process.env.NODE_ENV === 'production') {
    return res.status(err.statusCode).json({
      error: err.message,
      requestId: req.id
    });
  }

  res.status(err.statusCode).json({
    error: err.message,
    stack: err.stack
  });
});

app.use((req, res) => {
  res.status(404).json({ error: 'Route not found' });
});

7. Environment Configuration

require('dotenv').config();

const config = {
  port: process.env.PORT || 3000,
  env: process.env.NODE_ENV || 'development',
  database: {
    url: process.env.DATABASE_URL,
    dialect: 'postgres'
  },
  jwt: {
    secret: process.env.JWT_SECRET,
    expiresIn: '24h'
  },
  cors: {
    origin: process.env.CORS_ORIGIN || 'http://localhost:3000'
  }
};

module.exports = config;

Best Practices

✅ DO

  • Use middleware for cross-cutting concerns
  • Implement proper error handling
  • Validate input data before processing
  • Use async/await for async operations
  • Implement authentication on protected routes
  • Use environment variables for configuration
  • Add logging and monitoring
  • Use HTTPS in production
  • Implement rate limiting
  • Keep route handlers focused and small

❌ DON'T

  • Handle errors silently
  • Store sensitive data in code
  • Use synchronous operations in routes
  • Forget to validate user input
  • Implement authentication in route handlers
  • Use callback hell (use promises/async-await)
  • Expose stack traces in production
  • Trust client-side validation only

Complete Example

const express = require('express');
const jwt = require('jsonwebtoken');
const { Sequelize, DataTypes } = require('sequelize');

const app = express();
app.use(express.json());

const sequelize = new Sequelize('postgres://user:pass@localhost/db');

const User = sequelize.define('User', {
  email: DataTypes.STRING,
  password: DataTypes.STRING
});

const authenticateToken = (req, res, next) => {
  const token = req.headers['authorization']?.split(' ')[1];
  jwt.verify(token, 'secret', (err, user) => {
    if (err) return res.status(403).json({ error: 'Forbidden' });
    req.user = user;
    next();
  });
};

app.get('/users', authenticateToken, async (req, res, next) => {
  try {
    const users = await User.findAll();
    res.json({ data: users });
  } catch (err) {
    next(err);
  }
});

app.post('/users', async (req, res, next) => {
  try {
    const user = await User.create(req.body);
    res.status(201).json({ data: user });
  } catch (err) {
    next(err);
  }
});

app.listen(3000, () => console.log('Server running on port 3000'));

Quick Install

/plugin add https://github.com/aj-geddes/useful-ai-prompts/tree/main/nodejs-express-server

Copy and paste this command in Claude Code to install this skill

GitHub 仓库

aj-geddes/useful-ai-prompts
Path: skills/nodejs-express-server

Related Skills

sglang

Meta

SGLang is a high-performance LLM serving framework that specializes in fast, structured generation for JSON, regex, and agentic workflows using its RadixAttention prefix caching. It delivers significantly faster inference, especially for tasks with repeated prefixes, making it ideal for complex, structured outputs and multi-turn conversations. Choose SGLang over alternatives like vLLM when you need constrained decoding or are building applications with extensive prefix sharing.

View skill

evaluating-llms-harness

Testing

This Claude Skill runs the lm-evaluation-harness to benchmark LLMs across 60+ standardized academic tasks like MMLU and GSM8K. It's designed for developers to compare model quality, track training progress, or report academic results. The tool supports various backends including HuggingFace and vLLM models.

View skill

llamaguard

Other

LlamaGuard is Meta's 7-8B parameter model for moderating LLM inputs and outputs across six safety categories like violence and hate speech. It offers 94-95% accuracy and can be deployed using vLLM, Hugging Face, or Amazon SageMaker. Use this skill to easily integrate content filtering and safety guardrails into your AI applications.

View skill

langchain

Meta

LangChain is a framework for building LLM applications using agents, chains, and RAG pipelines. It supports multiple LLM providers, offers 500+ integrations, and includes features like tool calling and memory management. Use it for rapid prototyping and deploying production systems like chatbots, autonomous agents, and question-answering services.

View skill