Commit Graph
10 Commits
Author SHA1 Message Date
jakeandClaude Opus 4.6 9ecf7bbe3c Add watch trailer button with cinematic YouTube player dialog
Fetch trailer video keys from TMDB videos API during title import/refresh,
store in DB, and display a "Trailer" button on title pages that opens a
media-chrome Sutro-themed YouTube player in a fullwidth dialog.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 13:36:38 -05:00
jake 107eb9a9e7 Overhaul system health section with job trigger controls and live timestamps
Rebuild the background jobs card as a sortable table showing each job's
schedule, last run time (live-updating via a new useTimeAgo hook), last
duration, and a manual trigger button backed by a new POST
/api/admin/jobs/trigger route. Extract StatusDot into a shared
component. Add cronToHuman() to display schedule patterns as readable
strings (e.g. "Every 6h", "Daily at 03:00"). Replace static
formatDistanceToNow calls throughout the health section with a
LiveTimeAgo component that refreshes every 30 seconds. Also swap a
handful of section icons for better visual matches across settings cards.
2026-03-05 11:52:37 -05:00
jakeandClaude Opus 4.6 bafa45ec79 Add Emby webhook integration and remove unused username field
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>
2026-03-05 00:50:32 -05:00
jake b17f54f6db Add cronRuns table and integrate job scheduling with database logging
- Created a new `cronRuns` table to track job execution history, including job name, status, timestamps, and error messages.
- Updated job scheduling logic to log job status in the `cronRuns` table, capturing success and error states.
- Enhanced error handling to log detailed error messages in the database.

This commit establishes a foundation for monitoring scheduled jobs and their outcomes.
2026-03-04 12:59:19 -05:00
jakeandClaude Opus 4.6 2fb329e0dc Switch from Node.js + pnpm to Bun runtime and package manager
Replace @libsql/client with bun:sqlite for zero-dependency SQLite access,
swap drizzle-orm/libsql adapter for drizzle-orm/bun-sqlite, and rewrite
Dockerfile to use oven/bun:1-alpine. The raw Database instance is no longer
exported via Proxy (native C++ methods lose `this` binding through
Reflect.get); instead, a closeDatabase() helper handles graceful shutdown
and the health check uses Drizzle's db.run() directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 15:17:57 -05:00
jakeandClaude Opus 4.6 cb0f366d44 Add dynamic color theming from poster art using node-vibrant
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>
2026-03-02 12:29:13 -05:00
jakeandClaude Opus 4.6 67356e04c6 Add Plex and Jellyfin webhook integration for automatic watch tracking
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>
2026-03-01 16:24:39 -05:00
jakeandClaude Opus 4.6 db3a6cc3d4 Add auto-close registration and admin settings page
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>
2026-03-01 13:51:20 -05:00
jake ea0f00945d Add .gitkeep file to drizzle directory for version control 2026-03-01 13:31:28 -05:00
jakeandClaude Opus 4.6 96213c3086 Add Docker packaging and migrate from better-sqlite3 to libsql
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>
2026-03-01 13:14:57 -05:00