Admin Panel
The operator panel for Bitrate staff: moderation, catalog and account management. An Angular zoneless SPA on spartan-ng β see ADR-0035. It replaced the Kottster panel removed in ADR-0025.
π Quick Startβ
# Install dependencies (from repo root)
pnpm install
# Start development server (port from ADMIN_PORT, 3005 in the example env)
pnpm --filter @bitrate/admin dev
Angular has no .env support of its own, so scripts/with-env.mjs loads the env files and
generates the module the app reads NG_APP_API_URL from.
πΊοΈ Screensβ
Every route is lazy-loaded and guarded twice: requireStaffSession restores the staff session
(an httpOnly cookie) or redirects to /login?next=, and requirePermission('<resource>:<action>')
checks one permission from domain/access/permission.ts.
| Area | Routes |
|---|---|
| Overview | overview, overview/reports β dashboard with drill-down analytics |
| Moderation | moderation, moderation/:id β user reports |
| Catalog | catalog, catalog/:id β tracks, with an audio player built on @bitrate/player |
| Releases | releases, releases/:id β review of artist submissions |
| Content | albums, playlists with :id detail β take-down and restore |
| Accounts | artists, users (listeners) with :id detail |
| Genres | genres, genres/new, genres/:id β CRUD with guarded delete |
| Staff | staff, roles with new and :id β roles are editable sets of permissions |
| Audit | audit β the staff action log |
Lists share batch actions, CSV export, sorting, filters and pagination kept in the URL.
ποΈ Architectureβ
src/app/ has four layers: domain/ (types and rules), application/ (use cases and signal
stores), infrastructure/ (HTTP repositories over HttpClient, zod DTOs typed by
@bitrate/contracts, mappers) and presentation/ (pages, components and the vendored spartan-ng
ui/ primitives). It runs without zone.js.
Themes are dark, light and dim from @bitrate/tailwind. Localization uses Transloco with en
and uk dictionaries; only navigation and login are translated so far.
π§ͺ Testingβ
pnpm --filter @bitrate/admin test:unit # Vitest with jsdom
pnpm --filter @bitrate/admin lint # ESLint β admin is not a Biome workspace
pnpm --filter @bitrate/admin check:i18n # dictionary keys match across locales
There are no end-to-end tests yet.
Related: