FutsalManager is a classic three-tier web application. The Angular single-page application runs entirely in the browser and communicates with the Node.js/Express REST API over HTTP. The API persists data to a PostgreSQL database and uses Redis to cache frequently read responses and to enforce rate limits on authentication endpoints. Images are stored in Cloudinary and served via CDN.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/danielsl4/TFG_DAM_2526/llms.txt
Use this file to discover all available pages before exploring further.
Technology stack
| Layer | Technology | Version |
|---|---|---|
| Frontend framework | Angular | 20 |
| Frontend UI | Bootstrap | 5 |
| Backend runtime | Node.js | — |
| Backend framework | Express | 4 |
| Database | PostgreSQL | — |
| Cache / rate-limit store | Redis (ioredis) | — |
| Authentication | JSON Web Tokens (jsonwebtoken) | — |
| Password hashing | bcrypt | — |
| Image storage | Cloudinary | — |
| File uploads | Multer + sharp | — |
Frontend (Angular SPA)
The Angular application is a standalone SPA with client-side routing managed by@angular/router. All HTTP communication goes through the ApiService, which reads the backend base URL from environment.apiUrl at build time. Route guards control access to protected pages.
Key routes in the Angular app:
| Path | Access | Description |
|---|---|---|
/ | Public | Home page with match schedule |
/standings | Public | League standings per group |
/matches | Public | Match calendar |
/matches/detail/:id | Public | Full match detail with events |
/statistics | Public | Top scorers and leaderboard |
/teams/:id | Public | Team profile |
/players/:id | Public | Player profile |
/login, /register | Unauthenticated only | Auth pages (guarded by noAuthGuard) |
/profile | Authenticated | User profile (guarded by authGuard) |
/admin | Admin only | Admin panel (guarded by adminGuard) |
Backend (Node.js/Express API)
The Express server mounts modular route files. Each domain area has its own router, keeping the codebase easy to extend. Mounted routes:| Mount point | Router file | Domain |
|---|---|---|
/login, /register | src/routes/auth.js | Authentication |
/users, /user/profile | src/routes/users.js | User management |
/matches | src/routes/matches.js | Match lifecycle and events |
/teams | src/routes/teams.js | Team profiles and following |
/players | src/routes/players.js | Player profiles and registration |
/standings | src/routes/standings.js | League table calculations |
/statistics | src/routes/statistics.js | Scorer/card rankings, prediction stats |
/admin | src/routes/admin.js | Admin dashboard and image uploads |
/seasons | src/routes/seasons.js | Season CRUD and import |
/groups | src/routes/groups.js | Group and team assignment management |
/fields | src/routes/fields.js | Venue/field management |
Authentication and authorization
Authentication uses JSON Web Tokens signed with theJWT_SECRET environment variable. The token is passed in the Authorization: Bearer <token> header on every protected request.
Token lifetimes by role:
| Role | Token expiry | Rationale |
|---|---|---|
admin | 6 hours | Short-lived to limit exposure of privileged credentials |
referee | 6 hours | Short-lived for the same reason |
user | 7 days | Longer session for regular fans who do not have write access |
verifyToken— required on all protected routes; returns401if the token is missing or invalid.verifyReferee— permitsrefereeandadminroles only; used on match editing endpoints.verifyAdmin— permitsadminrole only; used on all admin panel endpoints.verifyMatchLock— checks whether a match is currently locked by another user. Locks expire after 2 minutes of inactivity and are cleaned up automatically.
Database (PostgreSQL)
The backend usespg (node-postgres) with a connection pool configured for up to 50 concurrent connections, a 30-second idle timeout, and a 5-second connection timeout. The connection is configured via the DATABASE_URL environment variable with SSL enabled.
All database access goes through a shared db module (backend/db.js) that exposes a query helper and a getClient method for transaction-level control.
Caching (Redis)
Redis serves two purposes: response caching and rate limiting. Response caching reduces database load on read-heavy endpoints. Cached keys follow a consistent naming scheme:| Key pattern | Contents |
|---|---|
all_matches | Full match list (global) |
matches:current | Current-season match list |
matches:season:<id> | Match list for a specific season |
match:<id> | Individual match detail |
match:<id>:user:<uid> | Match detail with user-specific vote data |
standings | Global standings |
standings:<id> | Standings for a specific season |
global_last_activity | Timestamp of the last admin action |
invalidateMatchCache function deletes all related keys (match detail, season list, standings, and all user-scoped match entries) to prevent stale reads.
Rate limiting on /login and /register uses express-rate-limit with a Redis store (rate-limit-redis). Each IP is limited to 10 requests per 15-minute window to guard against brute-force attacks.
Image uploads (Cloudinary)
Team and player images are uploaded through the/admin/upload endpoint. The backend accepts a multipart/form-data request, processes the file with sharp for optimisation, and sends it to Cloudinary using the cloudinary SDK. The returned CDN URL is stored in the database and served directly to the frontend.
CORS
CORS is currently configured with a wildcard origin (
Access-Control-Allow-Origin: *), which permits requests from any domain. This is intentional for maximum compatibility during development and self-hosted deployments. If you deploy to production and need to restrict access, replace the wildcard with an explicit list of allowed origins in backend/index.js.GET, POST, PUT, PATCH, DELETE, OPTIONS. Preflight OPTIONS requests receive an immediate 200 response without hitting any route handlers.
Next steps
Quickstart
Run both services locally and verify your setup.
API reference
Browse all endpoints with request and response schemas.
Deployment: backend
Deploy the Node.js API to a production environment.
Deployment: frontend
Build and deploy the Angular SPA.