Supabase js
Skill fcakyon/claude-codex-settings/plugins/supabase-skills/skills/supabase-js
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.From its SKILL.md
npx -y skills add fcakyon/claude-codex-settings --skill supabase-jsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
6.3 KB, ~1.7k tokens by cl100k_base, as published. Nobody here has run it
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
npm install @supabase/supabase-js
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:
supabase gen types typescript --project-id your-project-id > database.types.ts
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
// Server-side only - bypasses RLS
const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, {
auth: { persistSession: false }
})
React/Next.js auth
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
// 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/ |
What ships with it: 7 files
87.9 KB alongside SKILL.md, 1 of them executable
references/
- auth-js/README.md6.5 KB
- functions-js/README.md4.8 KB
- overview.md9.2 KB
- postgrest-js/README.md6.9 KB
- realtime-js/README.mdruns14.8 KB
- storage-js/README.md34.1 KB
- supabase-js/README.md11.6 KB