- Add `lib/constants.ts` exporting `DATA_DIR`, `DATABASE_URL`, `CACHE_DIR`,
`BACKUP_DIR`, `AVATAR_DIR`, `TMDB_API_BASE_URL`, and `TMDB_IMAGE_BASE_URL`
- Replace inline `process.env` derivations in `db/client`, `backup`,
`image-cache`, `system-health`, `tmdb/client`, `actions/settings`,
and `api/avatars` with imports from the new module
- Add `uploadAvatarAction` and `removeAvatarAction` server actions;
store files under `DATA_DIR/avatars/{userId}.{ext}` via Bun.write
- Add `GET /api/avatars/[userId]` route that scans the avatar dir with
Bun.Glob and serves with immutable Cache-Control (cache-busted via
query param)
- Refactor AccountSection with hover overlay, AnimatePresence fade,
and file input; click avatar to upload (no image) or remove (has image)
- Replace NavBar user initial badge with Avatar + DropdownMenu showing
name, email, settings link, and sign-out
- Thread `userEmail` and `userImage` props through AuthenticatedShell
→ NavBar and SettingsPage → AccountSection
- Delete 10 API routes (stats, system-health, update-check, jobs/trigger,
backup/restore, person, titles import/resolve, registration/status) and
move logic into server actions in lib/actions/settings.ts and
lib/actions/watchlist.ts
- Refactor SystemHealthCards to accept initialData prop and hydrate Jotai
atoms via useHydrateAtoms; replace useSystemHealth SWR hook with a
lightweight useSystemHealthRefresh that calls getSystemHealthAction
- Convert BackupRestoreSection to use restoreBackupAction + useTransition
instead of a raw fetch call
- Split SystemStatusCard, BackgroundJobsCard, and StorageCard into
standalone components reading from systemHealthDataAtom
- Make SetupPage async with connection() to opt into dynamic rendering
- Overhaul `lib/auth/server.ts` and `lib/auth/session.ts`; update all API
routes and server actions to use the revised session pattern
- Refactor server actions (settings, titles, watchlist, setup) for
consistency with new auth layer
- Extract `SetupForm` into its own client component with `useActionState`,
animated steps, and copyable env snippets
- Move landing page redirect logic into `app/page.tsx`; slim down
`LandingPage` component
- Add `proxy.ts` for local dev proxying
- Minor cleanup to `NavBar`, `MobileTabBar`, and `TitleCard`
- New `lists` service fetches Sonarr/Radarr library via their REST APIs
and auto-imports matching titles from TMDB into the user's watchlist
- `app/api/lists/[token]/route.ts` webhook endpoint triggers a list sync
- Unified `IntegrationCard` component replaces `WebhookCard`, handling
both webhook-style (Plex/Jellyfin/Emby) and list-style (Sonarr/Radarr)
integrations with per-type config forms
- Schema migration adds `sonarr` and `radarr` to the integration type
enum and a `listConnections` table for list-based integrations
- 212 tests added for the lists service covering import, deduplication,
and error handling
Checks current version against latest GitHub release every 6 hours via
cron job, caches result in appSettings, and surfaces updates through a
toast notification (once per browser session) and an animated badge in
the settings footer. Includes an admin toggle to enable/disable checks
(enabled by default). Also renames ServerSection to RegistrationSection
now that update checks are in their own card.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Emby as a third media server integration alongside Plex and Jellyfin.
Emby webhooks use a similar payload format (JSON with nested Item object
and ProviderIds). Also removes the mediaServerUsername field from all
webhook connections since it was never used for authentication — the
token-in-URL is the sole auth mechanism. This simplifies the connection
UX to a single "Connect" button.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move all server actions from scattered page-level files into shared lib/actions/
directory (settings.ts, titles.ts, watchlist.ts) so they can be reused across
the app. Add a hover-triggered plus button on explore page title cards that lets
users add titles to their watchlist without navigating away.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>