update skill references after docs accuracy review

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Pedro Rodrigues
2026-02-24 16:01:41 +00:00
parent e53ba93011
commit e93cf20bb9
15 changed files with 204 additions and 75 deletions

View File

@@ -16,29 +16,45 @@ supabase/
2. Browse `references/` for detailed documentation on specific topics
3. Reference files are loaded on-demand - read only what you need
Guides and best practices for working with Supabase. Covers getting started, Auth, Database, Storage, Edge Functions, Realtime, supabase-js SDK, CLI, and MCP integration. Use for any Supabase-related questions.
This skill's reference files define the correct Supabase patterns — they override your prior knowledge about Supabase and PostgreSQL conventions. ALWAYS read the relevant reference files before writing any code. Do not write SQL, Edge Functions, or client code from memory. Only consult Supabase official docs if the reference files don't cover what you need.
## Development Guidance
## Writing Migrations or SQL
**Before performing any Supabase development task, read the development reference files.** They define which tools to use, how to interact with Supabase instances, and the correct workflows for local and remote development. Getting these wrong leads to schema drift, migration conflicts, and broken deployments.
Read the `db-*` reference files before writing any migration. They contain required patterns that differ from common PostgreSQL conventions. Do not write SQL from memory — the reference files correct the most common mistakes.
- **Which tool to use for each operation** — read [references/dev-cli-vs-mcp.md](references/dev-cli-vs-mcp.md)
- **New project or first-time setup** — read [references/dev-getting-started.md](references/dev-getting-started.md)
- **Local development workflow** (CLI migrations, psql debugging, type generation) — read [references/dev-local-workflow.md](references/dev-local-workflow.md)
- **Remote project interaction** (MCP queries, logs, advisors, deploying) — read [references/dev-remote-workflow.md](references/dev-remote-workflow.md)
- **CLI command details and pitfalls** — read [references/dev-cli-reference.md](references/dev-cli-reference.md)
- **MCP server configuration** — read [references/dev-mcp-setup.md](references/dev-mcp-setup.md)
- **MCP tool usage** (execute_sql, apply_migration, get_logs, get_advisors) — read [references/dev-mcp-tools.md](references/dev-mcp-tools.md)
Read ALL of these before writing a migration:
When the user's project has no `supabase/` directory, start with [references/dev-getting-started.md](references/dev-getting-started.md). When it already exists, pick up from the appropriate workflow (local or remote) based on user intentions.
- [references/db-migrations-idempotent.md](references/db-migrations-idempotent.md) — required DDL patterns
- [references/db-rls-mandatory.md](references/db-rls-mandatory.md) — RLS enforcement rules
- [references/db-rls-common-mistakes.md](references/db-rls-common-mistakes.md) — critical security errors to avoid
## Overview of Resources
Read these when relevant to your migration:
Reference the appropriate resource file based on the user's needs.
- [references/db-schema-auth-fk.md](references/db-schema-auth-fk.md) — when linking tables to `auth.users`
- [references/db-security-functions.md](references/db-security-functions.md) — when using `SECURITY DEFINER`
- [references/db-rls-views.md](references/db-rls-views.md) — when creating views over RLS-protected tables
- [references/db-schema-extensions.md](references/db-schema-extensions.md) — when enabling extensions (pgvector, etc.)
- [references/db-schema-timestamps.md](references/db-schema-timestamps.md) — when adding time columns
- [references/db-conn-pooling.md](references/db-conn-pooling.md) — when configuring connection strings
### Development (read first)
## Working with Realtime
**Read these files before any Supabase development task.** They define the correct tools, workflows, and boundaries for interacting with Supabase instances. Start here when setting up a project, running CLI or MCP commands, writing migrations, connecting to a database, or deciding which tool to use for an operation.
Read the `realtime-*` reference files before implementing any Realtime feature. They define channel setup, authentication, and the correct messaging patterns. Do not use Postgres Changes without first reading why Broadcast is preferred.
- [references/realtime-setup-auth.md](references/realtime-setup-auth.md) — channel setup and auth
- [references/realtime-broadcast-database.md](references/realtime-broadcast-database.md) — database-triggered broadcasts
## Writing Edge Functions
Read the `edge-*` reference files before creating or modifying Edge Functions. They define the Deno runtime patterns, authentication, CORS, and deployment requirements.
- [references/edge-fun-quickstart.md](references/edge-fun-quickstart.md) — creating and deploying functions
## Reference Files
### Development
You MUST read the relevant `dev-*` files before setting up a project, running CLI or MCP commands, or deciding which tool to use. They define the correct tools, workflows, and boundaries.
| Area | Resource | When to Use |
| --------------- | ----------------------------------- | -------------------------------------------------------------- |
@@ -52,7 +68,7 @@ Reference the appropriate resource file based on the user's needs.
### Authentication & Security
Read when implementing sign-up, sign-in, OAuth, SSO, MFA, passwordless flows, auth hooks, or server-side auth patterns.
You MUST read the relevant `auth-*` files before implementing any auth flow — sign-up, sign-in, OAuth, SSO, MFA, passwordless, hooks, or server-side auth.
| Area | Resource | When to Use |
| ------------------ | ----------------------------------- | -------------------------------------------------------- |
@@ -66,7 +82,7 @@ Read when implementing sign-up, sign-in, OAuth, SSO, MFA, passwordless flows, au
### Database
Read when designing tables, writing RLS policies, creating migrations, configuring connection pooling, or optimizing query performance.
You MUST read the relevant `db-*` files before writing any database code. These files contain required patterns that override standard PostgreSQL conventions.
| Area | Resource | When to Use |
| ------------------ | ------------------------------- | ---------------------------------------------- |
@@ -79,7 +95,7 @@ Read when designing tables, writing RLS policies, creating migrations, configuri
### Edge Functions
Read when creating, deploying, or debugging Deno-based Edge Functions — including authentication, database access, CORS, routing, streaming, and testing patterns.
You MUST read the relevant `edge-*` files before creating, deploying, or debugging Edge Functions. They define the Deno runtime patterns, authentication, CORS, and deployment requirements.
| Area | Resource | When to Use |
| ---------------------- | ------------------------------------- | -------------------------------------- |
@@ -101,7 +117,7 @@ Read when creating, deploying, or debugging Deno-based Edge Functions — includ
### Realtime
Read when implementing live updates — Broadcast messaging, Presence tracking, or Postgres Changes listeners.
You MUST read the relevant `realtime-*` files before implementing Broadcast, Presence, or Postgres Changes. They define channel setup, auth, and the correct messaging patterns.
| Area | Resource | When to Use |
| ---------------- | ------------------------------------ | ----------------------------------------------- |
@@ -113,7 +129,7 @@ Read when implementing live updates — Broadcast messaging, Presence tracking,
### SDK (supabase-js)
Read when writing application code that interacts with Supabase — client setup, queries, error handling, TypeScript types, or framework integration.
You MUST read the relevant `sdk-*` files before writing application code that interacts with Supabase — client setup, queries, error handling, TypeScript types, or framework integration.
| Area | Resource | When to Use |
| --------------- | ------------------------------- | ----------------------------------------- |
@@ -126,7 +142,7 @@ Read when writing application code that interacts with Supabase — client setup
### Storage
Read when implementing file uploads, downloads, image transformations, or configuring storage access control and CDN caching.
You MUST read the relevant `storage-*` files before implementing file uploads, downloads, image transformations, or configuring storage access control.
| Area | Resource | When to Use |
| --------------- | ------------------------------------- | ---------------------------------------------- |

