superapp
ReferenceClient API

drizzle() Options

Drizzle client configuration reference.

drizzle() creates a Drizzle ORM instance using Drizzle Proxy that connects to your superapp backend. Drizzle builds parameterized SQL on the client, and the proxy driver sends SQL + params over HTTP. It returns a standard Drizzle db object with all query methods.

import { drizzle } from '@superapp/db'
import * as schema from './generated/schema'

const db = drizzle({
  connection: 'http://localhost:3001',
  token: session.token,
  schema,
})

Options

OptionTypeRequiredDefaultDescription
connectionstringYes--Your superapp backend URL. The proxy driver sends SQL + params to this endpoint.
tokenstringYes--A valid JWT obtained from the auth client. Sent as Authorization: Bearer <token> on every request.
schemaobjectYes--Your generated Drizzle schema object containing table definitions and relations.
const db = drizzle({
  connection: 'https://api.myapp.com',
  token: session.token,
  schema,
})

Schema

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', { id, amount, status, ... })
// schema.customers → pgTable('customers', { id, name, email, ... })
// schema.ordersRelations → relations(orders, ({ one }) => ({ customer: one(customers, { ... }) }))

Generating the Schema

Run the CLI against your running server:

npx @superapp/backend generate --url http://localhost:3001 --output ./generated/schema.ts

This introspects your database via the /schema endpoint and outputs a Drizzle schema file with all table definitions, column types, and relations.

Return Type

drizzle() returns a standard Drizzle database instance:

// Select builder
db.select().from(schema.orders).where(eq(schema.orders.status, 'active'))
db.select({ id: schema.orders.id }).from(schema.orders)

// Mutations
db.insert(schema.orders).values({ amount: 100, status: 'pending' })
db.update(schema.orders).set({ status: 'shipped' }).where(eq(schema.orders.id, 'ord_1'))
db.delete(schema.orders).where(eq(schema.orders.id, 'ord_1'))

// Relational queries
db.query.orders.findMany({ with: { customer: true }, limit: 50 })
db.query.orders.findFirst({ where: eq(schema.orders.id, 'ord_1') })

Shared Setup File

// 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,
  })
}

React Hook

// 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 Components

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
    const orders = await db.select()
      .from(schema.orders)
      .where(eq(schema.orders.status, 'active'))
      .orderBy(desc(schema.orders.createdAt))
      .limit(50)
    return orders
  }
}

How It Works

When you call a Drizzle query method, the proxy driver:

  1. Drizzle builds parameterized SQL on the client (e.g., SELECT ... FROM orders WHERE status = $1).
  2. POSTs SQL + params to the backend's /data endpoint with the JWT in the Authorization: Bearer header.
  3. The server validates the token, applies row-level permissions to the SQL, and executes through DuckDB.
  4. Returns typed results as JSON, deserialized into the expected TypeScript type.

This is standard Drizzle Proxy — the query syntax is identical to any other Drizzle setup, only the transport layer differs.

On this page