supabase · git:20260616.c038b3b · 2026-06-16 · sha256 c3821563066337ac

supabase git:20260616.c038b3bA

Immutable. This exact content never changes and is served at /api/v1/blob/c3821563066337ac.

---
name: supabase
description: Wire up Supabase for a project or extend an existing integration. Covers schema design, RLS policies, migrations, TypeScript type generation, and auth sync with external providers.
category: devops
tags: [supabase, postgres, rls, auth, migrations, typescript]
author: tushaarmehtaa
---

Set up or extend a Supabase integration from schema to type-safe queries.

## Context to read

- `supabase/` directory if it exists
- Any `*.sql` files in the repo
- `.env.local` or `.env` for `SUPABASE_URL` and `SUPABASE_ANON_KEY`
- Auth config (Clerk, Auth0, or Supabase Auth)
- `package.json` for `@supabase/supabase-js` version

## Steps

### 1. Check what exists

```bash
ls supabase/ 2>/dev/null
cat supabase/config.toml 2>/dev/null
```

Is Supabase initialized? Are there existing migrations? Which tables exist?

### 2. Schema design

For each new table:
- `uuid` primary key with `gen_random_uuid()` default
- `created_at timestamptz default now()`
- `updated_at timestamptz default now()`
- `user_id` for user-owned rows

If using an external auth provider (Clerk, Auth0), store their user ID as text — not a reference to `auth.users`:

```sql
user_id text not null  -- clerk user_id, not uuid ref to auth.users
```

### 3. RLS policies

Enable RLS on every table that holds user data:

```sql
alter table public.your_table enable row level security;

-- for Supabase Auth
create policy "users read own rows"
  on public.your_table for select
  using (user_id = auth.uid()::text);

-- for external auth (Clerk/Auth0): use a JWT claim helper
create policy "users read own rows"
  on public.your_table for select
  using (user_id = (auth.jwt() ->> 'sub'));
```

Add insert, update, delete policies for each table. Never leave a table with RLS enabled but no policies — all queries will fail silently.

### 4. Migrations

```bash
supabase db diff --file describe_the_change
supabase migration up
```

Always generate a named migration file. Never edit the schema directly in production. If no Supabase CLI:

```bash
npx supabase db diff --file describe_the_change
```

### 5. Generate TypeScript types

```bash
supabase gen types typescript --local > src/types/supabase.ts
# or for remote:
supabase gen types typescript --project-id your-project-id > src/types/supabase.ts
```

Import the generated types in every query. Do not use `any` for Supabase results.

### 6. Client setup

```ts
// lib/supabase.ts — browser client
import { createBrowserClient } from "@supabase/ssr";
import type { Database } from "@/types/supabase";

export const supabase = createBrowserClient<Database>(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
```

```ts
// lib/supabase-server.ts — server components / route handlers
import { createServerClient } from "@supabase/ssr";
import { cookies } from "next/headers";
import type { Database } from "@/types/supabase";

export function createSupabaseServer() {
  const cookieStore = cookies();
  return createServerClient<Database>(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    { cookies: { get: (name) => cookieStore.get(name)?.value } }
  );
}
```

### 7. Output

Report:
- Tables created or modified
- RLS policies set (and which auth strategy they use)
- Migration files written
- Type generation command confirmed
- Any auth edge cases (external provider JWT claims, service role usage)