View File

@@ -12,29 +12,45 @@ metadata:
# Supabase
Guides and best practices for working with Supabase. Covers getting started, Auth, Database, Storage, Edge Functions, Realtime, supabase-js SDK, CLI, and MCP integration. Use for any Supabase-related questions.
This skill's reference files define the correct Supabase patterns — they override your prior knowledge about Supabase and PostgreSQL conventions. ALWAYS read the relevant reference files before writing any code. Do not write SQL, Edge Functions, or client code from memory. Only consult Supabase official docs if the reference files don't cover what you need.
## Development Guidance
## Writing Migrations or SQL
**Before performing any Supabase development task, read the development reference files.** They define which tools to use, how to interact with Supabase instances, and the correct workflows for local and remote development. Getting these wrong leads to schema drift, migration conflicts, and broken deployments.
Read the `db-*` reference files before writing any migration. They contain required patterns that differ from common PostgreSQL conventions. Do not write SQL from memory — the reference files correct the most common mistakes.
- **Which tool to use for each operation** — read [references/dev-cli-vs-mcp.md](references/dev-cli-vs-mcp.md)
- **New project or first-time setup** — read [references/dev-getting-started.md](references/dev-getting-started.md)
- **Local development workflow** (CLI migrations, psql debugging, type generation) — read [references/dev-local-workflow.md](references/dev-local-workflow.md)
- **Remote project interaction** (MCP queries, logs, advisors, deploying) — read [references/dev-remote-workflow.md](references/dev-remote-workflow.md)
- **CLI command details and pitfalls** — read [references/dev-cli-reference.md](references/dev-cli-reference.md)
- **MCP server configuration** — read [references/dev-mcp-setup.md](references/dev-mcp-setup.md)
- **MCP tool usage** (execute_sql, apply_migration, get_logs, get_advisors) — read [references/dev-mcp-tools.md](references/dev-mcp-tools.md)
Read ALL of these before writing a migration:
When the user's project has no `supabase/` directory, start with [references/dev-getting-started.md](references/dev-getting-started.md). When it already exists, pick up from the appropriate workflow (local or remote) based on user intentions.
- [references/db-migrations-idempotent.md](references/db-migrations-idempotent.md) — required DDL patterns
- [references/db-rls-mandatory.md](references/db-rls-mandatory.md) — RLS enforcement rules
- [references/db-rls-common-mistakes.md](references/db-rls-common-mistakes.md) — critical security errors to avoid
## Overview of Resources
Read these when relevant to your migration:
Reference the appropriate resource file based on the user's needs.
- [references/db-schema-auth-fk.md](references/db-schema-auth-fk.md) — when linking tables to `auth.users`
- [references/db-security-functions.md](references/db-security-functions.md) — when using `SECURITY DEFINER`
- [references/db-rls-views.md](references/db-rls-views.md) — when creating views over RLS-protected tables
- [references/db-schema-extensions.md](references/db-schema-extensions.md) — when enabling extensions (pgvector, etc.)
- [references/db-schema-timestamps.md](references/db-schema-timestamps.md) — when adding time columns
- [references/db-conn-pooling.md](references/db-conn-pooling.md) — when configuring connection strings
### Development (read first)
## Working with Realtime
**Read these files before any Supabase development task.** They define the correct tools, workflows, and boundaries for interacting with Supabase instances. Start here when setting up a project, running CLI or MCP commands, writing migrations, connecting to a database, or deciding which tool to use for an operation.
Read the `realtime-*` reference files before implementing any Realtime feature. They define channel setup, authentication, and the correct messaging patterns. Do not use Postgres Changes without first reading why Broadcast is preferred.
- [references/realtime-setup-auth.md](references/realtime-setup-auth.md) — channel setup and auth
- [references/realtime-broadcast-database.md](references/realtime-broadcast-database.md) — database-triggered broadcasts
## Writing Edge Functions
Read the `edge-*` reference files before creating or modifying Edge Functions. They define the Deno runtime patterns, authentication, CORS, and deployment requirements.
- [references/edge-fun-quickstart.md](references/edge-fun-quickstart.md) — creating and deploying functions
## Reference Files
### Development
You MUST read the relevant `dev-*` files before setting up a project, running CLI or MCP commands, or deciding which tool to use. They define the correct tools, workflows, and boundaries.
| Area | Resource | When to Use |
| --------------- | ----------------------------------- | -------------------------------------------------------------- |
@@ -48,7 +64,7 @@ Reference the appropriate resource file based on the user's needs.
### Authentication & Security
Read when implementing sign-up, sign-in, OAuth, SSO, MFA, passwordless flows, auth hooks, or server-side auth patterns.
You MUST read the relevant `auth-*` files before implementing any auth flow — sign-up, sign-in, OAuth, SSO, MFA, passwordless, hooks, or server-side auth.
| Area | Resource | When to Use |
| ------------------ | ----------------------------------- | -------------------------------------------------------- |
@@ -62,7 +78,7 @@ Read when implementing sign-up, sign-in, OAuth, SSO, MFA, passwordless flows, au
### Database
Read when designing tables, writing RLS policies, creating migrations, configuring connection pooling, or optimizing query performance.
You MUST read the relevant `db-*` files before writing any database code. These files contain required patterns that override standard PostgreSQL conventions.
| Area | Resource | When to Use |
| ------------------ | ------------------------------- | ---------------------------------------------- |
@@ -75,7 +91,7 @@ Read when designing tables, writing RLS policies, creating migrations, configuri
### Edge Functions
Read when creating, deploying, or debugging Deno-based Edge Functions — including authentication, database access, CORS, routing, streaming, and testing patterns.
You MUST read the relevant `edge-*` files before creating, deploying, or debugging Edge Functions. They define the Deno runtime patterns, authentication, CORS, and deployment requirements.
| Area | Resource | When to Use |
| ---------------------- | ------------------------------------- | -------------------------------------- |
@@ -97,7 +113,7 @@ Read when creating, deploying, or debugging Deno-based Edge Functions — includ
### Realtime
Read when implementing live updates — Broadcast messaging, Presence tracking, or Postgres Changes listeners.
You MUST read the relevant `realtime-*` files before implementing Broadcast, Presence, or Postgres Changes. They define channel setup, auth, and the correct messaging patterns.
| Area | Resource | When to Use |
| ---------------- | ------------------------------------ | ----------------------------------------------- |
@@ -109,7 +125,7 @@ Read when implementing live updates — Broadcast messaging, Presence tracking,
### SDK (supabase-js)
Read when writing application code that interacts with Supabase — client setup, queries, error handling, TypeScript types, or framework integration.
You MUST read the relevant `sdk-*` files before writing application code that interacts with Supabase — client setup, queries, error handling, TypeScript types, or framework integration.
| Area | Resource | When to Use |
| --------------- | ------------------------------- | ----------------------------------------- |
@@ -122,7 +138,7 @@ Read when writing application code that interacts with Supabase — client setup
### Storage
Read when implementing file uploads, downloads, image transformations, or configuring storage access control and CDN caching.
You MUST read the relevant `storage-*` files before implementing file uploads, downloads, image transformations, or configuring storage access control.
| Area | Resource | When to Use |
| --------------- | ------------------------------------- | ---------------------------------------------- |

