Quick Start
Define your schema once, pass relations and (for SQLite) migrations, create a client for your runtime, and run your first query. One mental model—portable across adapters.
1) Define a schema with relations
1// db/schema.ts
2import { defineSchema, vibecodeTable, int, text, boolean, datetime, references, col } from '@vibecode-db/client'
3
4export const db = defineSchema({
5 users: vibecodeTable({
6 id: int().primaryKey(),
7 name: text().min(1),
8 email: text().email(),
9 }),
10
11 todos: vibecodeTable({
12 id: text().primaryKey(),
13 title: text(),
14 completed: boolean().default(false),
15 created_at: datetime(),
16 updated_at: datetime(),
17 user_id: references(col.integer('user_id'), () => db.tables.users.id),
18 }),
19})- The schema above produces
db.zodBundle(Zod validators) anddb.relations. - Use the explicit
references(col.integer('user_id'), () => <table>.id)helper to define foreign keys.
2) Prepare your DB spec (schema + relations + optional seed)
1// db/spec.ts
2import type { DBSpec } from '@vibecode-db/client'
3import { db } from './schema'
4
5export const dbSpec: DBSpec<typeof db.zodBundle.shape> = {
6 schema: db.zodBundle,
7 relations: db.relations,
8 seed: {
9 users: [
10 { id: 1, name: 'Ada', email: 'ada@example.com' },
11 { id: 2, name: 'Alan', email: 'alan@example.com' },
12 ],
13 todos: [
14 {
15 id: 't1',
16 title: 'Wire the UI',
17 completed: false,
18 user_id: 1,
19 created_at: new Date(),
20 updated_at: new Date(),
21 },
22 ],
23 },
24}
dbSpecis passed to the client so adapters can initialize consistently.
3) (SQLite only) Provide migrations
1// db/migrations.ts
2export const migrations: string[] = [
3 // users
4 `CREATE TABLE IF NOT EXISTS "users" (
5 "id" INTEGER PRIMARY KEY,
6 "name" TEXT,
7 "email" TEXT
8 );`,
9
10 // todos + FK → users.id
11 `CREATE TABLE IF NOT EXISTS "todos" (
12 "id" TEXT PRIMARY KEY,
13 "title" TEXT,
14 "completed" INTEGER,
15 "created_at" TEXT,
16 "updated_at" TEXT,
17 "user_id" INTEGER,
18 FOREIGN KEY("user_id") REFERENCES "users"("id")
19 );`,
20
21 // (optional) helpful index
22 `CREATE INDEX IF NOT EXISTS "todos_created_at_idx" ON "todos" ("created_at");`,
23]- Supply these to SQLite adapters so tables exist before queries run.
4) Create the client (pick ONE adapter per target)
Web (sqlite‑web, WASM)
1// db/client.web.ts
2import { createClient } from '@vibecode-db/client'
3import { SQLiteAdapter } from '@vibecode-db/sqlite-web'
4import { dbSpec } from './spec'
5import { migrations } from './migrations'
6
7export const db = createClient({
8 dbSpec,
9 adapter: (ctx) =>
10 new SQLiteAdapter(ctx, {
11 wasm: { wasmUrl: '/sql-wasm.wasm' }, // ensure this asset is served
12 migrations,
13 // persistence: 'opfs' | 'idb' (optional)
14 }),
15})Expo / React Native (sqlite‑expo)
1// db/client.expo.ts
2import { createClient } from '@vibecode-db/client'
3import { SQLiteAdapter } from '@vibecode-db/sqlite-expo'
4import { dbSpec } from './spec'
5import { migrations } from './migrations'
6
7export const db = createClient({
8 dbSpec,
9 adapter: (ctx) =>
10 new SQLiteAdapter(ctx, {
11 native: { dbName: 'vibecode.db' },
12 migrations,
13 // enableForeignKeys: true, // optional
14 }),
15})Supabase uses the same vibecode‑db client surface; wire credentials in the Supabase adapter (see Adapters → Supabase). We avoid documenting
sqlite-corehere (tooling-only).
5) First query
1import { db } from './db/client.web' // or .expo
2
3// Insert
4await db.from('users').insert({ id: 3, name: 'Grace', email: 'grace@example.com' })
5
6// Filter, then project
7const todos = await db
8 .from('todos')
9 .where({ user_id: 1 })
10 .select('id, title, users(name)') // nested projection from related tableInputs/outputs are validated by Zod at runtime and are fully typed at compile time. The query builder is identical across adapters.
You’re ready
You now have: a schema with relations → a dbSpec (schema + relations + optional seed) → migrations (for SQLite) → a client bound to your environment. Next, see Configuration for per‑adapter options or Defining Your Schema to model richer relations and constraints.