
Backend Context
- 1 installs
- 3 repo stars
- Updated June 17, 2026
- davidleonmayor/proyecto-grado-unimayor
Manages backend architecture context and API design for university capstone project.
About
Academic skill documenting backend patterns and API structure for graduation project. Educational reference.
- API design patterns
- Backend documentation
Backend Context by the numbers
- 1 all-time installs (skills.sh)
- Ranked #3,836 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/davidleonmayor/proyecto-grado-unimayor --skill backend-contextAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| repo stars | ★ 3 |
| Last updated | June 17, 2026 |
| Repository | davidleonmayor/proyecto-grado-unimayor ↗ |
What it does
Manages backend architecture context and API design for university capstone project.
Files
Stack
| Technology | Version | Purpose |
|---|---|---|
| Express.js | 5 | HTTP framework |
| TypeScript | 5 | Language |
| Prisma | 6 | ORM |
| MySQL | - | Database |
| Zod | 4 | Env validation |
| express-validator | 7 | Request validation |
| JWT (jsonwebtoken) | 9 | Authentication |
| Winston | 3 | Logging |
| Morgan | 1 | HTTP request logging |
| Multer | 2 | File uploads |
| Brevo | 3 | Transactional emails |
| Nodemailer | 7 | Email (fallback) |
| Jest + ts-jest | - | Testing |
| Supertest | 7 | HTTP testing |
File Naming Example:
- ✅
sendAuthEmail.test.ts(all tests with .test extencion) - ✅
createToken.ts(common files use camel case) - ✅
auth.controller.ts|auth.route.tsauth.schema.tsauth.service.ts(for each repositori spesification) - ✅
AuthMiddleware.ts(Uper camel case for classes) - ❌
create-token.ts(WRONG - do no separate be -) - ❌
sign-up-validation.spec.ts|sing-up-validation.ts(WRONG )
Scope Detection (ASK IF AMBIGUOUS)
| User Says | Action |
|---|---|
| "a test", "one test", "new test", "add test" | Create ONE test() in existing spec |
| "comprehensive tests", "all tests", "test suite", "generate tests" | Create full suite |
| "create route", "create router" | Trigger backend-router skill and add it |
| "create schema", "add validation" | Trigger backend-schema skill and add it |
Examples:
- "Create a test for user sign-up" → ONE test only
- "Generate E2E tests for login page" → Full suite
- "Add a test to verify form validation" → ONE test to existing spec
- "create POST /login route” → ONE route
Directory Structure
backend/
├── prisma/ # Database schema, migrations, seeds
│ ├── schema.prisma # MySQL schema definition
│ ├── migrations/ # Prisma migration history
│ ├── seed.ts # Database seeder
│ └── clear.ts # Database cleanup script
├── src/
│ ├── index.ts # Entry point — instantiates Server
│ ├── server.ts # Server class (middlewares, routes, shutdown)
│ ├── config/ # App configuration (envs, prisma, logger, cors, email clients)
│ ├── routes/ # Route class definitions — mounted under /api/
│ ├── controllers/ # Request handlers for each domain
│ ├── auth/ # Self-contained auth module (routes, controller, service, schema, tests)
│ ├── common/ # Shared code
│ │ ├── middleware/ # Auth, Role, validation, error handling, timeout
│ │ ├── schema/ # Global validation schemas
│ │ └── utils/ # Helpers (asyncHandler, createToken)
│ ├── email/ # Email templates (Brevo / Nodemailer)
│ ├── example/ # Reference module for new features
│ └── __test__/ # Integration / unit tests
├── logs/ # Winston log output (gitignored)
├── docs/ # Additional documentation
└── jest.config.js # Jest + ts-jest configArchitecture
The backend uses two architectural patterns:
Repository pattern — Self-contained modules under src/ with own routes, controller, service, schema, and tests. Each repository owns its full vertical slice.
| Repository | Path | Description |
|---|---|---|
auth | src/auth/ | Authentication, JWT, password flows — details |
Layered pattern — Domains that share src/routes/, src/controllers/ and src/common/. Currently used by the remaining modules while migrating to repository pattern.
| Domain | Routes | Controller |
|---|---|---|
| projects | src/routes/project.routes.ts | src/controllers/project.controller.ts |
| events | src/routes/event.routes.ts | src/controllers/event.controller.ts |
| persons | src/routes/person.routes.ts | src/controllers/person.controller.ts |
Request flow:
Request → Middleware Chain → Route Class → Controller → Service → Prisma → MySQL
↓
schema (express-validator)Layered responsibilities:
| Layer | Responsibility | Location |
|---|---|---|
| Server | Bootstrap, middleware chain, graceful shutdown | src/server.ts |
| Routes | HTTP method + path + middleware stack per endpoint | src/routes/, src/auth/auth.routes.ts |
| Controller | Parse request, call service/prisma, format response | src/controllers/, src/auth/auth.controller.ts |
| Service | Business logic, reusable operations | src/auth/auth.service.ts |
| Schema | Request validation rules (express-validator) | src/auth/auth.schema.ts, src/common/schema/ |
| Middleware | Cross-cutting: auth, roles, timeout, errors, logging | src/common/middleware/ |
| Config | Singletons and env-validated settings | src/config/ |
Request lifecycle:
1. requestTimeout(30s) wraps the request 2. Body parsers (json, urlencoded) with 10mb limit 3. CORS via corsConfig 4. Morgan HTTP logging 5. Routes.init(app) matches the endpoint 6. Route-level middleware chain (e.g. authLimiter → validateSchema → authMiddleware → controller) 7. Controller handles logic, returns response 8. Unmatched routes → notFound (404) 9. Errors → errorHandler (global catch-all)
Critical Patterns
Server Class
server.ts is a class-based Express setup. Middleware order matters:
1. requestTimeout(30000) — 30s global timeout 2. express.json({ limit: '10mb' }) — body parser 3. cors(corsConfig) — CORS 4. morganMiddleware — HTTP logging 5. Routes via Routes.init(app) 6. notFound — 404 handler 7. errorHandler — global error handler (always last)
Route Registration
Routes are class-based and mounted in src/routes/index.ts:
export class Routes {
public static init(app: Application) {
app.use("/api/auth", authRoutes.router);
app.use("/api/projects", projectRoutes.router);
app.use("/api/events", eventRoutes.router);
app.use("/api/persons", personRoutes.router);
}
}All API endpoints live under /api/.
Route Class Pattern
export class MyRoutes {
public router: Router;
private controller: MyController;
private authMiddleware: AuthMiddleware;
constructor() {
this.router = Router();
this.controller = new MyController();
this.authMiddleware = new AuthMiddleware();
this.initRoutes();
}
public initRoutes() {
this.router.get("/",
this.authMiddleware.isAuthenticatedUser,
this.controller.getItems
);
}
}Authentication
- JWT via
Bearertoken inAuthorizationheader AuthMiddleware.isAuthenticatedUserverifies token and attachesreq.user(typePartial<persona>)- Token created with
jsonwebtoken, secret fromJWT_SECRETenv var
Authorization (Roles)
Roles are determined by actores table (many-to-many between persona and trabajo_grado with tipo_rol):
| Middleware | Allows |
|---|---|
isPrivilegedUser | Director, Jurado, Coordinador de Carrera, Decano |
isAdmin | admin, Administrador, Admin |
isCoordinator | Coordinador de Carrera, Coordinador |
isDirectorOrProfessor | Director |
Prisma (Database)
- Singleton in
config/prisma.tsviaPrismaService.getInstance() - Import:
import { prisma } from "../config" - MySQL database, models use Spanish names with
@@map("TABLE_NAME") - Key models:
persona,trabajo_grado,actores,seguimiento_tg,evento
Environment Variables
Validated with Zod in config/envs.ts. Required vars:
NODE_ENV, PORT, DATABASE_URL, JWT_SECRET,
FRONTEND_URL, NODEMAILER_*, BREVO_*Access: import { envs } from "./config"
Validation
Two approaches coexist:
express-validatorviavalidateSchema()middleware — wrapscheckSchema()zod— used for env validation, available for request schemas
Error Handling
Global error handler in common/middleware/errorHandler.ts handles:
- Prisma errors (P2002 conflict, P2025 not found, P2003 FK violation)
- JWT errors (invalid, expired)
- JSON syntax errors
- Generic errors with statusCode
Logging
Winston logger with levels: error, warn, info, http, debug.
- Console + file transports (
logs/error.log,logs/combined.log) - Development: debug level. Production: warn level.
- Import:
import { logger } from "../config"
File Uploads
Multer handles file uploads. Two configs in project.controller.ts:
upload— general file uploads (PDF, images)excelUpload— Excel bulk upload (.xlsx, .xls)
Commands
pnpm dev # Dev server with nodemon (port 4000)
pnpm db:generate # Generate Prisma client
pnpm db:migrate # Run migrations
pnpm db:studio # Open Prisma Studio
pnpm db:seed # Seed database
pnpm db:clear # Clear database
pnpm test # Run tests (uses .env.test)Resources
- Repositories: See references/ for detailed context on each repository module
- auth-context.md — Auth repository: endpoints, schemas, JWT, password flows
Related AI Skills
- `backend-schema`: Guidelines for creating
express-validatorschemas. - `backend-router`: Guidelines for writing class-based Express routers.
Auth Repository — src/auth/
Authentication module: endpoints, patterns, and conventions.
References
| Resource | Description | Path |
|---|---|---|
| Prisma schema | Database models (persona, actores, tipo_rol) | backend/prisma/schema.prisma |
| Global middleware | AuthMiddleware, RoleMiddleware, errorHandler | backend/src/common/middleware/ |
| Email templates | Brevo transactional emails (confirmation, password reset) | backend/src/email/AuthEmail.ts |
| Rate limiter | Auth-specific rate limit (15 req / 15 min) | backend/src/config/limiter.ts |
Directory Structure
src/auth/
├── auth.routes.ts # Route definitions — mounted at /api/auth
├── auth.controller.ts # Request handlers (register, login, password flows)
├── auth.service.ts # Business logic (createUser, findUserByEmail)
├── auth.schema.ts # express-validator schemas per endpoint
├── interfaces/
│ └── authRequest.interface.ts # Extended Request type with user property
├── middlewares/
│ └── validateJwt.ts # JWT validation (module-local, currently empty)
├── utils/
│ ├── jwt.ts # generateJWT({ id, email }) — 6h expiry
│ ├── generateJwt.ts # generateJWT(uid) — 24h expiry (alternative)
│ ├── password.ts # hashPassword(), checkPassword() via bcrypt
│ └── __tests__/
│ └── password.test.ts
└── __tests__/
├── auth.controller.test.ts # Integration tests with supertest
└── auth.service.test.ts # Unit tests with jest mocksAPI Endpoints
All routes under /api/auth. Rate-limited: 15 requests per 15 min (skips successful).
Public Routes
| Method | Path | Schema | Description |
|---|---|---|---|
| POST | /register | RegisterSchema | Create account, returns confirmation token |
| POST | /confirm-account | UserConfirmationSchema | Confirm with 6-digit token |
| POST | /login | UserLoginSchema | Returns JWT as plain string |
| POST | /forgot-password | ForgotPasswordSchema | Sends reset email via Brevo |
| POST | /validate-token | ValidateTokenSchema | Check if reset token is valid |
| POST | /reset-password/:token | ResetPasswordSchema | Set new password with token |
Private Routes (require AuthMiddleware.isAuthenticatedUser)
| Method | Path | Schema | Description |
|---|---|---|---|
| GET | /user | — | Get current user (excludes password) |
| POST | /reset-auth-password | UpdatePasswordSchema | Change password (requires current) |
| POST | /check-password | CheckAuthUserPasswordSchema | Verify current password |
Critical Patterns
Route → Schema → Controller Flow
Every route uses validateSchema() before the controller:
this.router.post(
"/register",
validateSchema(RegisterSchema),
this.authController.register,
);Controller Binding
All controller methods are bound in the constructor to preserve this:
constructor() {
this.authService = new AuthService();
this.register = this.register.bind(this);
this.login = this.login.bind(this);
// ...
}Request Interface
Auth controller uses a custom Request type that includes user:
import type { Request } from "./interfaces/auth-request.interface";
// Request.user is of type User (full Prisma persona)Password Handling
- Hashing:
bcrypt.hash(password, salt=10) - Comparison:
bcrypt.compare(password, hash) - Import:
import { hashPassword, checkPassword } from "./utils/password"
JWT Generation
Two JWT generators exist in utils/:
| File | Payload | Expiry | Used by |
|---|---|---|---|
jwt.ts | { id, email } | 6h | auth.controller.ts (login) |
generate-jwt.ts | { uid } | 24h | Legacy / alternative |
Confirmation Token
6-digit numeric token generated by common/utils/createToken.ts:
Math.floor(100000 + Math.random() * 900000).toString()Stored in persona.token column, cleared on confirmation.
Validation Schemas
Defined in auth.schema.ts using express-validator Schema type:
| Schema | Validates |
|---|---|
RegisterSchema | names, lastNames, typeOfDentityDocument, idDocumentNumber, phoneNumber, email, password |
UserLoginSchema | email, password |
UserConfirmationSchema | token (6 chars) |
ForgotPasswordSchema | |
ValidateTokenSchema | token (6 chars) |
ResetPasswordSchema | token (params), password, confirmPassword |
UpdatePasswordSchema | authorization header, currentPassword, password, confirmPassword |
CheckAuthUserPasswordSchema | authorization header, password |
Password validation rule: min 8 chars, 1 uppercase, 1 lowercase, 1 digit, 1 special char.
Test Patterns
Tests use jest.mock() for prisma and utilities, supertest for HTTP:
jest.mock('@backend/config/prisma', () => ({
prisma: { persona: { findUnique: jest.fn(), create: jest.fn() } }
}));
const server = new Server();
const app = server['app'];
const response = await request(app)
.post('/api/auth/login')
.send({ email, password });Commands
pnpm test # Run all tests
pnpm test -- --testPathPattern=auth # Run auth tests only