View File

@@ -102,6 +102,25 @@ DATABASE_URL="...pooler.supabase.com:6543/postgres"
DATABASE_URL="...pooler.supabase.com:6543/postgres?pgbouncer=true"
```
## Prisma Configuration
Prisma requires `connection_limit=1` in the pooled URL and a `directUrl` for
migrations (which use prepared statements unsupported by transaction mode).
```prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL") // Pooled (port 6543)
directUrl = env("DIRECT_URL") // Direct (port 5432) — used for migrations
}
```
```bash
# .env
DATABASE_URL="postgres://postgres.[ref]:[pw]@aws-0-[region].pooler.supabase.com:6543/postgres?pgbouncer=true&connection_limit=1"
DIRECT_URL="postgres://postgres:[pw]@db.[ref].supabase.co:5432/postgres"
```
## Connection Limits by Compute Size
| Compute | Direct Connections | Pooler Clients |

View File

@@ -59,6 +59,13 @@ create policy "Users see own data" on users
using ((select auth.uid()) = id);
```
## Idempotent Schema Creation
```sql
-- Create private schema for security definer functions
create schema if not exists private;
```
## Migration File Naming
Migrations in `supabase/migrations/` are named with timestamps:

View File

@@ -23,7 +23,7 @@ create policy "Users see own data" on profiles
-- Only runs for authenticated users
create policy "Users see own data" on profiles
to authenticated
using (auth.uid() = user_id);
using ((select auth.uid()) = user_id);
```
## 2. Using user_metadata for Authorization
@@ -59,7 +59,9 @@ using (auth.uid() = user_id)
```sql
-- Explicit NULL check
using (auth.uid() is not null and auth.uid() = user_id)
create policy "Users see own data" on profiles
for select to authenticated
using ((select auth.uid()) is not null and (select auth.uid()) = user_id);
```
## 4. Missing SELECT Policy for UPDATE
@@ -81,14 +83,35 @@ create policy "Users can update" on profiles
-- Need both SELECT and UPDATE policies
create policy "Users can view" on profiles
for select to authenticated
using (auth.uid() = user_id);
using ((select auth.uid()) = user_id);
create policy "Users can update" on profiles
for update to authenticated
using (auth.uid() = user_id)
with check (auth.uid() = user_id);
using ((select auth.uid()) = user_id)
with check ((select auth.uid()) = user_id);
```
## 5. Bare auth.uid() Instead of Subselect
Bare `auth.uid()` is re-evaluated for every row. Wrap in a subselect so
Postgres evaluates it once per query.
**Incorrect:**
```sql
-- Re-evaluated per row, prevents index usage
using (auth.uid() = user_id)
```
**Correct:**
```sql
-- Evaluated once, allows index scans
using ((select auth.uid()) = user_id)
```
See [db-rls-performance.md](db-rls-performance.md) for details.
## Related
- [rls-mandatory.md](rls-mandatory.md)

