Architecture
Scroblarr is built as a monorepo using pnpm workspaces. This keeps everything organized and makes development easier.
Package structure
Backend (packages/backend)
The backend is an Express.js API server that handles:
- Webhook endpoints: Receives events from Plex and Jellyfin
- Sync service: Processes watch events and syncs to Trakt/TVTime
- User management: Handles authentication and user operations
- Settings management: Stores and retrieves configuration
- Database: TypeORM with SQLite or PostgreSQL; migrations run automatically on startup
- Sessions: Multiple sessions per user (you can stay logged in on several devices at once)
Tech stack:
- Express.js for the API
- TypeORM for database management
- Pino for logging
- Puppeteer for TVTime authentication
Database support:
- SQLite (default, for development)
- PostgreSQL (for production)
Frontend (packages/frontend)
A React-based web interface built with:
- React + TypeScript: Modern UI framework
- Vite: Fast build tool and dev server
- Tailwind CSS: Utility-first styling
- React Router: Client-side routing
- i18next: Internationalization support
The frontend communicates with the backend via REST API calls.
Shared (packages/shared)
Common code used by both frontend and backend:
- Types: Shared TypeScript interfaces and types
- Utilities: Helper functions used across packages
This ensures type safety between frontend and backend.
Data flow
- Media server (Plex/Jellyfin) sends webhook to Backend webhook endpoint
- Webhook parser extracts watch event data
- Sync service matches event to user and destination accounts
- Integration clients (Trakt/TVTime) sync the watch data
- Database stores sync history
- Frontend displays sync history and statistics
API structure
The backend exposes a REST API at /api/v1/:
/api/v1/webhooks/*- Plex and Jellyfin webhooks (no session; require the Scroblarr API key from Settings → General, per Configuration)/api/v1/auth/*- Sign-in, registration, OAuth callbacks, session checks/api/v1/logout- End the current session/api/v1/users/*- User management (admin)/api/v1/settings/*- Application settings (admin)/api/v1/sync/*- Sync history (authenticated users)/api/v1/trakt/*- Trakt linking and tokens/api/v1/tvtime/*- TVTime linking and profile helpers/api/v1/logs/*- Structured application logs (admin)/api/v1/avatars/*- User avatar proxy/fetch helpers/api/v1/meta/*- Build/version metadata (e.g./versionfor health and diagnostics)
Interactive use: the web UI relies on cookie-based sessions after login. Automation: use the OpenAPI description at /api-docs (and the served openapi.json) for exact paths, request bodies, and which operations accept session cookies vs other auth. Do not expose your webhook API key in client-side code.
API documentation
-
On a running instance: Swagger UI is at
/api-docs(same origin as the app in the usual single-host layout). Use it for live “try it” calls against your server. -
On this documentation site: the REST API section is generated from
packages/backend/openapi.yamlwhen the site is built (pnpm gen-api-docsinwebsite/). It mirrors the spec with examples and grouped operations.
Development
To work on Scroblarr:
# Install dependencies
pnpm install
# Run everything in dev mode
pnpm dev
# Or run packages separately
pnpm dev:backend # Backend only
pnpm dev:frontend # Frontend only
The backend runs on port 3000, frontend on port 5173 (in dev mode). In production, the frontend is built and served by the backend.