agent-health
Reads production/traces/agent-metrics.jsonl and displays a per-agent performance summary table for the current or a specified…
Applies production backend patterns: middleware, error handling, auth, database integration, and API design. Use when working with backend service files or when the user mentions Express, Fastify, NestJS, backend patterns, or service architecture.
Claude Code
$ npx -y skills add tranhieutt/software_development_department --skill backend-patterns --agent claude-code
Codex
$ npx skills add tranhieutt/software_development_department --skill backend-patterns -a codex -y
Cursor
$ npx skills add tranhieutt/software_development_department --skill backend-patterns -a cursor -y
Gemini CLI
$ npx skills add tranhieutt/software_development_department --skill backend-patterns -a gemini-cli -y
GitHub Copilot
$ npx skills add tranhieutt/software_development_department --skill backend-patterns -a github-copilot -y
OpenCode
$ npx skills add tranhieutt/software_development_department --skill backend-patterns -a opencode -y
Windsurf
$ npx skills add tranhieutt/software_development_department --skill backend-patterns -a windsurf -y
name: backend-patterns type: reference description: "Applies production backend patterns: middleware, error handling, auth, database integration, and API design. Use when working with backend service files or when the user mentions Express, Fastify, NestJS, backend patterns, or service architecture." paths: ["**/*.ts", "**/*.js", "**/server.*", "**/app.*", "**/routes/**"] effort: 3 allowed-tools: Read, Glob, Grep, Write, Edit, Bash context: fork agent: backend-developer user-invocable: true when_to_use: "When building Node.js backend services with Express, Fastify, or similar frameworks"
import express from "express";
import "express-async-errors"; // patches async error handling globally
import helmet from "helmet";
import { rateLimit } from "express-rate-limit";
const app = express();
app.use(helmet());
app.use(express.json({ limit: "10kb" }));
app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }));
// Routes
app.use("/api/v1/users", userRouter);
app.use("/api/v1/products", productRouter);
// 404 handler — must come after all routes
app.use((req, res) => res.status(404).json({ error: "Not found" }));
// Global error handler — must have 4 params
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
const status = err instanceof AppError ? err.statusCode : 500;
res.status(status).json({ error: err.message });
});interface IUserRepository {
findById(id: string): Promise<User | null>;
findByEmail(email: string): Promise<User | null>;
save(user: User): Promise<User>;
delete(id: string): Promise<void>;
}
class PgUserRepository implements IUserRepository {
constructor(private readonly db: Pool) {}
async findById(id: string) {
const { rows } = await this.db.query(
"SELECT * FROM users WHERE id = $1 AND deleted_at IS NULL", [id]
);
return rows[0] ?? null;
}
}class AppError extends Error {
constructor(public message: string, public statusCode: number) { super(message); }
}
class NotFoundError extends AppError { constructor(msg: string) { super(msg, 404); } }
class ForbiddenError extends AppError { constructor(msg: string) { super(msg, 403); } }
class UserService {
async getUser(id: string, requesterId: string): Promise<User> {
const user = await this.repo.findById(id);
if (!user) throw new NotFoundError(`User ${id} not found`);
if (user.id !== requesterId && !isAdmin(requesterId)) throw new ForbiddenError("Access denied");
return user;
}
}import jwt from "jsonwebtoken";
export function authenticate(req: Request, res: Response, next: NextFunction) {
const token = req.headers.authorization?.split(" ")[1];
if (!token) return res.status(401).json({ error: "No token" });
try {
req.user = jwt.verify(token, process.env.JWT_SECRET!) as JWTPayload;
next();
} catch {
res.status(401).json({ error: "Invalid token" });
}
}import { Pool } from "pg";
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
max: 20, // pool size
idleTimeoutMillis: 30_000,
connectionTimeoutMillis: 2_000,
});
// Test connection on startup
async function connectWithRetry(retries = 5, delay = 2000) {
for (let i = 0; i < retries; i++) {
try {
await pool.query("SELECT 1");
console.log("DB connected");
return;
} catch (err) {
if (i === retries - 1) throw err;
await new Promise(r => setTimeout(r, delay * (i + 1))); // exponential backoff
}
}
}const server = app.listen(PORT);
async function shutdown(signal: string) {
console.log(`${signal} received. Shutting down gracefully.`);
server.close(async () => {
await pool.end(); // drain DB connections
process.exit(0);
});
setTimeout(() => process.exit(1), 10_000); // force exit after 10s
}
process.on("SIGTERM", () => shutdown("SIGTERM"));
process.on("SIGINT", () => shutdown("SIGINT"));| Pitfall | Fix | |---|---| | Async handler without try/catch | Use `express-async-errors` package | | `await` inside `forEach` | Use `Promise.all(array.map(async...))` | | Logging raw errors to client | Log internally; return sanitized message to client | | Missing `return` after `res.json()` | Always `return res.json(...)` to stop execution | | Secrets in `config.js` | Use `process.env` + validation on startup |
Reads production/traces/agent-metrics.jsonl and displays a per-agent performance summary table for the current or a specified…
Provides the vendored agent-style v0.3.5 prose rule pack as a portable Claude skill. Use when installing, syncing, applying, or…
Provides Angular best practices for components, modules, services, and reactive patterns. Use when working with Angular…
Records unexpected API behaviors, undocumented caveats, version bugs, or non-obvious workarounds into…
Defines REST and GraphQL API contracts including endpoints, request/response schemas, auth flows, and versioning strategy. Use…
Manages the ADR (Architecture Decision Record) registry. Use when recording tech-stack choices, design patterns, or…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.