Getting Started
From zero to working sync in 6 steps
Prefer AI setup?
Copy a prompt for Claude/Cursor that analyzes your project and generates everything.
1. Install
pnpm add bettersync @electric-sql/pglite2. Create Sync Config
import { betterSync } from 'bettersync'
import { drizzleAdapter } from 'bettersync/adapters/drizzle'
import { db } from './db'
import { projects } from './db/schema'
export const sync = betterSync({
database: drizzleAdapter(db, { schema: { project: projects } }),
models: {
project: {
fields: {
id: { type: 'string', primaryKey: true },
userId: { type: 'string' },
title: { type: 'string' },
changed: { type: 'string' },
},
scope: (ctx) => ({ userId: ctx.userId }),
},
},
auth: async (req) => {
const session = await getSession(req.headers)
if (!session) throw new Error('Unauthorized')
return { userId: session.user.id }
},
})
export const syncSchema = sync.schema3. Mount Handler
import { sync } from '@/lib/sync'
export const POST = sync.handlerOr with Express/NestJS:
import { toNodeHandler } from 'bettersync/node'
app.post('/api/sync', toNodeHandler(sync))4. Generate Tables
npx @bettersync/cli generate --config lib/sync.ts5. Create Client
import { createSyncClient } from 'bettersync/client'
import { pgliteAdapter } from 'bettersync/adapters/pglite'
import { PGlite } from '@electric-sql/pglite'
import { syncSchema } from './sync'
export const syncClient = createSyncClient({
database: pgliteAdapter(new PGlite('idb://my-app')),
schema: syncSchema,
syncUrl: '/api/sync',
})6. Use in React
import { SyncProvider, useSync, useSyncQuery, SyncDevtools } from 'bettersync/react'
function App() {
return (
<SyncProvider client={syncClient}>
<TodoList />
<SyncDevtools />
</SyncProvider>
)
}
function TodoList() {
const sync = useSync()
const { data: todos } = useSyncQuery(
(s) => s.model('todo').findMany(), [],
{ live: true },
)
return <ul>{todos?.map(t => <li key={String(t.id)}>{String(t.title)}</li>)}</ul>
}Open two tabs. Add a todo in one. See it in the other.