Unified web dashboard for managing your self-hosted media stack — Sonarr, Radarr, Lidarr, Prowlarr, qBittorrent, and Soulseek.
arr-dashboard brings together all the services in your *arr media stack into a single, modern web interface. Instead of jumping between six different UIs to check download status, manage your library, or search for content, everything is accessible from one place.
- Unified library view — Browse movies (Radarr), TV series (Sonarr), and music artists (Lidarr) side-by-side
- Live download tracking — Real-time pipeline showing searches → grabs → imports across all *arr services + qBittorrent + Soulseek
- Manual search — Browse releases sorted by a smart quality/seeders composite score, with one-click grab
- Activity log — Full audit trail of every add, delete, search, and download
- Bandwidth monitor — Live download/upload speeds with lifetime tracking (survives restarts)
- Docker container monitoring — Service health strip with direct links to each service
- Light/dark mode — System-aware theme with CSS custom properties, persists via localStorage
- Mobile responsive — Bottom nav, collapsible sidebar, touch-optimized controls
- Accessibility — ARIA labels, keyboard navigation, focus-visible rings, screen-reader-friendly
| Service | Purpose |
|---|---|
| Radarr | Movie library management |
| Sonarr | TV series library management |
| Lidarr | Music library management |
| Prowlarr | Indexer management (via *arr proxies) |
| qBittorrent | Torrent client (downloads/seeding) |
| Soulseek (SLSKD) | Peer-to-peer music downloads |
| Jellyfin | Media server (status monitoring) |
| Bazarr | Subtitle management |
| Docker | Container health monitoring |
- Docker and Docker Compose
- Node.js 22+ (for development)
- Running instances of Radarr, Sonarr, Lidarr, qBittorrent, and/or SLSKD
Copy the environment template and fill in your API keys:
cp .env.example .envEdit .env with your service hosts and API keys:
# Required
RADARR_API_KEY=your_radarr_api_key
SONARR_API_KEY=your_sonarr_api_key
LIDARR_API_KEY=your_lidarr_api_key
# Optional (set host if not using Docker networking)
RADARR_HOST=http://radarr:7878
SONARR_HOST=http://sonarr:8989
LIDARR_HOST=http://lidarr:8686
QBITTORRENT_HOST=http://qbittorrent:8080
SLSKD_HOST=http://slskd:5030
# Required for torrent support
QBITTORRENT_USER=admin
QBITTORRENT_PASS=adminadmin
# Required for Soulseek support
SLSKD_API_KEY=your_slskd_api_keydocker compose build --no-cache
docker compose up -dThe dashboard will be available at http://localhost:8888.
# Backend
cd backend
npm install
npm run dev
# Frontend (separate terminal)
cd frontend
npm install
npm run dev┌─────────────────────────────────────────────────────┐
│ nginx (port 8888) │
│ ┌──────────────────────────────────────────────┐ │
│ │ Frontend (Vite + React + Tailwind) │ │
│ │ └─ dist/ served as static files │ │
│ └──────────────────────────────────────────────┘ │
│ │ proxy /api/* │
│ ┌──────────────────────────────────────────────┐ │
│ │ Backend (Express, port 3000) │ │
│ │ └─ server.js → src/ modules │ │
│ │ └─ Routes: system, qbit, arr, pipeline, │ │
│ │ search, lookup, add, delete, │ │
│ │ activity, meta, slskd │ │
│ └──────────────────────────────────────────────┘ │
│ │ │
│ ┌──────┬──────┬──────┼──────┬──────┬──────┐ │
│ │Radarr│Sonarr│Lidarr│qBit │SLSKD │Docker│ │
│ └──────┴──────┴──────┴──────┴──────┴──────┘ │
└─────────────────────────────────────────────────────┘
Server startup (backend/src/middleware.js) registers graceful shutdown handlers so intervals are cleaned up and state is persisted on SIGTERM/SIGINT.
arr-dashboard/
├── backend/
│ ├── src/
│ │ ├── config.js # Environment variables & constants
│ │ ├── state.js # In-memory state (pipeline, caches, activity)
│ │ ├── utils.js # Shared utilities (fetch helpers, normalization)
│ │ ├── middleware.js # Rate limiting, body limits, graceful shutdown
│ │ └── routes/ # Route modules (extracted from server.js)
│ ├── server.js # Express entry point
│ ├── Dockerfile
│ ├── package.json
│ └── .dockerignore
├── frontend/
│ ├── src/
│ │ ├── App.jsx # Root component with polling & layout
│ │ ├── Library.jsx # Library browser (movies, series, music)
│ │ ├── SidePanel.jsx # Right sidebar (bandwidth, storage, downloads)
│ │ ├── TorrentTable.jsx # qBittorrent torrent list
│ │ ├── PipelineCard.jsx # Download pipeline card
│ │ ├── ManualSearchModal.jsx # Manual torrent search modal
│ │ ├── ActivityLog.jsx # SLSKD download cards
│ │ ├── api.js # Fetch wrapper (dedup, backoff, abort)
│ │ ├── constants.js # Design tokens, service config, breakpoints
│ │ ├── utils.js # Formatting & utility functions
│ │ ├── App.css # Global styles + CSS variables
│ │ └── index.css # Theme variables (dark/light)
│ ├── package.json
│ ├── vite.config.js
│ └── tailwind.config.js
├── docker-compose.yml
├── .env.example
├── .gitignore
├── LICENSE
└── README.md
- API keys: Stored in
.env, mounted into the container, never baked into images. API calls to *arr services useX-Api-Keyheaders, not query strings - Rate limiting: 300 requests/minute per IP
- Body limits: 1MB maximum request body
- Docker socket: Only the backend container has socket access; frontend is served through nginx
# Frontend tests
cd frontend
npx vitest run
# Backend tests (when available)
cd backend
npm test- ES modules throughout (
import/export) - React functional components with hooks
- Tailwind CSS for styling (with inline style fallbacks)
- CSS custom properties for theming
MIT — see LICENSE.
See CONTRIBUTING.md.