Use Drizzle ORM to define PostgreSQL tables in RefactKit, enforce tenant isolation with organizationId, push schema changes, and query data in server functions.
Use this file to discover all available pages before exploring further.
RefactKit uses Drizzle ORM with a PostgreSQL database hosted on Supabase. All table definitions live in a single file — db/schema.ts — which acts as the single source of truth for your entire data model. Drizzle generates fully-typed query builders from this schema, so TypeScript catches invalid field references at compile time rather than at runtime.
Open db/schema.ts to see the existing tables. The core schema ships with the tables required by Better Auth: user, session, account, verification, organization, member, and invitation. The galleryImage table is an example of a product-specific table:
Run this command to synchronize your schema file with the live database. Drizzle inspects the current database structure, diffs it against db/schema.ts, and applies only the changes needed:
npx drizzle-kit push
If you update the better-auth package, always check their changelog before running npx drizzle-kit push. Better Auth updates often add new columns to the core authentication tables. You must manually verify db/schema.ts matches their required schema before pushing.
Always include organizationId for tenant isolation
Every table that stores product data must include an organizationId foreign key. This is the cornerstone of RefactKit’s multi-tenancy model — it guarantees that no query can accidentally return data belonging to a different organization.
Add a database index on organizationId for every table. RefactKit’s pattern is to pass an (table) => [index('my_table_organizationId_idx').on(table.organizationId)] argument as the third parameter to pgTable. Without this index, queries that filter by organization will perform a full table scan as your data grows.
Drizzle Studio is a local browser-based UI for browsing and editing your database records directly:
npx drizzle-kit studio
This opens a web interface at https://local.drizzle.studio where you can inspect tables, run queries, and edit rows — useful during development without needing a separate database GUI tool.
Backend logic in RefactKit lives in server functions created with createServerFn from @tanstack/react-start. These run exclusively on the Nitro server and have direct access to the db instance. Use Zod to validate inputs before touching the database:
import { createServerFn } from '@tanstack/react-start'import { z } from 'zod'import { db } from '@/db'import { myTable } from '@/db/schema'export const createItem = createServerFn({ method: 'POST' }) .validator((data: unknown) => z.object({ name: z.string().min(1) }).parse(data) ) .handler(async ({ data }) => { const newItem = await db .insert(myTable) .values({ name: data.name }) .returning() return { item: newItem[0] } })
For read queries, scope every query to the current organization. Never return rows without filtering on organizationId: