supabase-knowledge-patch

Installation
SKILL.md

Supabase Knowledge Patch

Claude's baseline knowledge covers Supabase through mid-2025. This skill provides features and breaking changes from late 2025 onwards.

Index

Quick Reference: New API Key Model

Type Format Replaces Notes
Publishable sb_publishable_... anon JWT Safe for client-side
Secret sb_secret_... service_role JWT Browser-blocked (401)

Both old and new keys work simultaneously. Not JWTs — gateway mints short-lived JWT internally. Platform-only (not CLI/self-hosted).

// Client-side
const supabase = createClient(SUPABASE_URL, 'sb_publishable_...')
// Server-side
const supabase = createClient(SUPABASE_URL, 'sb_secret_...', {
  auth: { persistSession: false },
})

Quick Reference: Auth

Feature API
OAuth 2.1 server supabase.auth.oauth.approveAuthorization(id)
Custom OAuth/OIDC supabase.auth.admin.customProviders.createProvider({...})
Web3 (Ethereum/Solana) supabase.auth.signInWithWeb3({ chain: 'ethereum' })
JWT claims in Edge Fn supabase.auth.getClaims(token)
Throw on error createClient(url, key, { auth: { throwOnError: true } })
Skip auto-init (SSR) createClient(url, key, { auth: { skipAutoInitialize: true } })
Before user hook SQL function returning { "error": {...} } to reject signup

OAuth tokens include client_id claim — use in RLS to restrict OAuth client access:

CREATE POLICY "No OAuth access" ON sensitive_table FOR ALL USING (
  auth.uid () = user_id
  AND (auth.jwt () ->> 'client_id') IS NULL
);

Quick Reference: Edge Functions

Feature Usage
Background tasks EdgeRuntime.waitUntil(promise)
S3 mount read/write Deno.readFile('/s3/BUCKET/path')
Ephemeral /tmp 256MB free, 512MB paid; sync APIs only at top level
Wall clock 150s free / 400s paid
CPU per request 2s
Bundle size 20MB
Functions/project 100 free / 500 pro / 1000 team

Quick Reference: Realtime

Private channels require RLS on realtime.messages + private: true:

await supabase.realtime.setAuth()
const channel = supabase.channel('room:123', { config: { private: true } })

Server-side broadcast: SELECT realtime.send(payload, event, topic, private).

Broadcast replay (alpha, private channels only):

const channel = supabase.channel('room:main', {
  config: { private: true, broadcast: { replay: { since: timestamp, limit: 10 } } },
})

Quick Reference: Vector Buckets (Alpha)

const bucket = supabase.storage.vectors.from('embeddings');
await bucket.createIndex({
  indexName: 'docs',
  dataType: 'float32',
  dimension: 1536,
  distanceMetric: 'cosine',
});

const index = bucket.index('docs');
await index.putVectors({
  vectors: [
    { key: 'doc-1', data: { float32: embedding }, metadata: { title: 'Doc' } },
  ],
});
const { data } = await index.queryVectors({
  queryVector: { float32: query },
  topK: 10,
  filter: { category: 'guide' },
});

SQL access via FDW: WHERE data <==> '[...]'::embd ORDER BY embd_distance(data). Limits: 10 buckets, 10 indexes/bucket, 4096 dims.

Quick Reference: Declarative Schemas

Place desired-state SQL in supabase/schemas/, then diff to generate migrations:

supabase db diff -f create_employees_table
[db.migrations]
schema_paths = ["./schemas/employees.sql", "./schemas/*.sql"]

Quick Reference: Secret Management

# env() — reference env vars in any config field
[auth.external.github]
client_id = "env(GITHUB_CLIENT_ID)"
secret = "env(GITHUB_SECRET)"
supabase secrets set --env-file ./supabase/.env

Quick Reference: Queues (pgmq_public)

// Send
await supabase.schema('pgmq_public').rpc('send', {
  queue_name: 'my_queue',
  message: { hello: 'world' },
  sleep_seconds: 0,
});
// Read (with visibility timeout)
await supabase.schema('pgmq_public').rpc('read', {
  queue_name: 'my_queue',
  sleep_seconds: 30,
  n: 5,
});
// Pop (read + delete)
await supabase.schema('pgmq_public').rpc('pop', { queue_name: 'my_queue' });

Requires: enable pgmq extension, toggle "Expose Queues via PostgREST", enable RLS on pgmq.q_<name>.

Quick Reference: JS Client (v2.74–v2.101)

Change Version Details
Node.js 20+ required v2.79.0+ @supabase/node-fetch removed; pin v2.78.0 for Node 18
notin() filter .notin('id', [1,2,3])
isdistinct() filter .isdistinct('deleted_at', null) — NULL-safe
overrideTypes<>() v2.48.0+ Override query result types
Auth throw mode v2.79.0+ { auth: { throwOnError: true } }
detectSessionInUrl fn v2.88.0+ Accepts predicate function
Functions timeout v2.81.0+ signal: AbortSignal.timeout(30000)
CORS headers v2.95.0+ import { corsHeaders } from '@supabase/supabase-js/cors'
DatabaseWithoutInternals v2.89.0+ Strips internal schemas from Database type

Quick Reference: MCP Server

Remote: https://mcp.supabase.com/mcp (HTTP transport, OAuth 2.1 auth). Local CLI: http://localhost:54321/mcp (no OAuth).

Config via URL params: ?project_ref=...&read_only=true&features=database,docs

Feature groups: account, docs, database, debugging, development, functions, storage, branching. All enabled by default except storage.

Quick Reference: Sub-Minute Cron

SELECT cron.schedule('fast-poll', '30 seconds', 'SELECT process_pending()');

Valid: 1–59 seconds. Requires Postgres 15.1.1.61+.

Breaking Changes (2025–2026)

  • OpenAPI spec via anon key removed (Mar 2026) — use service_role or sb_secret_ key
  • pg_graphql disabled by default on new projects — CREATE EXTENSION pg_graphql to re-enable
  • PostgREST v14 JWT cache — enabled by default (~20% more RPS); disable: ALTER ROLE authenticator SET pgrst.jwt_cache_max_entries TO 0
  • Edge Functions recursive call rate limit (Mar 2026) — 5,000 req/min budget for function-to-function calls within a project
Related skills
Installs
3
GitHub Stars
19
First Seen
Apr 7, 2026