소스 정보
- 저장소
- diegosouzapw/awesome-omni-skill
- 최근 소스 활동
- 2026년 2월 28일 04:03
- 감지된 SKILL.md 언어
- 영어
- 스타
- 50
- 포크
- 19
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/diegosouzapw/awesome-omni-skill --skill api-framework-express명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Token-efficient tracking for AI orchestration. CLI-first for status updates (~50 tokens), agent fallback for complex ops (~1KB). Use when: updating task status, querying blockers, creating progress files, validating phases.
AshAi extension guidelines for integrating AI capabilities with Ash Framework. Use when implementing vectorization/embeddings, exposing Ash actions as LLM tools, creating prompt-backed actions, or setting up MCP servers. Covers semantic search, LangChain integration, and structured outputs.
This skill should be used when solving hard questions, complex architectural problems, or debugging issues that benefit from GPT-5 Pro or GPT-5.1 thinking models with large file context. Use when standard Claude analysis needs deeper reasoning or extended context windows.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | api-framework-express |
| description | Express.js routes, middleware, error handling, request/response patterns |
Quick Guide: Use Express.js for building REST APIs with middleware-based request processing. The framework excels at composable middleware chains, modular routing via
express.Router(), and centralized error handling with 4-argument error middleware(err, req, res, next).
<critical_requirements>
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST define error-handling middleware with 4 arguments: (err, req, res, next))
(You MUST register error handlers AFTER all routes and other middleware)
(You MUST call next(err) to forward async errors in Express 4 - Express 5 handles this automatically)
(You MUST use express.json() and express.urlencoded() for body parsing)
</critical_requirements>
Auto-detection: Express.js, express, app.use, app.get, app.post, app.put, app.delete, express.Router, req.params, req.query, req.body, res.json, res.status, middleware, next(), error handler, router.use, express.static, express.json, express.urlencoded
When to use:
express.Router()When NOT to use:
Key patterns covered:
app.use() and next()app.get/post/put/delete and route parametersexpress.Router()res.json() and res.status()express.static()Detailed Resources:
Middleware-first architecture. Express processes requests through a chain of middleware functions. Each middleware can modify request/response objects, end the response, or call next() to continue the chain.
Use Express when: Need mature ecosystem with extensive middleware library, building traditional REST APIs, team familiarity with Express patterns.
Use alternatives when: Need OpenAPI generation (Hono), edge deployment (Hono/Fastify), strict type safety with schema validation (tRPC).
Set up Express with body parsing middleware and basic configuration.
const PORT = 3000;
const JSON_LIMIT = "10mb";
// src/app.ts
import express from "express";
import type { Express } from "express";
import { userRoutes } from "./routes/user-routes";
import { productRoutes } from "./routes/product-routes";
import { errorHandler } from "./middleware/error-handler";
const app: Express = express();
// Built-in middleware for body parsing
app.use(express.json({ limit: JSON_LIMIT }));
app.use(express.urlencoded({ extended: true }));
// Mount route modules
app.use("/api/users", userRoutes);
app.use("/api/products", productRoutes);
// Error handler MUST be last
app.use(errorHandler);
export { app };
Why good: Named constants for configuration, built-in body parsers registered early, error handler registered last, modular route mounting
// WRONG: Magic strings and error handler in wrong position
const app = express();
app.use(errorHandler); // Error handler too early - won't catch route errors
app.use(express.json({ limit: "10mb" })); // Magic string
app.use("/api/users", userRoutes);
Why bad: Error handler before routes means it never catches errors, magic strings make configuration hard to maintain
Create modular, mountable route handlers for better organization.
// src/routes/user-routes.ts
import { Router } from "express";
import type { Request, Response, NextFunction } from "express";
const router = Router();
const HTTP_OK = 200;
const HTTP_CREATED = 201;
const HTTP_NOT_FOUND = 404;
// GET /api/users
router.get("/", async (req: Request, res: Response, next: NextFunction) => {
try {
const users = await getUsersFromDatabase();
res.status(HTTP_OK).json({ data: users });
} catch (error) {
next(error); // Forward to error handler
}
});
// GET /api/users/:id
router.get("/:id", async (req: Request, res: , : ) => {
{
{ id } = req.;
user = (id);
(!user) {
res.().({ : });
;
}
res.().({ : user });
} (error) {
(error);
}
});
router.(, (: , : , : ) => {
{
userData = req.;
newUser = (userData);
res.().({ : newUser });
} (error) {
(error);
}
});
{ router userRoutes };
Why good: Router isolates related routes, named HTTP status constants, explicit error forwarding with next(error), named export follows convention
// WRONG: All routes in main app file
const app = express();
app.get("/api/users", (req, res) => {
/* ... */
});
app.get("/api/users/:id", (req, res) => {
/* ... */
});
app.post("/api/users", (req, res) => {
/* ... */
});
app.get("/api/products", (req, res) => {
/* ... */
});
// ... hundreds more lines
export default app; // Default export
Why bad: God file with all routes, no separation of concerns, default export violates convention
Error handlers MUST have 4 arguments: (err, req, res, next).
// src/middleware/error-handler.ts
import type { Request, Response, NextFunction } from "express";
const HTTP_BAD_REQUEST = 400;
const HTTP_INTERNAL_ERROR = 500;
interface AppError extends Error {
statusCode?: number;
code?: string;
}
const errorHandler = (
err: AppError,
req: Request,
res: Response,
next: NextFunction,
): void => {
console.error(`[Error] ${req.method} ${req.path}:`, err.message);
// Already sent response - delegate to default handler
if (res.headersSent) {
next(err);
return;
}
const statusCode = err.statusCode || HTTP_INTERNAL_ERROR;
const message = err.message || "Internal server error";
res.status(statusCode).({
: {
message,
: err. || ,
: req.,
},
});
};
{ errorHandler };
Why good: 4 arguments identifies this as error middleware, checks headersSent to avoid double-response, logs with request context, consistent error shape
// WRONG: Only 3 arguments - Express won't recognize as error handler
const errorHandler = (err, req, res) => {
res.status(500).send("Error"); // Magic number
};
// WRONG: Not checking headersSent
const errorHandler = (err, req, res, next) => {
res.status(500).json({ error: err.message }); // May crash if headers sent
};
Why bad: 3-argument function treated as regular middleware (ignores err), not checking headersSent causes "headers already sent" crashes
Forward errors from async functions to the error handler.
// src/routes/product-routes.ts
import { Router } from "express";
import type { Request, Response, NextFunction } from "express";
const router = Router();
const HTTP_OK = 200;
// Option 1: try/catch with next(error)
router.get("/:id", async (req: Request, res: Response, next: NextFunction) => {
try {
const product = await getProductById(req.params.id);
res.status(HTTP_OK).json({ data: product });
} catch (error) {
next(error); // REQUIRED in Express 4
}
});
// Option 2: Promise .catch(next)
router.get("/featured", (req: Request, res: Response, next: NextFunction) => {
getFeaturedProducts()
.( res.().({ : products }))
.(next);
});
{ router productRoutes };
// src/utils/async-handler.ts
import type { Request, Response, NextFunction, RequestHandler } from "express";
type AsyncHandler = (
req: Request,
res: Response,
next: NextFunction,
) => Promise<void>;
const asyncHandler = (fn: AsyncHandler): RequestHandler => {
return (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
};
export { asyncHandler };
// Usage with wrapper
import { asyncHandler } from "../utils/async-handler";
router.get(
"/:id",
asyncHandler(async (req, res) => {
const product = await getProductById(req.params.id);
res.status(HTTP_OK).json({ data: product });
// Errors automatically forwarded to error handler
}),
);
Why good: asyncHandler removes try/catch boilerplate, errors automatically forwarded, cleaner route definitions
// WRONG: Missing error forwarding in Express 4
router.get("/:id", async (req, res) => {
const product = await getProductById(req.params.id); // Error = unhandled rejection
res.json({ data: product });
});
Why bad: Async errors not caught by Express 4, causes unhandled promise rejection and request hangs
Validate request data before handlers process it.
// src/middleware/validate-request.ts
import type { Request, Response, NextFunction } from "express";
const HTTP_BAD_REQUEST = 400;
const MIN_NAME_LENGTH = 1;
const MAX_NAME_LENGTH = 100;
interface UserCreateBody {
name: string;
email: string;
}
const validateUserCreate = (
req: Request,
res: Response,
next: NextFunction,
): void => {
const { name, email } = req.body as UserCreateBody;
const errors: string[] = [];
if (!name || name.length < MIN_NAME_LENGTH || name.length > MAX_NAME_LENGTH) {
errors.push(
`Name must be between ${MIN_NAME_LENGTH} and ${MAX_NAME_LENGTH} characters`,
);
}
if (!email || !email.includes()) {
errors.();
}
(errors. > ) {
res.().({
: {
: ,
: errors,
},
});
;
}
();
};
{ validateUserCreate };
// Apply validation middleware to route
router.post("/", validateUserCreate, async (req, res, next) => {
try {
// req.body is validated at this point
const user = await createUser(req.body);
res.status(HTTP_CREATED).json({ data: user });
} catch (error) {
next(error);
}
});
Why good: Validation separated from business logic, named constants for limits, early return on validation failure, reusable across routes
Access dynamic URL segments and query parameters.
// src/routes/search-routes.ts
import { Router } from "express";
import type { Request, Response, NextFunction } from "express";
const router = Router();
const HTTP_OK = 200;
const DEFAULT_PAGE = 1;
const DEFAULT_LIMIT = 20;
const MAX_LIMIT = 100;
interface SearchQuery {
q?: string;
page?: string;
limit?: string;
sort?: string;
}
// GET /api/search?q=term&page=1&limit=20&sort=date
router.get("/", async (req: Request, res: Response, next: NextFunction) => {
try {
const { q, page, limit, sort } = req.query as SearchQuery;
const pageNum = (page || (), );
limitNum = .(
(limit || (), ),
,
);
results = ({
: q || ,
: pageNum,
: limitNum,
: sort || ,
});
res.().({
: results.,
: {
: pageNum,
: limitNum,
: results.,
},
});
} (error) {
(error);
}
});
router.(
,
(: , : , : ) => {
{
{ userId, postId } = req.;
post = (userId, postId);
res.().({ : post });
} (error) {
(error);
}
},
);
{ router searchRoutes };
Why good: Query params typed, default values with named constants, parseInt with radix 10, limit capped at MAX_LIMIT to prevent abuse
Protect routes with middleware that validates access.
// src/middleware/auth-guard.ts
import type { Request, Response, NextFunction } from "express";
const HTTP_UNAUTHORIZED = 401;
const HTTP_FORBIDDEN = 403;
interface AuthenticatedRequest extends Request {
user?: {
id: string;
role: string;
};
}
const requireAuth = (
req: AuthenticatedRequest,
res: Response,
next: NextFunction,
): void => {
const token = req.headers.authorization?.replace("Bearer ", "");
if (!token) {
res.status(HTTP_UNAUTHORIZED).json({
error: { message: "Authentication required" },
});
return;
}
try {
// Verify token with your auth solution
const user = verifyToken(token);
req.user = user;
();
} {
res.().({
: { : },
});
}
};
= () => {
(
: ,
: ,
: ,
): {
(!req.) {
res.().({
: { : },
});
;
}
(!allowedRoles.(req..)) {
res.().({
: { : },
});
;
}
();
};
};
{ requireAuth, requireRole };
{ };
// Apply guards to routes
import { requireAuth, requireRole } from "../middleware/auth-guard";
// All routes in this router require authentication
router.use(requireAuth);
// Only admins can delete users
router.delete("/:id", requireRole(["admin"]), async (req, res, next) => {
try {
await deleteUser(req.params.id);
res.status(HTTP_OK).json({ message: "User deleted" });
} catch (error) {
next(error);
}
});
Why good: Auth middleware reusable, role-based guard configurable, extends Request type for type safety, clear separation of auth concerns
Serve static assets and use Express built-in middleware.
// src/app.ts
import express from "express";
import path from "path";
const app = express();
const STATIC_MAX_AGE_MS = 86400000; // 1 day in milliseconds
// Serve static files from 'public' directory
app.use(
express.static(path.join(__dirname, "public"), {
maxAge: STATIC_MAX_AGE_MS,
etag: true,
}),
);
// Serve uploaded files from 'uploads' with restricted access
app.use(
"/uploads",
requireAuth, // Protect uploads
express.static(path.join(__dirname, "uploads")),
);
export { app };
Why good: Caching configured with named constant, path.join for cross-platform compatibility, protected static route with auth middleware
Standardize API responses for predictable client consumption.
// src/utils/response-helpers.ts
import type { Response } from "express";
const HTTP_OK = 200;
const HTTP_CREATED = 201;
const HTTP_NO_CONTENT = 204;
const HTTP_BAD_REQUEST = 400;
const HTTP_NOT_FOUND = 404;
interface SuccessResponse<T> {
success: true;
data: T;
meta?: Record<string, unknown>;
}
interface ErrorResponse {
success: false;
error: {
message: string;
code?: string;
details?: unknown;
};
}
const sendSuccess = <T>(
res: Response,
data: T,
statusCode: number = HTTP_OK,
meta?: Record<string, unknown>,
): => {
: <T> = { : , data };
(meta) {
response. = meta;
}
res.(statusCode).(response);
};
sendCreated = <T>(: , : T): {
(res, data, );
};
sendNoContent = (: ): {
res.().();
};
sendError = (
: ,
: ,
: = ,
?: ,
?: ,
): {
: = {
: ,
: { message, code, details },
};
res.(statusCode).(response);
};
sendNotFound = (: , : = ): {
(res, , , );
};
{ sendSuccess, sendCreated, sendNoContent, sendError, sendNotFound };
// Usage in routes
import {
sendSuccess,
sendCreated,
sendNotFound,
} from "../utils/response-helpers";
router.get("/:id", async (req, res, next) => {
try {
const user = await getUserById(req.params.id);
if (!user) {
sendNotFound(res, "User");
return;
}
sendSuccess(res, user);
} catch (error) {
next(error);
}
});
Why good: Consistent response shape, typed responses, reusable helpers reduce boilerplate, status codes as named constants
Order matters for security, parsing, and error handling.
// src/app.ts
import express from "express";
import helmet from "helmet";
import cors from "cors";
import rateLimit from "express-rate-limit";
const app = express();
const RATE_LIMIT_WINDOW_MS = 900000; // 15 minutes
const RATE_LIMIT_MAX_REQUESTS = 100;
const JSON_LIMIT = "10mb";
// 1. Security headers FIRST
app.use(helmet());
// 2. CORS configuration
app.use(
cors({
origin: process.env.ALLOWED_ORIGINS?.split(",") || [],
credentials: true,
}),
);
// 3. Rate limiting (before body parsing to save resources)
app.use(
rateLimit({
windowMs: RATE_LIMIT_WINDOW_MS,
max: RATE_LIMIT_MAX_REQUESTS,
standardHeaders: true,
legacyHeaders: false,
}),
);
// 4. Body parsing
app.(express.({ : _LIMIT }));
app.(express.({ : }));
app.(requestLogger);
app.(, userRoutes);
app.(, productRoutes);
app.( {
res.().({ : { : } });
});
app.(errorHandler);
{ app };
Why good: Security (helmet) first, rate limiting before expensive body parsing, error handler absolutely last, 404 handler catches unmatched routes
Works with:
req.body in middleware before handlersnext(error)Replaces / Conflicts with:
<critical_reminders>
Before implementing ANY Express route, verify these requirements are met:
All code must follow project conventions in CLAUDE.md
(You MUST define error-handling middleware with 4 arguments: (err, req, res, next))
(You MUST register error handlers AFTER all routes and other middleware)
(You MUST call next(err) to forward async errors in Express 4 - Express 5 handles this automatically)
(You MUST use express.json() and express.urlencoded() for body parsing)
Failure to follow these rules will cause unhandled errors and broken middleware chains.
</critical_reminders>