Drizzle schema

If you use Drizzle ORM, Studio can scaffold a screen straight from your schema.ts - no live database connection needed at generation time. Your schema file is the single source of truth.

Scaffold from a schema file

npx @svgrid/studio add customers --from src/lib/db/schema.ts
npm run dev            # open /customers

Given a Drizzle table:

// src/lib/db/schema.ts
import { pgTable, serial, text, integer, boolean, timestamp } from 'drizzle-orm/pg-core'

export const customers = pgTable('customers', {
  id: serial('id').primaryKey(),
  name: text('name').notNull(),
  email: text('email').notNull(),
  mrr: integer('mrr'),
  active: boolean('active').default(true),
  createdAt: timestamp('created_at').defaultNow(),
})

Studio reads the columns, primary key, and notNull constraints into an EntitySchema and generates the three files:

Generated files: the schema module, the +server.ts API route, and the +page.svelte screen.

If your file defines several tables, pick one:

npx @svgrid/studio add orders --from src/lib/db/schema.ts --table orders

Scaffold the whole app

Pass --all to generate a screen for every table in the file, plus a nav layout and a home page linking them:

npx @svgrid/studio add --all --from src/lib/db/schema.ts
npm run dev            # open / and browse every entity

Foreign keys are followed across the file. A .references() column becomes a relation field - a searchable lookup that shows the related row's label - and an enum column becomes a select:

export const users = pgTable('users', {
  id: serial('id').primaryKey(),
  name: text('name').notNull(),
})

export const roleEnum = pgEnum('role', ['admin', 'member'])

export const posts = pgTable('posts', {
  id: serial('id').primaryKey(),
  title: text('title').notNull(),
  role: roleEnum('role'),                                  // -> a select
  authorId: integer('author_id').references(() => users.id), // -> a lookup on users
})

Studio resolves each lookup's display field from the referenced table (a name or title column, if present), so the generated screens are linked out of the box.

Connecting the data

By default the generated API route starts in-memory so the screen runs immediately. When you are ready to hit the database, regenerate with a driver:

# emit a route wired to your database driver + DATABASE_URL
npx @svgrid/studio add customers --from src/lib/db/schema.ts --db postgres

...or keep your Drizzle db instance and wire it by hand - the generated schema

// src/routes/api/customers/+server.ts
import { sql } from 'drizzle-orm'
import { createKitHandlers, createSqlDataSource } from '@svgrid/enterprise'
import { db } from '$lib/server/db'
import { customersSchema, type CustomersRow } from '$lib/customers.schema'

const source = createSqlDataSource<CustomersRow>({
  schema: customersSchema,
  table: 'customers',
  dialect: { placeholders: '
#39;, ilike: true }, execute: async (text, params) => { const result = await db.execute(sql.raw(text, params)) return (result.rows ?? result) as Record<string, unknown>[] }, }) export const { POST } = createKitHandlers({ schema: customersSchema, source })

Renamed columns

When a Drizzle column name differs from its property key - createdAt: timestamp('created_at') - Studio records the real column as dbColumn: 'created_at' on the field. The grid and form key on createdAt, while createSqlDataSource reads / writes created_at and aliases it back, so a renamed column works end to end with no manual mapping.

Notes

See also