API module — Fastify + WebSocket, status: 🟢 ACTIVE. The only active backend of the system: the legacy
olimpico-live-backend/(Nitro/Nuxt) has been completely removed.
Stack
| Component | Version |
|---|---|
| Framework | Fastify ^5.3.0 |
| WebSocket | ws (native Server) ^8.18.x |
| Documentation | @fastify/swagger (Swagger UI at /docs) |
| Language | TypeScript (tsx runner) |
| Database | MongoDB + Mongoose ^9.7.3 |
| Runtime | Node.js ^22 |
REST API
| Endpoint | Feature | What it does |
|---|---|---|
GET /api/devices | Device list | Returns all connected iPads with status and heartbeat |
POST /api/devices/heartbeat | Heartbeat | Records an iPad's heartbeat (every 30s), updates lastSeen |
PUT /api/devices/:id | Rename device | Changes the display name of an iPad |
DELETE /api/devices/:id | Delete device | Removes an iPad from the list |
GET /api/links | Streaming link list | Returns all channels/stream URLs |
POST /api/links | Create link | Adds a new stream URL with name and assigned slot |
PUT /api/links/:id | Edit link | Updates name, URL, slot of a link |
DELETE /api/links/:id | Delete link | Removes a link |
PUT /api/links/:id/activate | Activate link on slot | Assigns a link to a slot (main/feed/alt), updates all devices in real time |
PUT /api/links/:id/block | Block/unblock link | Blocks a link (prevents activation), or unblocks it |
POST /api/links/ping | Ping stream URL | Checks whether a stream URL is reachable (HEAD request), shows response time or error |
GET /api/events | Event list | Returns all scheduled events |
POST /api/events | Create event | Creates a new event with name, date, slot URL |
PUT /api/events/:id | Edit event | Updates the details of an event |
DELETE /api/events/:id | Delete event | Removes an event |
POST /api/events/:id/push | Push event | Sends an event to all devices (updates active links) |
GET /api/license | License status | Shows current license: client, expiry, days remaining |
DELETE /api/license | Revoke license | Removes the license key from the server |
GET /docs | Swagger UI | Interactive API documentation |
WebSocket
| Channel | Feature | What it does |
|---|---|---|
/ws/regia | Control Room connection | Bidirectional channel for the operator panel |
/ws/device/:id | iPad connection | Each iPad connects with its own ID |
broadcastActiveStreams | Synchronized streams | Sends current stream URLs to all devices |
link:activate | Activate link | Assigns a URL to a slot and propagates it to all devices |
link:deactivate | Free slot | Removes a link from the slot, frees the stream |
link:block | Block link | Prevents a link from being used |
device:rename | Rename device | Propagates the new name to all clients |
device:reset | Reset streams | Sends a command to a single device to restart all streams |
device:slot:control | Remote slot control | Stops/starts/restarts a specific slot (main/feed/alt) on a single device |
device:heartbeat | Heartbeat | Keeps the connection to the device alive |
links:sync | Link synchronization | Propagates the updated link list to all clients |
Infrastructure
| Feature | What it does |
|---|---|
| License HMAC | Validates the license key on every startup — without a valid key the server does not start |
| SSL/TLS | Optional HTTPS with Let's Encrypt or self-signed certificate |
| CORS | Enables cross-origin requests for Control Room UI and app |
| MongoDB | Persistent database for devices, links, events |
| Swagger Docs | Interactive API documentation at /docs |
| Auto-restart PM2 | Automatic restart every night at 3:00 AM to clear memory |
| Graceful shutdown | Configurable timeout for clean connection shutdown |
Development
bash
npm run dev # tsx watch → Fastify on :3002
npm run build # TypeScript build → dist/
npm start # Start the buildFuture evolution
- Microservices → Decomposition into independent services (auth, tablet, link, stream, metadata) after production