The DB client was initialized at import time, which caused Next.js page
data collection to fail during Docker builds where no database exists.
Wrapping in Proxy defers createClient() until first actual use.
Also adds data/ to .dockerignore.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move `ensureImageDirs` outside the production-only block so the local
image cache directories are created in dev mode too. Update
`extractAndStoreColors` to download the poster if it isn't cached yet
instead of falling back to a direct TMDB CDN URL, keeping color
extraction consistent with the server-side image routing approach. Add
`/data` to `.gitignore` to avoid committing the local cache directory.
Extract dominant colors from movie/TV poster images server-side and use
them to create per-title atmospheric effects on detail pages — tinted
backdrop gradients, ambient glow orbs, and colored poster shadows.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a user finishes watching on their media server, a webhook fires and
Sofa logs it as watched, triggering all existing auto-transitions. Each
user configures their connection in settings and gets a unique webhook URL.
- Add webhookConnections and webhookEventLog schema tables
- Add TMDB findByExternalId for resolving IMDB/TVDB IDs
- Add source parameter to tracking functions (plex/jellyfin)
- Add webhook processing service with payload parsers, title resolution,
and deduplication
- Add public webhook receiver route (token-based auth)
- Add authenticated settings API routes for managing connections
- Add Media Servers section to settings UI with Plex/Jellyfin cards
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
First user to register automatically becomes admin and registration
closes. Admins can re-open registration from a new settings page.
Uses Better Auth admin plugin for role management and a new appSettings
table for the registration flag. Mobile tab bar now links to settings
instead of inline logout.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Docker self-hosting support:
- Dockerfile (multi-stage Alpine build with tini init)
- docker-compose.yml with named volume for SQLite persistence
- /api/health endpoint for container health checks
- Auto-migration on startup via drizzle-orm/libsql/migrator
- Graceful shutdown (SIGTERM stops scheduler, closes DB)
- Next.js standalone output mode for minimal image size
Database driver migration (better-sqlite3 → @libsql/client):
- Eliminates native C++ compilation, enabling Alpine Docker images
- All DB queries converted from sync to async across services and routes
- DATABASE_URL now uses libsql file: prefix format
- drizzle.config.ts dialect changed to turso for libsql support
- Initial migration files generated in drizzle/
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add all 10 milestones: Drizzle ORM + SQLite database with WAL mode,
Better Auth email/password authentication, TMDB API integration for
search and metadata import, TV season/episode caching, user tracking
(watchlist/status/watches/ratings with auto-transitions), discovery
feeds (continue watching, library, recommendations), US streaming
availability via TMDB providers, background job scheduler with
instrumentation hook, and dark cinema-themed frontend with DM Serif
Display + DM Sans typography and amber accent design system.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>