agentsclimarketplace

Nodejs typescript server

Skill Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack/plugins/devtools-pack/skills/nodejs-typescript-server

A curated pack of custom Claude Code skills for developers — installable as a Claude Code plugin marketplace.

Install
npx -y skills add Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack --skill nodejs-typescript-server

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

When to activate: Express with TypeScript, middleware patterns, REST API design, error handling, OpenAPI, JWT auth, rate limiting

SKILL.md

5.6 KB, as published. Nobody here has run it

Node.js TypeScript Server Patterns

Project Structure

src/
├── index.ts               # Entry: create app, start server
├── app.ts                 # Express factory: middlewares, routes
├── config/
│   └── env.ts             # Zod-validated env
├── middleware/
│   ├── auth.ts            # JWT auth
│   ├── rateLimit.ts
│   └── errorHandler.ts
├── routes/
│   └── v1/
│       ├── index.ts
│       └── users.ts
├── services/
│   └── userService.ts
├── repositories/
│   └── userRepository.ts
├── types/
│   └── express.d.ts       # Request augmentation
└── lib/
    └── logger.ts          # Pino

App Factory

// src/app.ts
import express from 'express'
import helmet from 'helmet'
import cors from 'cors'
import { json } from 'express'
import { v1Router } from './routes/v1'
import { errorHandler } from './middleware/errorHandler'
import { notFoundHandler } from './middleware/notFoundHandler'

export function createApp() {
  const app = express()

  app.use(helmet())
  app.use(cors({ origin: process.env.CORS_ORIGIN, credentials: true }))
  app.use(json({ limit: '1mb' }))

  app.get('/health', (_req, res) => res.json({ status: 'ok', ts: Date.now() }))
  app.use('/api/v1', v1Router)

  app.use(notFoundHandler)
  app.use(errorHandler)

  return app
}

Auth Middleware (JWT)

// middleware/auth.ts
import { Request, Response, NextFunction } from 'express'
import jwt from 'jsonwebtoken'
import { env } from '../config/env'

interface TokenPayload { sub: string; role: string; iat: number; exp: number }

declare module 'express' {
  interface Request { user?: TokenPayload }
}

export function authenticate(req: Request, res: Response, next: NextFunction) {
  const header = req.headers.authorization
  if (!header?.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Missing token' })
  }
  try {
    const token   = header.slice(7)
    req.user = jwt.verify(token, env.JWT_SECRET) as TokenPayload
    next()
  } catch {
    res.status(401).json({ error: 'Invalid token' })
  }
}

export function authorize(...roles: string[]) {
  return (req: Request, res: Response, next: NextFunction) => {
    if (!req.user || !roles.includes(req.user.role)) {
      return res.status(403).json({ error: 'Forbidden' })
    }
    next()
  }
}

Error Handler

// middleware/errorHandler.ts
import { Request, Response, NextFunction } from 'express'
import { ZodError } from 'zod'
import { logger } from '../lib/logger'

export class AppError extends Error {
  constructor(
    public status: number,
    message: string,
    public details?: unknown
  ) { super(message) }
}

export function errorHandler(
  err: unknown,
  _req: Request,
  res: Response,
  _next: NextFunction
) {
  if (err instanceof ZodError) {
    return res.status(422).json({
      error: 'Validation failed',
      details: err.flatten(),
    })
  }

  if (err instanceof AppError) {
    return res.status(err.status).json({
      error: err.message,
      ...(err.details ? { details: err.details } : {}),
    })
  }

  logger.error(err, 'Unhandled error')
  res.status(500).json({ error: 'Internal server error' })
}

Route Handler Pattern

// routes/v1/users.ts
import { Router } from 'express'
import { z } from 'zod'
import { authenticate } from '../../middleware/auth'
import { userService } from '../../services/userService'
import { AppError } from '../../middleware/errorHandler'

const router = Router()

const CreateUserSchema = z.object({
  name:  z.string().min(1).max(100),
  email: z.string().email(),
})

router.get('/', authenticate, async (req, res, next) => {
  try {
    const { page = 1, limit = 20 } = req.query
    const result = await userService.list({ page: Number(page), limit: Number(limit) })
    res.json(result)
  } catch (err) { next(err) }
})

router.post('/', async (req, res, next) => {
  try {
    const data = CreateUserSchema.parse(req.body)
    const user = await userService.create(data)
    res.status(201).json(user)
  } catch (err) { next(err) }
})

router.get('/:id', authenticate, async (req, res, next) => {
  try {
    const user = await userService.getById(req.params.id)
    if (!user) throw new AppError(404, 'User not found')
    res.json(user)
  } catch (err) { next(err) }
})

export { router as usersRouter }

Rate Limiting

import rateLimit from 'express-rate-limit'
import RedisStore from 'rate-limit-redis'

export const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,  // 15 min
  max: 100,
  standardHeaders: true,
  legacyHeaders: false,
  store: new RedisStore({ client: redisClient }),
  keyGenerator: (req) => req.user?.sub ?? req.ip ?? 'unknown',
  handler: (_req, res) => res.status(429).json({ error: 'Too many requests' }),
})

export const strictLimiter = rateLimit({
  windowMs: 60_000,
  max: 5,
  message: { error: 'Too many attempts, try again in 1 minute' },
})

Logger (Pino)

// lib/logger.ts
import pino from 'pino'

export const logger = pino({
  level: process.env.LOG_LEVEL ?? 'info',
  ...(process.env.NODE_ENV !== 'production' && {
    transport: { target: 'pino-pretty', options: { colorize: true } },
  }),
  redact: ['req.headers.authorization', '*.password', '*.token'],
})

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.