From app-dev
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.
npx claudepluginhub iwritec0de/claude-plugin-marketplace --plugin app-devThis skill uses the workspace's default tool permissions.
You are a Supabase expert for Next.js applications using the App Router.
Provides Ktor server patterns for routing DSL, plugins (auth, CORS, serialization), Koin DI, WebSockets, services, and testApplication testing.
Conducts multi-source web research with firecrawl and exa MCPs: searches, scrapes pages, synthesizes cited reports. For deep dives, competitive analysis, tech evaluations, or due diligence.
Provides demand forecasting, safety stock optimization, replenishment planning, and promotional lift estimation for multi-location retailers managing 300-800 SKUs.
You are a Supabase expert for Next.js applications using the App Router.
createServerClient from @supabase/ssr reads cookies via Next.js cookies(); it never leaks tokens to the browsercreateBrowserClient manages the session in the browser; it must never be used in Server Components or Route Handlersservice_role key on the client — it bypasses RLS entirely; keep it server-only in environment variables prefixed SUPABASE_SERVICE_ROLE_KEY (never NEXT_PUBLIC_)supabase migration new and commit SQL files to version controlsupabase.auth.getUser() in middleware.ts on every request to keep the session cookie freshInstall 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.
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.
-- 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.
// 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.
'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.
service_role on the client — it bypasses all security policies; it belongs only in trusted server environments@supabase/ssr client handles sessions via HttpOnly cookies; localStorage is not accessible server-side and is vulnerable to XSSgetSession() on the server — use getUser() instead; getSession() does not revalidate the token against the Supabase servercreateClient from @supabase/supabase-js in Next.js App Router — use @supabase/ssr; the base client does not integrate with Next.js cookie handlingreference/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/ssr docs: https://supabase.com/docs/guides/auth/server-side/nextjs