Core Concepts
This page gives you a mental model for vibecode‑db at a glance—what each piece is for, how they fit, and the few rules that keep everything consistent across environments.
3.1 Client & Context
- Client: the runtime interface you call (
createClient→db.from(...).where(...).select(...)). - Context (ctx): passed to the adapter factory; contains your full DBSpec so adapters can initialize consistently.
3.2 Adapters
- Bind the client to a runtime (Web WASM, Expo/React Native, Supabase).
- The query API stays the same; only adapter wiring differs per environment.
3.3 Schema (vibecode‑db schema → Zod)
- Define tables and columns with the schema DSL (
defineSchema,vibecodeTable, column helpers). - The DSL generates a Zod bundle (runtime validation) and TypeScript types (compile‑time safety).
3.4 DBSpec
- A typed object you pass to the client and adapters:
{ schema, relations, seed?, meta? } schema(required): the Zod bundle from your DSL.relations(required when you model FKs): graph inferred from your DSL.seed(optional): boot data for local/dev.meta(optional): adapter‑specific metadata.
3.5 Models, Tables & Columns
- A model maps to a SQL table.
- Columns are defined with helpers (
int,text,boolean,datetime, …) and constraints (primaryKey,min, etc.).
3.6 Relations (one‑to‑one, one‑to‑many)
- Use
referenceswithcolto declare FKs in the schema DSL. - Example:
user_id: references(col.integer('user_id'), () => db.tables.users.id) - Relations are used for nested reads and to inform adapters about integrity.
3.7 Query Builder (fluent chain)
- Chain filters/modifiers first, then call
.select(...)to execute. - Supports nested projection strings for relations:
select('id, title, users(name)')
3.8 Migrations & Seeding (overview)
- SQLite (Web/Expo): provide a
string[]of SQL statements; adapters run them on startup. - Seeding: optional initial rows per table; useful for demos, tests, and rapid prototyping.
Put it together
- Define schema + relations → get Zod + types.
- Build a DBSpec.
- Create a client with an adapter per environment.
- Query using the same API everywhere.
That’s the core idea: one schema and one fluent API—portable across runtimes.