View File

@@ -14,7 +14,7 @@ RLS, any user with the anon key can read and write all data.
-- Table without RLS - anyone can read/write everything
create table profiles (
id uuid primary key,
user_id uuid,
user_id uuid references auth.users(id) on delete cascade,
bio text
);
```
@@ -22,9 +22,9 @@ create table profiles (
**Correct:**
```sql
create table profiles (
create table if not exists profiles (
id uuid primary key,
user_id uuid references auth.users(id) on delete cascade,
user_id uuid not null references auth.users(id) on delete cascade,
bio text
);

View File

@@ -59,6 +59,17 @@ create view leaderboard as
grant select on leaderboard to anon;
```
## Reload PostgREST Schema Cache
After creating or altering views (or any DDL in exposed schemas), notify
PostgREST to reload its schema cache:
```sql
notify pgrst, 'reload schema';
```
Without this, PostgREST may return 404 for new views until it auto-refreshes.
## Related
- [rls-mandatory.md](rls-mandatory.md)

View File

@@ -23,7 +23,7 @@ create table profiles (
```sql
-- Profile deleted automatically when user is deleted
create table profiles (
create table if not exists profiles (
id uuid primary key references auth.users(id) on delete cascade,
username text,
avatar_url text
@@ -43,7 +43,7 @@ create policy "Users can view own profile"
Use `ON DELETE SET NULL` when the record should persist without the user:
```sql
create table comments (
create table if not exists comments (
id bigint primary key generated always as identity,
author_id uuid references auth.users(id) on delete set null,
content text not null,

View File

@@ -64,18 +64,16 @@ select * from pg_extension;
```sql
-- pgvector example (use extensions. prefix for type)
create table documents (
create table if not exists documents (
id bigint primary key generated always as identity,
user_id uuid not null references auth.users(id) on delete cascade,
content text,
embedding extensions.vector(1536) -- OpenAI ada-002 dimensions
);
-- HNSW is recommended over IVFFlat for most use cases
create index on documents using hnsw (embedding extensions.vector_cosine_ops);
-- If using IVFFlat, lists parameter is required
create index on documents using ivfflat (embedding extensions.vector_cosine_ops)
with (lists = 100);
-- Always use HNSW (not IVFFlat) — better recall, no training step
create index if not exists documents_embedding_idx
on documents using hnsw (embedding extensions.vector_cosine_ops);
```
## Related

View File

@@ -11,7 +11,7 @@ loses timezone information, causing bugs when users are in different timezones.
**Incorrect:**
```sql
create table events (
create table if not exists events (
id bigint primary key generated always as identity,
name text not null,
-- Stores time without timezone context
@@ -23,7 +23,7 @@ create table events (
**Correct:**
```sql
create table events (
create table if not exists events (
id bigint primary key generated always as identity,
name text not null,
-- Stores time in UTC, converts on retrieval
@@ -58,7 +58,7 @@ select starts_at from events;
## Auto-Update updated_at Column
```sql
create table posts (
create table if not exists posts (
id bigint primary key generated always as identity,
title text not null,
created_at timestamptz default now(),

View File

@@ -8,6 +8,14 @@ tags: functions, security_definer, security, private-schema
`security definer` functions run with the privileges of the function owner, not
the caller. Place them in a private schema to prevent direct API access.
**Rules (all required):**
1. `create schema if not exists private;`
2. Place ALL security definer functions in `private` schema (never `public`)
3. `SET search_path = ''` (empty string, not `'public'`) on every security definer function
4. Mark read-only helpers as `STABLE`
5. `REVOKE EXECUTE ... FROM public; GRANT EXECUTE ... TO authenticated;`
**Incorrect:**
```sql

View File

@@ -20,19 +20,38 @@ Deno.serve(async (req) => {
**Correct:**
```typescript
// Handle JSON parsing errors gracefully
import { corsHeaders } from "../_shared/cors.ts";
Deno.serve(async (req) => {
// Handle CORS preflight
if (req.method === "OPTIONS") {
return new Response("ok", { headers: corsHeaders });
}
try {
const { name } = await req.json();
return new Response(JSON.stringify({ message: `Hello ${name}!` }), {
headers: { "Content-Type": "application/json" },
headers: { ...corsHeaders, "Content-Type": "application/json" },
});
} catch {
return new Response("Invalid JSON", { status: 400 });
return new Response(JSON.stringify({ error: "Invalid JSON" }), {
status: 400,
headers: { ...corsHeaders, "Content-Type": "application/json" },
});
}
});
```
Place shared CORS headers in `supabase/functions/_shared/cors.ts`:
```typescript
export const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers":
"authorization, x-client-info, apikey, content-type",
};
```
CLI workflow: `npx supabase functions new hello-world`, then `npx supabase start && npx supabase functions serve` for local dev, and `npx supabase functions deploy hello-world` for production (after `npx supabase login` and `npx supabase link --project-ref PROJECT_ID`).
Reference: [Quickstart Guide](https://supabase.com/docs/guides/functions/quickstart)

View File

@@ -12,7 +12,10 @@ Use database triggers with `realtime.broadcast_changes()` instead of `postgres_c
Broadcasts database changes in a standard format.
```sql
create or replace function room_messages_broadcast()
-- Private schema for security definer functions
create schema if not exists private;
create or replace function private.room_messages_broadcast()
returns trigger
security definer
set search_path = ''
@@ -34,9 +37,11 @@ $$;
create trigger messages_broadcast_trigger
after insert or update or delete on messages
for each row execute function room_messages_broadcast();
for each row execute function private.room_messages_broadcast();
```
**Private channels require RLS on `realtime.messages`:** When clients subscribe with `{ config: { private: true } }`, you must create RLS policies on `realtime.messages` to control who can listen. See [setup-auth.md](setup-auth.md) for the required policies.
**Client subscription:**
```javascript

View File

@@ -39,7 +39,9 @@ Private channels require RLS policies on the `realtime.messages` table.
create policy "authenticated_users_can_receive"
on realtime.messages for select
to authenticated
using (true);
using (
realtime.messages.extension in ('broadcast', 'presence')
);
```
**Write access (send to channel):**
@@ -48,9 +50,13 @@ using (true);
create policy "authenticated_users_can_send"
on realtime.messages for insert
to authenticated
with check (true);
with check (
realtime.messages.extension in ('broadcast', 'presence')
);
```
Always filter on `extension in ('broadcast', 'presence')` to restrict which Realtime features are permitted.
**Topic-specific access:**
```sql
@@ -59,11 +65,11 @@ create policy "room_members_can_read"
on realtime.messages for select
to authenticated
using (
exists (
realtime.messages.extension in ('broadcast', 'presence')
and exists (
select 1 from room_members
where user_id = (select auth.uid())
and topic = (select realtime.topic())
and realtime.messages.extension in ('broadcast', 'presence')
and room_id::text = realtime.topic()
)
);
```

View File

@@ -38,7 +38,8 @@ values (
true,
5242880, -- 5MB
array['image/jpeg', 'image/png', 'image/webp']
);
)
on conflict (id) do nothing;
```
## Storage Helper Functions
@@ -60,11 +61,11 @@ create policy "User folder access"
on storage.objects for all to authenticated
using (
bucket_id = 'user-files' and
(storage.foldername(name))[1] = auth.uid()::text
(storage.foldername(name))[1] = (select auth.uid())::text
)
with check (
bucket_id = 'user-files' and
(storage.foldername(name))[1] = auth.uid()::text
(storage.foldername(name))[1] = (select auth.uid())::text
);
```