Supabase
Full-stack Next.js development plugin for Claude Code
npx -y skills add iwritec0de/app-dev --skill supabaseAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
This skill should be used when the user asks to "integrate Supabase", "set up Supabase auth", "write RLS policies", "use Supabase storage", "subscribe to realtime changes", or mentions "supabase", "supabase auth", "RLS", "row level security", "supabase client", "supabase storage", "realtime", "edge function", "supabase migration". Provides Supabase best practices for Next.js applications including auth, database, storage, realtime, and edge functions.
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.9 KB, as published. Nobody here has run it
Supabase Skill
You are a Supabase expert for Next.js applications using the App Router.
Critical Rules
- Always enable RLS on every table — a table without Row Level Security is open to any authenticated user by default
- Use the server-side client for Server Components —
createServerClientfrom@supabase/ssrreads cookies via Next.jscookies(); it never leaks tokens to the browser - Use the browser client for Client Components —
createBrowserClientmanages the session in the browser; it must never be used in Server Components or Route Handlers - Never expose the
service_rolekey on the client — it bypasses RLS entirely; keep it server-only in environment variables prefixedSUPABASE_SERVICE_ROLE_KEY(neverNEXT_PUBLIC_) - Use database migrations for schema changes — never edit schema through the Supabase dashboard in production; use
supabase migration newand commit SQL files to version control - Always use parameterized queries — the Supabase client does this automatically; never interpolate user input into raw SQL strings
- Refresh sessions in middleware — call
supabase.auth.getUser()inmiddleware.tson every request to keep the session cookie fresh
Client Setup
Install the required packages:
npm install @supabase/supabase-js @supabase/ssr
Server Component / Route Handler client — reads and writes cookies via Next.js cookies():
// lib/supabase/server.ts
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'
import type { Database } from '@/types/supabase'
export async function createClient() {
const cookieStore = await cookies()
return createServerClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() { return cookieStore.getAll() },
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options)
)
} catch {} // Safe to ignore in Server Components; middleware handles refresh
},
},
}
)
}
Client Component client — manages the session in the browser:
// lib/supabase/client.ts
import { createBrowserClient } from '@supabase/ssr'
import type { Database } from '@/types/supabase'
export function createClient() {
return createBrowserClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
}
Read reference/auth-patterns.md for the full middleware setup, sign-in/sign-up flows, OAuth, and protected route patterns.
Database
Always import your generated types for full type safety:
import type { Database } from '@/types/supabase'
// Generate: npx supabase gen types typescript --local > types/supabase.ts
Common query patterns:
const supabase = await createClient()
// Select with filter
const { data, error } = await supabase
.from('posts')
.select('id, title, created_at')
.eq('user_id', userId)
.order('created_at', { ascending: false })
// Insert
const { data, error } = await supabase
.from('posts')
.insert({ title, body, user_id: userId })
.select()
.single()
// Upsert
const { error } = await supabase
.from('profiles')
.upsert({ id: userId, display_name: name })
Read reference/database-patterns.md for RLS policy patterns, migrations, RPC functions, joins, and views.
RLS Policies — Quick Reference
-- Authenticated users can read all rows
CREATE POLICY "authenticated read" ON posts
FOR SELECT TO authenticated USING (true);
-- Users can only modify their own rows
CREATE POLICY "owner write" ON posts
FOR ALL TO authenticated USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
-- Role-based access using JWT claims
CREATE POLICY "admin only" ON admin_logs
FOR SELECT TO authenticated
USING (auth.jwt() ->> 'role' = 'admin');
Read reference/database-patterns.md for full RLS patterns including multi-tenancy, team-based access, and helper functions.
Storage
// Upload a file
const { data, error } = await supabase.storage
.from('avatars')
.upload(`${userId}/avatar.png`, file, { upsert: true })
// Get a public URL (public bucket)
const { data: { publicUrl } } = supabase.storage
.from('avatars')
.getPublicUrl(`${userId}/avatar.png`)
// Get a signed URL (private bucket, expires in 60 seconds)
const { data, error } = await supabase.storage
.from('documents')
.createSignedUrl(`${userId}/file.pdf`, 60)
Read reference/realtime-storage.md for image transformations, resumable uploads, and storage RLS.
Realtime
'use client'
// Subscribe to table changes
const channel = supabase
.channel('posts-changes')
.on('postgres_changes',
{ event: 'INSERT', schema: 'public', table: 'posts' },
(payload) => setItems(prev => [payload.new as Post, ...prev])
)
.subscribe()
return () => { supabase.removeChannel(channel) }
Read reference/realtime-storage.md for presence, broadcast, and channel cleanup patterns.
Anti-Patterns
- Do not disable RLS — even temporarily; attackers do not wait for you to re-enable it
- Do not use
service_roleon the client — it bypasses all security policies; it belongs only in trusted server environments - Do not skip migrations — dashboard edits to schema are not tracked in version control and will diverge between environments
- Do not store auth state in localStorage — the
@supabase/ssrclient handles sessions via HttpOnly cookies; localStorage is not accessible server-side and is vulnerable to XSS - Do not call
getSession()on the server — usegetUser()instead;getSession()does not revalidate the token against the Supabase server - Do not use
createClientfrom@supabase/supabase-jsin Next.js App Router — use@supabase/ssr; the base client does not integrate with Next.js cookie handling
Related
reference/auth-patterns.md— Sign up, sign in, OAuth, magic link, middleware, protected routes, RBACreference/database-patterns.md— Schema design, RLS policies, migrations, RPC functions, joins, viewsreference/realtime-storage.md— Realtime subscriptions, presence, broadcast, storage upload/download, signed URLs- Supabase docs: https://supabase.com/docs
@supabase/ssrdocs: https://supabase.com/docs/guides/auth/server-side/nextjs