supabase-js

$npx mdskill add fcakyon/claude-codex-settings/supabase-js

Query Supabase database for rows

  • Identify the table and columns to query.
  • Use `supabase.from('table').select('*')` to fetch all data.
  • Apply filters using `.eq()`, `.gt()`, or `.lt()` as needed.
  • Return the queried data directly without further processing.

SKILL.md

.github/skills/supabase-jsView on GitHub ↗
---
name: supabase-js
description: This skill should be used when user asks to "use supabase-js", "query Supabase database", "supabase auth", "supabase storage", "supabase realtime", "supabase edge functions", or works with the @supabase/supabase-js JavaScript/TypeScript SDK.
references:
  - supabase-js
  - auth-js
  - postgrest-js
  - storage-js
license: MIT
---

# Supabase JavaScript SDK Skill

Skill for building applications with the `@supabase/supabase-js` SDK. Covers Auth, Database (PostgREST), Storage, Realtime, and Edge Functions.

The SDK docs at https://supabase.com/docs/reference/javascript are the source of truth. The reference files alongside this skill contain source code and READMEs extracted from the monorepo for quick lookup.

## Setup

```bash
npm install @supabase/supabase-js
```

```typescript
import { createClient } from '@supabase/supabase-js'

const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key')
```

For type-safe queries, generate types from your database schema:

```bash
supabase gen types typescript --project-id your-project-id > database.types.ts
```

```typescript
import { createClient } from '@supabase/supabase-js'
import type { Database } from './database.types'

const supabase = createClient<Database>(SUPABASE_URL, SUPABASE_ANON_KEY)
```

## Quick Decision Trees

### "I need to query data"

```
Database query?
├─ Select rows → supabase.from('table').select('*')
├─ Filter rows → .select().eq('col', val) / .gt() / .lt() / .in() / .like()
├─ Join tables → .select('*, other_table(*)') or .select('*, other_table!fk(*)')
├─ Insert → supabase.from('table').insert({ col: val })
├─ Upsert → supabase.from('table').upsert({ id: 1, col: val })
├─ Update → supabase.from('table').update({ col: val }).eq('id', 1)
├─ Delete → supabase.from('table').delete().eq('id', 1)
├─ Call RPC function → supabase.rpc('function_name', { arg: val })
├─ Count rows → .select('*', { count: 'exact', head: true })
├─ Pagination → .range(0, 9) or .limit(10).offset(20)
└─ Order → .order('created_at', { ascending: false })
```

### "I need authentication"

```
Auth?
├─ Email/password sign up → supabase.auth.signUp({ email, password })
├─ Email/password sign in → supabase.auth.signInWithPassword({ email, password })
├─ OAuth (Google, GitHub, etc.) → supabase.auth.signInWithOAuth({ provider: 'google' })
├─ Magic link → supabase.auth.signInWithOtp({ email })
├─ Phone OTP → supabase.auth.signInWithOtp({ phone })
├─ Sign out → supabase.auth.signOut()
├─ Get current user → supabase.auth.getUser()
├─ Get session → supabase.auth.getSession()
├─ Listen to auth changes → supabase.auth.onAuthStateChange((event, session) => {})
├─ Reset password → supabase.auth.resetPasswordForEmail(email)
├─ Update user → supabase.auth.updateUser({ data: { name: 'New' } })
└─ Admin operations → supabase.auth.admin.listUsers() / .deleteUser(id)
```

### "I need file storage"

```
Storage?
├─ Upload file → supabase.storage.from('bucket').upload('path/file.png', file)
├─ Download file → supabase.storage.from('bucket').download('path/file.png')
├─ Get public URL → supabase.storage.from('bucket').getPublicUrl('path/file.png')
├─ Create signed URL → supabase.storage.from('bucket').createSignedUrl('path', 3600)
├─ List files → supabase.storage.from('bucket').list('folder')
├─ Move file → supabase.storage.from('bucket').move('old/path', 'new/path')
├─ Remove file → supabase.storage.from('bucket').remove(['path/file.png'])
├─ Create bucket → supabase.storage.createBucket('name', { public: false })
└─ List buckets → supabase.storage.listBuckets()
```

### "I need realtime"

