Core Concepts — Models, Tables & Columns
Models describe tables; columns specify the kind of each field. You declare them once with the vibecode‑db schema DSL and get a Zod bundle and TypeScript types from that single source of truth. (Foreign keys/relations are introduced separately.)
Column kinds (current surface)
The column kinds available today are:
1integer | varchar | boolean | timestamp | uuid | json | enumYou declare kinds via the col helper from @vibecode-db/client.
Define models & columns
1import { defineSchema, vibecodeTable, col } from '@vibecode-db/client'
2
3export const db = defineSchema({
4 users: vibecodeTable('users', {
5 id: col.integer(),
6 name: col.varchar(),
7 email: col.varchar(),
8 }),
9
10 todos: vibecodeTable('todos', {
11 id: col.uuid(),
12 title: col.varchar(),
13 completed: col.boolean(),
14 created_at: col.timestamp(),
15 updated_at: col.timestamp(),
16 user_id: col.integer(), // FK source column; relation declared separately
17 }),
18})
19// Outputs → db.zodBundle (validators) and typed shapes for queriesNote: Constraints (e.g., min/max, email, defaults) and explicit nullability are not part of the current column surface. Keep definitions focused on kind for now.
Relations preview (declared elsewhere)
- Keep the source column (e.g.,
user_id: col.integer()) in the table. - Declare the foreign key relation using
references(...)in the Relations step (next doc), e.g. linkingtodos.user_id→users.id. - Relations become part of
db.relationsand are included in yourDBSpec.
Modeling tips (for the current surface)
- Start with stable table and column names; migrations in SQLite depend on them.
- Use
uuidfor app‑generated identifiers; useintegerfor numeric counters or SQLite rowids. - Prefer
timestampfor date‑time fields to keep adapters consistent. - Use
jsonfor nested blobs you don’t want to normalize yet; consider promoting to tables later. - Use
enumsparingly for small, well‑known value sets.
Summary
Define tables with vibecodeTable('<name>', { ... }) and pick column kinds with col.<kind>(). That’s it on this layer—no constraints/nullability. Add relations in the next step and include both schema and relations in your DBSpec to power adapters and typed queries.