Client
Setup
Configure the Drizzle ORM client with your superapp backend connection and generated schema.
The drizzle() function creates a Drizzle ORM instance configured with an HTTP driver that connects to your superapp backend.
import { drizzle } from '@superapp/db'
import * as schema from './generated/schema'
// Each user gets their own Drizzle instance tied to their JWT.
// All queries through this `db` are automatically scoped to this user's data.
const db = drizzle({
connection: 'http://localhost:3001',
token: session.token, // ← identifies who this user is
schema,
})Options
| Option | Type | Required | Description |
|---|---|---|---|
connection | string | Yes | Your superapp backend URL |
token | string | Yes | A valid JWT obtained from the auth client |
schema | object | Yes | Your generated Drizzle schema object |
Schema Import
The schema is auto-generated from your database by the CLI. It contains standard Drizzle table definitions:
import * as schema from './generated/schema'
// schema.orders → pgTable('orders', { ... })
// schema.customers → pgTable('customers', { ... })
// schema.ordersRelations → relations(orders, ({ one }) => ({ ... }))See Type Generation for how to generate the schema.
Recommended Setup
Create a shared setup file and a React hook for easy access across your app.
lib/db.ts
import { drizzle } from '@superapp/db'
import { createAuth } from '@superapp/auth'
import * as schema from '../generated/schema'
const SUPERAPP_URL = process.env.NEXT_PUBLIC_SUPERAPP_URL!
export const authClient = createAuth(SUPERAPP_URL)
export function createDb(token: string) {
return drizzle({
connection: SUPERAPP_URL,
token,
schema,
})
}hooks/use-db.ts
import { useMemo } from 'react'
import { useSession } from '@superapp/auth'
import { createDb } from '@/lib/db'
export function useDb() {
const { data: session } = useSession()
return useMemo(
() => (session?.token ? createDb(session.token) : null),
[session?.token]
)
}Usage in a component:
import { useDb } from '@/hooks/use-db'
import { eq, desc } from 'drizzle-orm'
import * as schema from '@/generated/schema'
export function OrdersList() {
const db = useDb()
async function loadOrders() {
if (!db) return
// No user_id filter needed — the backend scopes results automatically.
// Each user only sees their own orders.
const orders = await db.select()
.from(schema.orders)
.where(eq(schema.orders.status, 'active'))
.orderBy(desc(schema.orders.createdAt))
.limit(50)
}
}How It Works
When you call a Drizzle query method, the HTTP driver:
- Serializes the query to a structured format.
- POSTs it to the backend with the JWT in the
Authorizationheader. - The backend validates the token, applies row-level permissions, and executes the query.
- Returns the typed result.
The query syntax is identical to standard Drizzle ORM — the only difference is the transport layer.