```
Realtime?
├─ Listen to DB changes → supabase.channel('name')
│    .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'messages' }, handler)
│    .subscribe()
├─ Broadcast messages → channel.send({ type: 'broadcast', event: 'cursor', payload: { x, y } })
├─ Listen to broadcasts → .on('broadcast', { event: 'cursor' }, handler)
├─ Presence (who's online) → channel.track({ user_id, online_at })
│    .on('presence', { event: 'sync' }, () => channel.presenceState())
├─ Unsubscribe → supabase.removeChannel(channel)
└─ Unsubscribe all → supabase.removeAllChannels()
```

### "I need edge functions"

```
Edge Functions?
├─ Invoke function → supabase.functions.invoke('function-name', { body: { key: 'val' } })
├─ With custom headers → .invoke('fn', { headers: { 'x-custom': 'val' }, body })
└─ Set region → .invoke('fn', { body, region: 'us-east-1' })
```

## Common Patterns

### Server-side with service role key

```typescript
// Server-side only - bypasses RLS
const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, {
  auth: { persistSession: false }
})
```

### React/Next.js auth

```typescript
import { createClient } from '@supabase/supabase-js'
import { useEffect, useState } from 'react'

const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY)

function useUser() {
  const [user, setUser] = useState(null)
  useEffect(() => {
    supabase.auth.getUser().then(({ data }) => setUser(data.user))
    const { data: { subscription } } = supabase.auth.onAuthStateChange(
      (_, session) => setUser(session?.user ?? null)
    )
    return () => subscription.unsubscribe()
  }, [])
  return user
}
```

### Typed database queries

```typescript
// Generated types give autocomplete for table names, column names, and return types
const { data, error } = await supabase
  .from('profiles')        // autocompleted table name
  .select('id, username')  // autocompleted columns
  .eq('id', userId)        // type-safe filter
  .single()                // returns single row or error
// data is typed as { id: string; username: string } | null
```

## Package Index

| Package | Sub-client | Reference |
|---------|-----------|-----------|
| `@supabase/supabase-js` | `createClient()` | `references/supabase-js/` |
| `@supabase/auth-js` | `.auth` | `references/auth-js/` |
| `@supabase/postgrest-js` | `.from()`, `.rpc()` | `references/postgrest-js/` |
| `@supabase/realtime-js` | `.channel()`, `.realtime` | `references/realtime-js/` |
| `@supabase/storage-js` | `.storage` | `references/storage-js/` |
| `@supabase/functions-js` | `.functions` | `references/functions-js/` |

More from fcakyon/claude-codex-settings

SkillDescription
adhd-output-styleThis skill should be used when the user asks for "ADHD output", "fewer output tokens", "short numbered steps", "limited working memory formatting", or explicitly invokes "adhd-output-style".
anthropic-frontend-designGuidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.
azure-usageThis skill should be used when user asks to "query Azure resources", "list storage accounts", "manage Key Vault secrets", "work with Cosmos DB", "check AKS clusters", "use Azure MCP", or interact with any Azure service.
clean-gone-branchesThis skill should be used when user asks to "clean gone branches", "remove deleted local branches", "prune branches removed from remote", or explicitly invokes "clean-gone-branches".
commit-stagedThis skill should be used when user asks to "commit these changes", "write commit message", "stage and commit", "create a commit", "commit staged files", or explicitly invokes "commit-staged".
docUse when the task involves reading, creating, or editing `.docx` documents, especially when formatting or layout fidelity matters; prefer `python-docx` plus the bundled `scripts/render_docx.py` for visual checks.
dokploy-deployThis skill should be used when user asks to "deploy with Dokploy", "use Dokploy Cloud", "manage self-hosted Dokploy", "deploy Docker Compose on Dokploy", "manage Dokploy databases", "configure Dokploy domains", or "look up Dokploy CLI commands".
electronAutomate Electron desktop apps (VS Code, Slack, Discord, Figma, Notion, Spotify, etc.) using agent-browser via Chrome DevTools Protocol. Use when the user needs to interact with an Electron app, automate a desktop app, connect to a running app, control a native app, or test an Electron application. Triggers include "automate Slack app", "control VS Code", "interact with Discord app", "test this Electron app", "connect to desktop app", or any task requiring automation of a native Electron application.
fable-advisorThis skill should be used when the user asks for a "Fable second opinion", wants to "check a plan before committing", needs another view after repeated failures, or explicitly invokes "fable-advisor".
gcloud-usageThis skill should be used when user asks about "GCloud logs", "Cloud Logging queries", "Google Cloud metrics", "GCP observability", "trace analysis", or "debugging production issues on GCP".