- Drop `@sofa/core` and `@sofa/api` from `apps/public-api` — importing workspace packages with DB/Node dependencies broke the Vercel edge runtime
- `fetchUserData` on Trakt and Simkl importers now returns raw `unknown` API responses; parsing is deferred to the self-hosted server
- Add `source` + `rawPayload` fields to `ParsePayloadInput`; `parsePayload` procedure now dispatches to `parseTraktPayload`/`parseSimklPayload` and returns full warnings + diagnostics
- Export `ProviderEnum` from `apps/public-api/src/importers/index.ts` instead of defining it inline in `app.ts`
* Convert to Turborepo monorepo with shared API contract package
Restructure the repository as a monorepo in preparation for adding
future clients (mobile app, CLI). Extract the oRPC contract and Zod
schemas into `@sofa/api` (packages/api/) as a JIT internal package,
and relocate the Next.js app to `@sofa/web` (apps/web/).
- Add Turborepo with Bun workspaces for task orchestration and caching
- Extract `contract.ts` and `schemas.ts` into `@sofa/api` package
- Move all app code, configs, tests, and migrations to `apps/web/`
- Update 17 import paths from `@/lib/orpc/schemas` to `@sofa/api/schemas`
- Add `outputFileTracingRoot` and `transpilePackages` to next.config.ts
- Rewrite Dockerfile with `turbo prune --docker` for efficient builds
- Update CI workflows to use `turbo run` for lint/check-types/test
- Update CLAUDE.md with monorepo structure and commands
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Extract standalone Hono API server and split shared packages
Separate all server-side concerns from the Next.js frontend into a new
`apps/server/` Hono app and dedicated shared packages, making `@sofa/web`
a frontend-only app with no direct DB or service access.
- Add `@sofa/server` (`apps/server/`) — Hono API on port 3001 hosting
oRPC procedures, Better Auth, cron jobs, and non-RPC routes
- Add `@sofa/core` (`packages/core/`) — All 15 business logic services
moved from `apps/web/lib/services/`; tests moved to `packages/core/test/`
- Add `@sofa/db` (`packages/db/`) — DB client, schema, migrations,
constants, and logger extracted from `apps/web/lib/db/` and `lib/`
- Add `@sofa/tmdb` (`packages/tmdb/`) — TMDB client and image helpers
moved from `apps/web/lib/tmdb/`
- Add `@sofa/auth` (`packages/auth/`) — Better Auth server config moved
from `apps/web/lib/auth/`
- Move oRPC procedures, handler, router, middleware to `apps/server/src/orpc/`
- Move Hono route handlers (avatars, backups, images, lists, webhooks,
health) to `apps/server/src/routes/`; delete equivalent Next.js API routes
- Strip `apps/web` to frontend-only: no DB imports, no service imports,
all data via oRPC client calls to the API server
- Add `entrypoint.sh` to start API server, wait for health, then Next.js
- Update `next.config.ts` rewrites to proxy `/rpc/*` and `/api/*` to
`INTERNAL_API_URL` (default `http://localhost:3001`)
- Update Dockerfile and CLAUDE.md for the new structure
* Migrate web app from Next.js to Vite + TanStack Router SPA and add workspace catalog
Replace Next.js with a pure Vite SPA using TanStack Router for file-based routing,
removing all SSR complexity. The API server (Hono) now serves both API routes and
SPA static files in production, simplifying Docker to a single-process container.
Key changes:
- Vite 7 + @tanstack/react-router with file-based routing via plugin
- Route guards via beforeLoad + authClient.getSession() (replaces server-side auth)
- Route loaders with queryClient.ensureQueryData() (replaces SSR data fetching)
- Self-hosted fonts via @fontsource (replaces next/font/google)
- Tailwind v4 via @tailwindcss/vite (replaces @tailwindcss/postcss)
- Single oRPC client (removed SSR client and server-side session helper)
- Hono serves SPA static files in production (single port 3000)
- Single-process Dockerfile (removed entrypoint.sh)
- Bun workspace catalog for centralized dependency version management
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Extract @sofa/logger and @sofa/config shared packages
- Add `@sofa/logger` (`packages/logger/`) — standalone logger package
extracted from `@sofa/db/logger`; update all imports across server,
core, auth, db, and tmdb packages
- Add `@sofa/config` (`packages/config/`) — standalone config/constants
package extracted from `@sofa/db/constants`; exports `DATA_DIR`,
`DATABASE_URL`, `CACHE_DIR`, `AVATAR_DIR`, `BACKUP_DIR`
- Move `.env.example` from `apps/web/` to repo root; update server dev
scripts to load it via `--env-file=../../.env`
- Move image serving from `/api/images` to `/images`; add `serveStatic`
fast path in `index.ts` for cached files before falling back to the
TMDB fetch route; add `/images` proxy to Vite dev config
- Fix `Sparkline` component: replace `ResponsiveContainer` with
`ResizeObserver` to avoid SSR/hydration issues with recharts
- Replace `VITE_SERVER_URL` env var with `window.location.origin` in
the oRPC client (always same-origin in both dev and production)
* Fix asset caching, SPA 404 fallback, and DATA_DIR resolution
- Add `Cache-Control: immutable` header for hashed `/assets/*` files;
return 404 for missing asset paths instead of falling back to
`index.html` (prevents serving stale chunks after deploy)
- Wrap `query.invalidate` in an arrow function in the oRPC QueryClient
error handler to avoid illegal invocation errors
- Resolve `DATA_DIR` to an absolute path via `path.resolve()` so
relative paths work regardless of the process working directory
* Migrate @sofa/logger to pino for structured logging
- Replace custom logger implementation in `packages/logger/` with pino
+ pino-pretty; add both as workspace catalog dependencies
- Add `pino` and `pino-pretty` to the workspace catalog in `package.json`
- Fix `log.error()` calls in oRPC and OpenAPI handlers to pass the
error directly instead of wrapping it in `{ error }` to match pino's
serializer expectations
* Rename discoverProcedure/statsProcedure exports to discover/stats
* Add TanStackDevtools unified panel and VS Code workspace config
- Replace separate Router/Query devtools with unified `TanStackDevtools`
from `@tanstack/react-devtools` + `@tanstack/devtools-vite` plugin
- Wrap app in `<StrictMode>` in `main.tsx`
- Add `.vscode/settings.json` (Biome formatter, format-on-save, readonly
`routeTree.gen.ts`) and `.vscode/extensions.json` (recommended extensions)
* Move test DB helpers to @sofa/db/test-utils and add root bunfig.toml
Extract in-memory SQLite setup and fixture helpers (insertUser, insertTitle,
etc.) from packages/core/test/sqlite.ts into packages/db/src/test-utils.ts
so DB test utilities live alongside the schema they depend on. Use
import.meta.dir for CWD-independent migration path resolution.
Add root bunfig.toml so `bun test` works from the repo root in addition
to `bun run test` (turbo).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix devtools plugin order and whitespace-only TMDB token check
Move devtools() to first position in Vite plugins array per TanStack
docs, and trim TMDB_API_READ_ACCESS_TOKEN before boolean coercion so
whitespace-only values are treated as unconfigured.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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>
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>