Add Table Skill
Add or modify database tables in the x4-mono Drizzle ORM setup.
Arguments
The user describes the table or schema change they want. If unclear, ask for:
- Table name (snake_case)
- Columns with types
- Relations to existing tables
- Whether seed data is needed
Schema Conventions
All tables in packages/database/src/schema.ts must follow these patterns:
Standard Columns (always include)
id: uuid("id").primaryKey().defaultRandom(),
createdAt: timestamp("created_at").default(sql`now()`).notNull(),
updatedAt: timestamp("updated_at")
.default(sql`now()`)
.notNull()
.$onUpdate(() => new Date()),
Column Naming
- TypeScript: camelCase (
userId,createdAt) - SQL: snake_case via explicit names (
uuid("user_id"),timestamp("created_at")) - Always use explicit SQL column names
Foreign Keys
userId: uuid("user_id")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
Indexes
(table) => [index('idx_tablename_column').on(table.column)];
Relations
export const tableRelations = relations(tableName, ({ one, many }) => ({
owner: one(users, { fields: [tableName.ownerId], references: [users.id] }),
items: many(otherTable),
}));
Workflow
- Read current schema: Read
packages/database/src/schema.ts - Add table definition: Add
pgTable()with standard columns + custom columns - Add relations: Define relations if foreign keys exist
- Add Zod schema: Create corresponding Zod schemas in
packages/shared/ - Generate migration: Run
bun db:generate - Push to dev DB: Run
bun db:push - Add seed data: Update
packages/database/seed.tsif needed - Type check: Run
bun turbo type-checkto verify
Available Column Types
import {
pgTable,
uuid,
varchar,
text,
timestamp,
boolean,
integer,
numeric,
pgEnum,
index,
jsonb,
serial,
} from 'drizzle-orm/pg-core';
Important Notes
- Schema
status: text("status")returnsstringnot union type at runtime - Nullable columns return
string | nullnotstring | undefined - Output Zod schemas must match DB return types
- Use
db.select().from()SQL-like API, notdb.queryrelational API - Better Auth expects singular model names (
usernotusers) — the existingexport const user = users;alias handles this