mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-07-14 18:15:56 -04:00
Update CLAUDE.md to reflect current codebase state
Fixes numerous outdated sections: auth pages location, UUID generation method, missing services/schema tables/cron jobs, OIDC support, cached session helper, image profile category, and environment variables. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -32,10 +32,11 @@ IMPORTANT: Default to using Bun instead of Node.js:
|
||||
### Stack
|
||||
|
||||
- **Framework**: Next.js 16 (App Router), React 19, TypeScript
|
||||
- **Database**: SQLite via bun:sqlite + Drizzle ORM (WAL mode, singleton via `globalThis`, sync queries)
|
||||
- **Auth**: Better Auth with Drizzle adapter, email/password
|
||||
- **Database**: SQLite via bun:sqlite + Drizzle ORM (WAL mode, singleton via `globalThis`, sync queries, auto-migrations on startup)
|
||||
- **Auth**: Better Auth with Drizzle adapter — email/password + optional OIDC/SSO via `genericOAuth` plugin
|
||||
- **Styling**: Tailwind CSS v4, shadcn components, dark cinema theme with warm primary accents
|
||||
- **Fonts**: DM Serif Display (display), DM Sans (body), Geist Mono (mono)
|
||||
- **State**: Jotai (client), SWR (data fetching)
|
||||
- **Linting**: Biome (2-space indent, organized imports, React/Next.js recommended rules)
|
||||
- **External API**: TMDB (The Movie Database) with Bearer token auth
|
||||
|
||||
@@ -46,17 +47,29 @@ IMPORTANT: Default to using Bun instead of Node.js:
|
||||
### Key directories
|
||||
|
||||
- `lib/db/schema.ts` — Single file with all Drizzle table definitions (auth tables + app tables)
|
||||
- `lib/services/` — Business logic layer (metadata, tracking, discovery, availability)
|
||||
- `lib/db/migrate.ts` — Auto-migration runner (executed on startup via instrumentation)
|
||||
- `lib/services/` — Business logic layer (metadata, tracking, discovery, availability, credits, person, webhooks, backup, settings, colors, update-check, system-health)
|
||||
- `lib/tmdb/` — TMDB API client and TypeScript types
|
||||
- `lib/auth/` — Better Auth server config (`server.ts`) and client hooks (`client.ts`)
|
||||
- `lib/auth/` — Better Auth server config (`server.ts`), client hooks (`client.ts`), cached session helper (`session.ts`)
|
||||
- `lib/config.ts` — Server-side environment checks (TMDB configured, OIDC configured, etc.)
|
||||
- `lib/logger.ts` — Structured logger with `LOG_LEVEL` support
|
||||
- `lib/types/` — Shared TypeScript types (e.g. `title.ts`)
|
||||
- `lib/cron.ts` — Background job scheduler (croner, `globalThis` singleton)
|
||||
- `app/api/` — Next.js route handlers
|
||||
- `app/(pages)/` — User-facing pages (dashboard, search, title detail, login, register)
|
||||
- `app/(pages)/` — Authenticated pages (dashboard, explore, titles/[id], people/[id], settings)
|
||||
- `app/(auth)/` — Auth pages (login, register, setup)
|
||||
- `components/` — App components + `components/ui/` for shadcn primitives
|
||||
|
||||
### Auth pattern
|
||||
|
||||
Route handlers call Better Auth directly. Every authenticated route follows this pattern:
|
||||
Server components and layouts use the cached session helper to avoid redundant lookups:
|
||||
|
||||
```typescript
|
||||
import { getSession } from "@/lib/auth/session";
|
||||
const session = await getSession();
|
||||
```
|
||||
|
||||
Route handlers call Better Auth directly:
|
||||
|
||||
```typescript
|
||||
import { headers } from "next/headers";
|
||||
@@ -69,39 +82,63 @@ if (!session)
|
||||
|
||||
### Database schema
|
||||
|
||||
All app tables use UUID text primary keys generated via the `uuid` package. Better Auth tables use their own ID format. Key relationships:
|
||||
All app tables use UUIDv7 text primary keys generated via `Bun.randomUUIDv7()`. Better Auth tables use their own ID format. Key relationships:
|
||||
|
||||
- `titles` → `seasons` → `episodes` (TV hierarchy)
|
||||
- `persons` + `titleCast` (cast/crew linked to titles)
|
||||
- `userTitleStatus` links users to titles with status (watchlist/in_progress/completed)
|
||||
- `userMovieWatches` / `userEpisodeWatches` track watch history
|
||||
- `userMovieWatches` / `userEpisodeWatches` track watch history (source: manual/import/plex/jellyfin/emby)
|
||||
- `userRatings` stores 1-5 star ratings
|
||||
- `availabilityOffers` caches streaming provider data per title
|
||||
- `titleRecommendations` stores TMDB recommendations and similar titles
|
||||
- `webhookConnections` / `webhookEventLog` — Plex/Jellyfin/Emby webhook integrations
|
||||
- `cronRuns` — Background job execution history
|
||||
- `appSettings` — Key-value store for runtime app configuration
|
||||
|
||||
### Service layer
|
||||
|
||||
- **metadata.ts**: `importTitle()` fetches from TMDB, inserts into DB, fire-and-forgets availability + recommendations + image caching. `refreshTvChildren()` fetches all seasons/episodes with 250ms rate limiting.
|
||||
- **image-cache.ts**: Downloads and caches TMDB images to local disk. `cacheImagesForTitle()` caches poster + backdrop, `cacheEpisodeStills()` caches episode stills, `cacheProviderLogos()` caches streaming provider logos.
|
||||
- **metadata.ts**: `importTitle()` fetches from TMDB, inserts into DB, fire-and-forgets availability + recommendations + credits + image caching. `refreshTvChildren()` fetches all seasons/episodes with 250ms rate limiting.
|
||||
- **image-cache.ts**: Downloads and caches TMDB images to local disk. `cacheImagesForTitle()` caches poster + backdrop, `cacheEpisodeStills()` caches episode stills, `cacheProviderLogos()` caches streaming provider logos, `cacheProfilePhotos()` caches person profile images.
|
||||
- **tracking.ts**: Auto-transitions — logging a movie watch sets status to `completed`; logging an episode watch sets `in_progress`; all episodes watched auto-completes the series.
|
||||
- **discovery.ts**: Feed generators — continue watching (next unwatched episode per in-progress show), library titles with availability, personalized recommendations from completed/highly-rated titles.
|
||||
- **availability.ts**: Caches US streaming providers from TMDB watch/providers endpoint.
|
||||
- **credits.ts**: Fetches and caches cast/crew data from TMDB, links persons to titles via `titleCast`.
|
||||
- **person.ts**: Person detail and filmography lookups.
|
||||
- **webhooks.ts**: Processes incoming Plex/Jellyfin/Emby webhook events to auto-log watches.
|
||||
- **backup.ts**: Database backup/restore with configurable scheduled backups and retention pruning.
|
||||
- **settings.ts**: Runtime app settings (registration open/closed, backup config, etc.) via `appSettings` table.
|
||||
- **colors.ts**: Extracts dominant color palettes from title posters via node-vibrant.
|
||||
- **update-check.ts**: Checks for new Sofa releases.
|
||||
- **system-health.ts**: System health diagnostics.
|
||||
|
||||
### TMDB images
|
||||
|
||||
Only paths are stored in DB. Image URLs are resolved **server-side only** — API routes and server components call `tmdbImageUrl()` from `lib/tmdb/image.ts` before sending data to clients. Client components never import `tmdbImageUrl`; they receive ready-to-use URLs.
|
||||
|
||||
When `IMAGE_CACHE_ENABLED` is set (default), images are downloaded to local disk (`CACHE_DIR`, derived from `DATA_DIR/images`) and served via `app/api/images/[...path]/route.ts`. Categories: `posters` (w500), `backdrops` (w1280), `stills` (w1280), `logos` (w92). When disabled, `tmdbImageUrl()` returns direct TMDB CDN URLs using `TMDB_IMAGE_BASE_URL` (defaults to `https://image.tmdb.org/t/p`).
|
||||
When `IMAGE_CACHE_ENABLED` is set (default), images are downloaded to local disk (`CACHE_DIR`, derived from `DATA_DIR/images`) and served via `app/api/images/[...path]/route.ts`. Categories: `posters` (w500), `backdrops` (w1280), `stills` (w1280), `logos` (w92), `profiles` (w185). When disabled, `tmdbImageUrl()` returns direct TMDB CDN URLs using `TMDB_IMAGE_BASE_URL` (defaults to `https://image.tmdb.org/t/p`).
|
||||
|
||||
Core files: `lib/services/image-cache.ts` (caching logic), `lib/tmdb/image.ts` (URL construction), `app/api/images/[...path]/route.ts` (proxy route).
|
||||
|
||||
### Background jobs
|
||||
|
||||
Defined in `lib/cron.ts` using croner cron expressions, started via Next.js instrumentation hook (`instrumentation.ts`) in production. Jobs: nightly library refresh (`0 3 * * *`), availability refresh (`0 */6 * * *`), recommendations refresh (`0 */12 * * *`), TV episodes refresh (`30 */12 * * *`), image caching (`0 1,13 * * *`). All jobs use `protect: true` to prevent overlapping runs. All batch jobs use 300ms delay between TMDB calls.
|
||||
Defined in `lib/cron.ts` using croner cron expressions, started via Next.js instrumentation hook (`instrumentation.ts`) when `NEXT_RUNTIME === "nodejs"`. The instrumentation hook also runs DB migrations on startup and registers graceful shutdown handlers.
|
||||
|
||||
Jobs (all use `protect: true` to prevent overlapping runs, 300ms delay between TMDB calls):
|
||||
- `nightlyRefreshLibrary` (`0 3 * * *`) — refreshes stale library titles (7d) and non-library titles (30d)
|
||||
- `refreshAvailability` (`0 */6 * * *`) — streaming provider data
|
||||
- `refreshRecommendations` (`0 */12 * * *`)
|
||||
- `refreshTvChildren` (`30 */12 * * *`) — episodes for returning/in-production TV shows
|
||||
- `cacheImages` (`0 1,13 * * *`) — posters, backdrops, stills, logos, profile photos
|
||||
- `refreshCredits` (`0 2 * * *`) — cast/crew data for library titles
|
||||
- `scheduledBackup` (configurable via settings) — database backups with retention pruning
|
||||
- `updateCheck` (`0 */6 * * *`) — checks for new Sofa releases
|
||||
|
||||
### Environment variables
|
||||
|
||||
See `.env.example`: `DATA_DIR` (root for DB + cache, default `./data`), `TMDB_API_READ_ACCESS_TOKEN`, `BETTER_AUTH_SECRET`, `BETTER_AUTH_URL`. `DATABASE_URL` and `CACHE_DIR` are derived from `DATA_DIR` but can be overridden individually.
|
||||
|
||||
Optional: `OIDC_CLIENT_ID`, `OIDC_CLIENT_SECRET`, `OIDC_ISSUER_URL`, `OIDC_PROVIDER_NAME`, `OIDC_AUTO_REGISTER`, `DISABLE_PASSWORD_LOGIN` (OIDC/SSO support). `LOG_LEVEL` (error/warn/info/debug, default: info). `IMAGE_CACHE_ENABLED` (default: true).
|
||||
|
||||
## Browser Automation
|
||||
|
||||
Use `agent-browser` for web automation. Run `agent-browser --help` for all commands.
|
||||
@@ -111,3 +148,5 @@ Core workflow:
|
||||
2. `agent-browser snapshot -i` - Get interactive elements with refs (@e1, @e2)
|
||||
3. `agent-browser click @e1` / `fill @e2 "text"` - Interact using refs
|
||||
4. Re-snapshot after page changes
|
||||
|
||||
When encountering auth, use `jake@jarv.is` for the username/email and `password` for the password.
|
||||
|
||||
Reference in New Issue
Block a user