# Supabase
URL: /docs/integrations/supabase
LLM index: /llms.txt
Description: How to use Farming Labs ORM with Supabase through either its PostgreSQL connection layer or the direct Supabase JS client.

# Supabase

Supabase now fits through two honest paths:

- the PostgreSQL connection layer
- the direct Supabase JS client runtime

Both paths keep the same schema definition and the same ORM query surface.

## Which path to use

Use the PostgreSQL path when:

- the app already owns a `pg` pool or client
- you want SQL-style setup helpers such as `pushSchema(...)`
- you want the ORM to behave like the normal PostgreSQL runtime

Use the direct Supabase JS path when:

- the app already owns a `createClient(...)` instance
- you want to accept that client directly instead of asking for a second DB client
- you want the ORM to speak the Supabase table API rather than a hidden raw `pg` bridge

## PostgreSQL path

If you already have a `pg` pool or client connected to Supabase, use the
PostgreSQL aliases in `@farming-labs/orm-sql`.

```ts title="supabase-postgres-runtime.ts"
import { createOrm } from "@farming-labs/orm";
import { createSupabasePoolDriver } from "@farming-labs/orm-sql";
import { Pool } from "pg";
import { appSchema } from "./schema";

const pool = new Pool({
  connectionString: process.env.SUPABASE_DB_URL,
});

const orm = createOrm({
  schema: appSchema,
  driver: createSupabasePoolDriver(pool),
});
```

If you already have a connected PostgreSQL client instead of a pool:

```ts
import { createOrm } from "@farming-labs/orm";
import { createSupabaseClientDriver } from "@farming-labs/orm-sql";

const orm = createOrm({
  schema: appSchema,
  driver: createSupabaseClientDriver(pgClient),
});
```

This path stays intentionally thin because it is still just PostgreSQL.

## Direct Supabase JS path

If the app already has a Supabase client, use the dedicated runtime:

```ts title="supabase-js-runtime.ts"
import { createOrm } from "@farming-labs/orm";
import { createSupabaseDriver } from "@farming-labs/orm-supabase";
import { createClient } from "@supabase/supabase-js";
import { appSchema } from "./schema";

const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_SERVICE_ROLE_KEY!);

const orm = createOrm({
  schema: appSchema,
  driver: createSupabaseDriver({
    client: supabase,
  }),
});
```

Or let the runtime helpers detect it directly:

```ts
import { createOrmFromRuntime } from "@farming-labs/orm-runtime";

const orm = await createOrmFromRuntime({
  schema: appSchema,
  client: supabase,
});
```

This runtime uses Supabase's own client API. It does **not** wrap a hidden raw
PostgreSQL bridge.

## Setup helpers

If the package or framework needs to prepare the database before tests or setup
flows, use the PostgreSQL path with the runtime-aware setup helpers:

```ts
import { pushSchema } from "@farming-labs/orm-runtime/setup";

await pushSchema({
  schema: appSchema,
  client: pool,
});
```

Or, if you want setup plus the ORM back:

```ts
import { bootstrapDatabase } from "@farming-labs/orm-runtime/setup";

const orm = await bootstrapDatabase({
  schema: appSchema,
  client: pool,
});
```

For the direct Supabase JS runtime, `pushSchema(...)` and `applySchema(...)`
stay no-op. That path assumes the Supabase tables already exist.

## Generated output

If the consuming app wants generated artifacts instead of only the live runtime,
the same schema can still render:

```ts
import { renderDrizzleSchema, renderPrismaSchema, renderSafeSql } from "@farming-labs/orm";

const prismaSchema = renderPrismaSchema(appSchema, {
  provider: "postgresql",
});

const drizzleSchema = renderDrizzleSchema(appSchema, {
  dialect: "pg",
});

const sqlSchema = renderSafeSql(appSchema, {
  dialect: "postgres",
});
```

## Connection guidance

Supabase's own docs are still the right place to choose the actual connection
mode, TLS settings, and connection string for your environment:

- [Connect to your database](https://supabase.com/docs/guides/database/connecting-to-postgres)
- [Connection strings](https://supabase.com/docs/reference/postgres/connection-strings)

Keep the provider-recommended TLS settings for your environment. Avoid
disabling certificate verification in connection examples unless you are
debugging a local-only setup and fully understand the tradeoff.

## Why this matters

This lets a library or framework:

- keep one schema definition
- accept either a raw PostgreSQL client or a Supabase client
- reuse the same ORM query surface across both app styles
- avoid forcing every Supabase app into the same connection strategy