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 | enum

You 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 queries

Note: 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. linking todos.user_idusers.id.
  • Relations become part of db.relations and are included in your DBSpec.

Modeling tips (for the current surface)

  • Start with stable table and column names; migrations in SQLite depend on them.
  • Use uuid for app‑generated identifiers; use integer for numeric counters or SQLite rowids.
  • Prefer timestamp for date‑time fields to keep adapters consistent.
  • Use json for nested blobs you don’t want to normalize yet; consider promoting to tables later.
  • Use enum sparingly 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.