Kanban Example
A Svelte app using Prisma Next IDB, migrations, auth, and full bidirectional sync
The Prisma Next kanban example is a full-stack SvelteKit app: an IndexedDB client in the browser, a Postgres server, better-auth for sessions (Google OAuth and anonymous guest sign-in), and the sync engine keeping the two databases in sync per user.
Live app: next-kanban.prisma-idb.dev
Source: apps/prisma-next-idb-kanban-example
What it shows
- One
schema.prismainterpreted twice — a client (IDB) projection and a server (Postgres) projection — with@@idb.excludemarking better-auth'sSession,Account, andVerificationtables as server-only (see Client Contracts) - Committed migration chains for both sides:
migrations/app(IDB) andmigrations-postgres/app(Postgres) createManagedAutoSyncIdbClientfor a singleton, race-safe, auto-migrating, sync-tracked client in one call (see Client)- Google + anonymous sign-in via better-auth, with the signed-in user mirrored into IDB through
withoutTrackingon first load - A
SyncWorkerpushing and pulling against/api/sync/pushand/api/sync/pull, withcreateSyncServer's ownership DAG authorizing every write and read server-side (see Server) - A pending-sync-count badge driven by the
"outboxwrite"event, and a resync on the browser'sonlineevent resetDb()(the managed client's race-safe wipe) called on sign-out, so a different account on the same browser never sees a previous session's local data- A minimal PWA manifest and service worker so the app shell works offline after the first load
Run it
From the repository root, bring up Postgres and initialize both databases:
pnpm --filter @prisma-next-idb/kanban-example db:up
pnpm --filter @prisma-next-idb/kanban-example db:init
pnpm --filter @prisma-next-idb/kanban-example devFor a production check:
pnpm --filter @prisma-next-idb/kanban-example check
pnpm --filter @prisma-next-idb/kanban-example build
pnpm --filter @prisma-next-idb/kanban-example test:e2eOffline behavior
The PWA setup intentionally stays small. The service worker precaches the built app shell and static files, then caches same-origin GET requests as they are fetched.
IndexedDB data already lives on the device. Once the browser has loaded the app and installed the service worker, the kanban UI can reopen offline, keep reading and writing local data, and queue outbox events for the SyncWorker to push once the connection returns.
Where to look
| File | Purpose |
|---|---|
src/lib/prisma/schema.prisma | Single schema, source for both the IDB and Postgres contracts |
src/lib/prisma/db.ts | Managed, auto-migrating, sync-tracked IDB client |
src/lib/server/auth.ts | better-auth config (Google + anonymous sign-in) |
src/lib/server/sync.ts | createSyncServer + createSqlSyncAdapter (@prisma-next-idb/sync-server-sql) setup |
src/routes/api/sync/push/+server.ts | Push endpoint — HTTP boundary around validatePush |
src/routes/api/sync/pull/+server.ts | Pull endpoint — HTTP boundary around buildPullQueries |
src/lib/stores/kanban.svelte.ts | Svelte state: loads the workspace, drives the sync worker |
src/service-worker.ts | Caches the app shell and same-origin assets |
static/manifest.webmanifest | Provides the installable PWA metadata |