- All route handlers must live in
src/routes/with one file per logical domain (e.g.,src/routes/users.ts,src/routes/products.ts). Never put routes inindex.ts. - All business logic must live in
src/services/with one file per domain (e.g.,src/services/UserService.ts). Services are classes with static methods or instance methods, never functions. - All database queries must live in
src/repositories/with one file per entity (e.g.,src/repositories/UserRepository.ts). Repositories are classes, never raw query functions. - All middleware must live in
src/middleware/with descriptive names (e.g.,src/middleware/authMiddleware.ts,src/middleware/validationMiddleware.ts). - All custom error classes must live in
src/errors/with one file per error type (e.g.,src/errors/ValidationError.ts,src/errors/NotFoundError.ts). - All type definitions must live in
src/types/with one file per domain (e.g.,src/types/user.ts,src/types/product.ts). Never inline interfaces in route files. - All validators must live in
src/validators/using Zod schemas (e.g.,src/validators/userValidator.ts). One schema per entity. - All tests must live in
src/__tests__/mirroring the source structure (e.g.,src/__tests__/services/UserService.test.ts). src/index.tsmust only import and wire together middleware, routes, and error handlers. Maximum 50 lines.
- Use
constexclusively. Never useletorvar. - All function names must be camelCase. All class names must be PascalCase. All constants must be UPPER_SNAKE_CASE.
- All exported functions and classes must have explicit return type annotations. Never use implicit
anyreturns. - File names must be camelCase for utilities and middleware (e.g.,
authMiddleware.ts), PascalCase for classes (e.g.,UserService.ts). - All imports must use absolute paths from
src/(e.g.,import { UserService } from 'src/services/UserService'). Never use relative paths like../../../. - Use
export constfor named exports only. Never useexport default. - All object properties in types must use explicit types, never
any. Useunknownif truly unknown, then narrow with type guards.
- Never use
astype assertions outside of test files. Use type guards or Zod.parse()instead. - All function parameters must have explicit types. No implicit
any. - All Express route handlers must have explicit types:
(req: Request, res: Response, next: NextFunction): void => { }. Never omitnext. - All
req.bodyaccess must be preceded by validation using Zod. Never trustreq.bodydirectly. - All
req.paramsandreq.querymust be validated with Zod before use. - All database query results must be validated against their expected type using Zod or explicit type guards.
- Never use
Object,object, or{}as types. UseRecord<string, unknown>or specific interfaces.
- All custom errors must extend
Errorand include astatusCodeproperty (e.g.,class ValidationError extends Error { statusCode = 400; }). - All async functions must have try/catch blocks. Caught errors must be typed:
catch (err) { if (err instanceof AppError) { ... } else { throw new UnexpectedError(); } }. - All route handlers must call
next(err)when catching errors, neverres.status().json()directly in catch blocks. - Error middleware must be the last middleware registered in
src/index.ts. It must catch all errors and return a structured response with{ error: string; statusCode: number; }— never raw error messages. - Never return
error.messagedirectly to the client. Map errors to user-safe messages in the error middleware. - All errors returned to the client must have a
statusCodebetween 400-599. Never return 200 with an error. - Validation errors must return 400 with a
{ error: string; details: Record<string, string[]>; }structure from Zod.safeParse().
- All POST/PUT/PATCH handlers must validate
req.bodyusing a Zod schema before accessing any property. - All GET handlers with query parameters must validate
req.queryusing a Zod schema. - All route parameters (
:id,:slug) must be validated with Zod before passing to services. - Validation must happen in middleware or at the start of the route handler, never deep in business logic.
- Zod schemas must be defined in
src/validators/and imported, never inline in route files.
- Never hardcode secrets, API keys, or database credentials. All must come from environment variables via
process.env. - All environment variables must be validated at startup using Zod in
src/config/env.ts. The app must crash if required vars are missing. - Never log
req.body,req.headers, orreq.querydirectly. Sanitize sensitive fields before logging. - All user input must be trimmed and validated for length before storage:
Zod.string().trim().max(255). - Never use
eval(),Function(), or dynamicrequire()with user input. - All database queries must use parameterized queries or ORM methods, never string concatenation.
- CORS must be explicitly configured in
src/middleware/corsMiddleware.tswith a whitelist, never*.
- All services must have unit tests in
src/__tests__/services/with.test.tsextension. - All route handlers must have integration tests in
src/__tests__/routes/with.test.tsextension. - All tests must use Jest with
describe()andit()blocks. Never usetest(). - All async tests must use
async/await, never.then()chains. - All mocked dependencies must be imported with
jest.mock()at the top of the test file. - All tests must clean up database state in
afterEach()hooks. - Error cases must be tested explicitly: test that invalid input returns 400, that missing auth returns 401, etc.
- Test files must have at least 80% coverage of the service or route they test.
- All route files must export a single function:
export const setupUserRoutes = (app: Express): void => { }. - All middleware must be typed:
(req: Request, res: Response, next: NextFunction): void => { }or(err: Error, req: Request, res: Response, next: NextFunction): void => { }for error middleware. - All route handlers must be async functions that call
next(err)on error, neverres.status().json()in catch blocks. - All responses must use
res.status(code).json(data), neverres.send()orres.end(). - All successful responses must return
{ data: T; }or{ data: T[]; }structure, never raw objects. - All 404 responses must be handled by a catch-all route at the end of
src/index.tsthat returns{ error: 'Not Found'; statusCode: 404; }.
Source: Codelibrium — the marketplace for AI behaviour files. Browse multiple rulesets at codelibrium.com or install via CLI:
npx codelibrium-cli install <ruleset-name>