Use when adding new error messages to React, or seeing "unknown error code" warnings.
npx skills add kumaran-is/claude-code-onboarding --skill "nodejs-typescript"
Install specific skill from multi-skill repository
# Description
Patterns and templates for Node.js 24 / TypeScript 5.x development. Activate when creating Node.js services, Express/Fastify APIs, TypeScript utilities, npm packages, or tests.
# SKILL.md
name: nodejs-typescript
description: Patterns and templates for Node.js 24 / TypeScript 5.x development. Activate when creating Node.js services, Express/Fastify APIs, TypeScript utilities, npm packages, or tests.
allowed-tools: Bash, Read, Write, Edit
Node.js 24 + TypeScript 5.x Development Skill
Quick Scaffold β New Node.js/TypeScript Project
mkdir my-service && cd my-service
npm init -y
npm install typescript @types/node tsx --save-dev
npm install express zod dotenv
npm install @types/express --save-dev
npx tsc --init
package.json Essentials
{
"name": "my-service",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc",
"start": "node dist/index.js",
"test": "vitest run",
"test:watch": "vitest",
"lint": "eslint src/",
"typecheck": "tsc --noEmit"
},
"engines": {
"node": ">=24.0.0"
}
}
tsconfig.json
{
"compilerOptions": {
"target": "ES2024",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"esModuleInterop": true,
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"sourceMap": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"isolatedModules": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "tests"]
}
Express App Template
// src/app.ts
import express from 'express';
import { errorHandler } from './middleware/error-handler.js';
import { userRouter } from './routes/user.routes.js';
const app = express();
app.use(express.json());
app.use('/api/v1/users', userRouter);
app.use(errorHandler);
export { app };
// src/index.ts
import { app } from './app.js';
const PORT = process.env.PORT ?? 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
Zod Validation + Type Inference
import { z } from 'zod';
export const CreateUserSchema = z.object({
email: z.string().email(),
name: z.string().min(1).max(100),
role: z.enum(['admin', 'user', 'viewer']).default('user'),
});
export type CreateUserDto = z.infer<typeof CreateUserSchema>;
// In route handler:
const dto = CreateUserSchema.parse(req.body); // throws ZodError on invalid input
Error Handler Middleware
import { Request, Response, NextFunction } from 'express';
import { ZodError } from 'zod';
export function errorHandler(err: Error, req: Request, res: Response, next: NextFunction) {
if (err instanceof ZodError) {
res.status(400).json({ error: 'Validation failed', details: err.errors });
return;
}
console.error(err);
res.status(500).json({ error: 'Internal server error' });
}
Route Template
import { Router, Request, Response, NextFunction } from 'express';
import { CreateUserSchema } from '../models/user.schema.js';
import { userService } from '../services/user.service.js';
export const userRouter = Router();
userRouter.get('/', async (req: Request, res: Response, next: NextFunction) => {
try {
const users = await userService.findAll();
res.json({ data: users });
} catch (error) {
next(error);
}
});
userRouter.post('/', async (req: Request, res: Response, next: NextFunction) => {
try {
const dto = CreateUserSchema.parse(req.body);
const user = await userService.create(dto);
res.status(201).json(user);
} catch (error) {
next(error);
}
});
Vitest Test Template
import { describe, it, expect } from 'vitest';
import request from 'supertest';
import { app } from '../src/app.js';
describe('User API', () => {
it('POST /api/v1/users returns 201', async () => {
const res = await request(app)
.post('/api/v1/users')
.send({ email: '[email protected]', name: 'Test User' });
expect(res.status).toBe(201);
expect(res.body.email).toBe('[email protected]');
});
it('POST /api/v1/users returns 400 on invalid email', async () => {
const res = await request(app)
.post('/api/v1/users')
.send({ email: 'not-an-email', name: 'Test' });
expect(res.status).toBe(400);
});
});
Docker Template
FROM node:24-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:24-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
RUN npm ci --omit=dev
EXPOSE 3000
CMD ["node", "dist/index.js"]
# Supported AI Coding Agents
This skill is compatible with the SKILL.md standard and works with all major AI coding agents:
Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.