The FutsalLeague Manager backend is a Node.js/Express API that connects to PostgreSQL for persistent storage, Redis for caching and rate limiting, Cloudinary for image uploads, and Gmail for transactional email. This guide covers everything you need to get the API running in a production environment.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.
Prerequisites
Before deploying, make sure the following are available:- Node.js — No engine field is specified in
package.json; use Node.js 18 LTS or newer for best compatibility. - PostgreSQL — A running PostgreSQL instance with the database initialized (see Database setup).
- Redis — Required for both response caching and auth rate limiting. A Redis 6+ instance or a managed service (Redis Cloud, Upstash, etc.) is supported.
- Cloudinary account — For team and player image uploads.
- Gmail account — For sending verification and password-reset emails via Nodemailer.
Environment variables
Create a.env file in the backend/ directory (or set these as environment variables in your hosting platform). All variables are required unless a default is noted.
| Variable | Description | Default |
|---|---|---|
PORT | Port the Express server listens on | 3000 |
DATABASE_URL | Full PostgreSQL connection string (used by pg.Pool) | — |
JWT_SECRET | Secret key used to sign and verify JWT tokens | — |
REDIS_URL | Redis connection URL used by ioredis | — |
CLOUDINARY_CLOUD_NAME | Your Cloudinary cloud name | — |
CLOUDINARY_API_KEY | Cloudinary API key | — |
CLOUDINARY_API_SECRET | Cloudinary API secret | — |
EMAIL_USER | Gmail address used as the sender for all emails | — |
EMAIL_PASS | Gmail app password for the sender account | — |
FRONTEND_URL | Public URL of the frontend — embedded in verification and password-reset email links | http://localhost:4200 |
Redis is required for two separate concerns: response caching (match lists, standings) via
ioredis, and distributed rate limiting on auth endpoints via rate-limit-redis. The API will not start correctly if Redis is unreachable at boot.Sample .env file
Installation and start
http://localhost:3000 (or the port defined in PORT) and prints:
CORS configuration
The API currently allows requests from all origins using a manual CORS middleware:GET, POST, PUT, PATCH, DELETE, OPTIONS) and the Authorization header are permitted. If you need to restrict origins to your frontend domain in production, update this header in index.js.
Rate limiting
Authentication endpoints (/login, /register, /forgot-password, /resend-verification) are protected by a shared rate limiter:
- Limit: 10 requests per IP per 15-minute window
- Storage: Redis (via
rate-limit-redis), so limits are shared across multiple server instances - Response on breach: HTTP 429 with a JSON message asking the user to retry after 15 minutes
RateLimit-* response headers are included; legacy X-RateLimit-* headers are disabled.
Cron jobs
The backend registers scheduled tasks at startup usingnode-cron. No external job runner is required — they run inside the Node.js process.
| Schedule | Task |
|---|---|
Daily at midnight (0 0 * * *) | Deletes all user accounts that have been unverified for more than 24 hours, keeping the users table free of stale registrations. |
API route structure
| Prefix | Description |
|---|---|
/login, /register | Authentication and account management |
/users | User profile endpoints |
/matches | Match records and referee management |
/teams | Team detail and follow relationships |
/players | Player detail |
/standings | League standings |
/statistics | Global statistics |
/admin | Admin panel operations |
/seasons | Season management |
/groups | Group management |
/fields | Playing field management |