
supabase-nextjs-integration
by AgentiveCity
A skill factory for managing Claude Code skills
SKILL.md
name: "supabase-nextjs-integration" description: "Use this skill whenever the user wants to set up, refactor, or optimize Supabase usage in a Next.js (App Router) + TypeScript project, including auth, database, storage, RLS-safe patterns, edge functions, and secure client/server integration."
Supabase + Next.js App Router Integration Skill
Purpose
You are a specialized assistant for integrating Supabase with Next.js App Router in a secure, idiomatic, and scalable way.
Use this skill to:
- Set up Supabase in a Next.js App Router + TypeScript project
- Configure environment variables & secrets safely
- Create Supabase clients for:
- Server Components
- Route Handlers
- Server Actions
- Client Components (ONLY with anon keys)
- Implement Auth flows (email/password, OAuth, magic links, password reset)
- Use Row Level Security (RLS) safely and correctly
- Integrate database, storage, and edge functions
- Choose between Edge runtime and Node runtime for Supabase usage
- Structure the project so all Supabase usage is consistent and easily testable
Do not use this skill for non-Next.js projects or when Supabase is not part of the stack.
If CLAUDE.md exists, follow its conventions for env vars, directory structure, and security rules
(e.g. “never use service_role in app”, “always go through specific route handlers”).
When To Apply This Skill
Trigger this skill when the user asks for any of the following (or similar):
- “Set up Supabase in this Next.js app.”
- “Use Supabase auth (login, signup, magic links) in my Next.js frontend.”
- “Wire RLS-protected tables to my Next.js pages/components.”
- “Securely call Supabase from server actions / route handlers.”
- “Use Edge Functions from my Next.js app.”
- “Fix Supabase auth/session handling in App Router.”
- “Use Supabase for database + storage + auth in my Next app.”
Avoid applying this skill when:
- The question is purely about UI & components with no data/auth.
- The project does not use or plan to use Supabase.
High-Level Architecture
When integrating Supabase with Next.js App Router, follow this architecture:
-
Environment variables
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEYSUPABASE_SERVICE_ROLE_KEY(server-only, NEVER sent to client)- Any other Supabase-related secrets (e.g. JWT secret, webhook secrets)
-
Supabase client modules (example paths):
src/lib/supabase/client.ts→ browser/client-side usage (anon key)src/lib/supabase/server.ts→ server-side usage with cookies & auth helperssrc/lib/supabase/admin.ts→ server-only admin usage (service_role, if really needed)
-
Auth integration
- Use Supabase auth for sessions and user identity.
- Implement auth-aware Server Components, layouts, and middleware as needed.
- Never expose
service_roleto the browser; use row-level security (RLS) to protect data.
-
Edge vs Node runtime
- Use Edge runtime (
runtime = "edge") when you want low-latency Supabase access and your libraries are Edge-compatible. - Use Node runtime (
runtime = "nodejs") for heavier operations or incompatible libs.
- Use Edge runtime (
-
Edge Functions
- Implement Supabase Edge Functions for server-side logic that should run close to the data
and call them from your Next.js app via
fetch.
- Implement Supabase Edge Functions for server-side logic that should run close to the data
and call them from your Next.js app via
Environment & Secrets
Always configure Supabase secrets like this:
# .env.local (never committed)
NEXT_PUBLIC_SUPABASE_URL="https://YOUR_PROJECT_ID.supabase.co"
NEXT_PUBLIC_SUPABASE_ANON_KEY="public-anon-key"
SUPABASE_SERVICE_ROLE_KEY="service-role-key" # SERVER ONLY – never exposed client-side
Guidelines:
NEXT_PUBLIC_*env vars are visible to the browser; only use public/anon keys there.SUPABASE_SERVICE_ROLE_KEYmust never be used in code that can run on the client.- When in doubt, use server components and route handlers to keep secrets safe.
Supabase Client Setup
1. Client-side Supabase (browser / anon-only)
Use this for strictly client-side features that need Supabase and are safe with anon keys (e.g. some public reads, optional real-time features).
// src/lib/supabase/client.ts
import { createBrowserClient } from "@supabase/ssr";
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
}
Usage in client components:
"use client";
import { useEffect, useState } from "react";
import { createClient } from "@/lib/supabase/client";
export function ProfileWidget() {
const [profile, setProfile] = useState<any>(null);
useEffect(() => {
const supabase = createClient();
supabase
.from("profiles")
.select("*")
.limit(1)
.then(({ data }) => setProfile(data?.[0] ?? null));
}, []);
// render...
}
Use this skill to warn when something should really be fetched server-side instead.
2. Server-side Supabase (App Router aware)
Use this in Server Components, Route Handlers, and Server Actions when you need session-aware Supabase access.
// src/lib/supabase/server.ts
import { cookies } from "next/headers";
import { createServerClient } from "@supabase/ssr";
export function createServerSupabaseClient() {
const cookieStore = cookies();
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
get(name: string) {
return cookieStore.get(name)?.value;
},
},
}
);
}
Usage in a server component:
// app/dashboard/page.tsx
import { createServerSupabaseClient } from "@/lib/supabase/server";
export default async function DashboardPage() {
const supabase = createServerSupabaseClient();
const {
data: { user },
} = await supabase.auth.getUser();
if (!user) {
// handle redirect to login, etc.
}
const { data: items } = await supabase.from("items").select("*").order("created_at", { ascending: false });
return <DashboardView user={user} items={items ?? []} />;
}
3. Admin / Service-role Supabase (server-only)
Use sparingly, only for back-office or system tasks that require bypassing RLS.
// src/lib/supabase/admin.ts
import { createClient } from "@supabase/supabase-js";
export const adminSupabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!,
{
auth: { persistSession: false },
}
);
Never import adminSupabase in client components.
Auth Flows (Next.js + Supabase)
Sign Up / Sign In (Server Actions)
Use server actions or route handlers to handle auth operations:
// app/(auth)/actions.ts
"use server";
import { redirect } from "next/navigation";
import { createServerSupabaseClient } from "@/lib/supabase/server";
export async function signInWithEmail(formData: FormData) {
const email = String(formData.get("email") ?? "");
const password = String(formData.get("password") ?? "");
const supabase = createServerSupabaseClient();
const { error } = await supabase.auth.signInWithPassword({ email, password });
if (error) {
// handle error (return structured error)
return { error: error.message };
}
redirect("/dashboard");
}
Use this skill to:
- Keep auth flows entirely server-side where possible.
- Avoid exposing unnecessary auth logic to the client.
- Ensure proper redirects and error handling.
Magic Links / OAuth
- Use Supabase auth methods for magic links and OAuth providers.
- Handle redirect URLs and
nextparameters carefully, avoiding open redirects.
RLS (Row Level Security) Best Practices
-
Enable RLS on all tables that store user data.
-
Define policies based on Supabase's
auth.uid():Example policy pattern:
create policy "Users can see their own rows" on profiles for select using ( auth.uid() = user_id );
Use this skill to:
- Encourage RLS for all user-related tables.
- Avoid relying on
service_rolefor regular app operations. - Ensure queries are written with RLS in mind (e.g. filter by
user_idinstead of trusting client input).
Edge Functions
Supabase Edge Functions are great for:
- High-performance APIs close to your database
- Work that should remain within Supabase infrastructure
Use this skill to:
-
Suggest separation of complex logic into Edge Functions.
-
Show patterns for calling Edge Functions from Next.js via
fetch:const res = await fetch("https://YOUR_PROJECT_ID.supabase.co/functions/v1/my-fn", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${accessToken}`, // if needed }, body: JSON.stringify(payload), }); -
Keep security & auth in mind when calling these functions.
Step-by-Step Workflow
When this skill is active, follow this workflow:
1. Detect current state
-
Check if Supabase is already set up:
- Are env vars present?
- Are
@supabase/*dependencies installed? - Are there any existing Supabase client helper files?
-
If not present → propose a clean setup with minimal, well-structured helpers.
2. Define goals
- Ask (or infer) what the user wants:
- Auth? Database? Storage? Edge Functions?
- RLS on which tables?
- Public vs authenticated routes?
3. Set up or refactor client modules
- Create or refine:
lib/supabase/client.tslib/supabase/server.tslib/supabase/admin.ts(if needed)
- Ensure no server-only keys are referenced in browser code.
4. Implement auth flows
- For login, signup, logout, password reset, etc.:
- Use server actions or route handlers.
- Maintain a clean separation between UI and auth logic.
- Ensure redirects work correctly in App Router.
5. Wire Supabase into routes/layouts
- Use server components for auth-aware pages and layouts.
- Use RLS-friendly queries (no trusting user IDs from the client).
- Use Suspense/loading states where relevant.
6. Integrate storage & other features
- Provide helpers for uploading/downloading from Supabase storage.
- Ensure signed URL usage when appropriate.
7. Use Edge Functions when appropriate
- Offload complex or latency-sensitive logic.
- Ensure correct authentication from Next.js to Edge Functions.
8. Summarize and document
-
After setting up or refactoring Supabase integration, summarize:
- Where Supabase helpers live.
- How auth flows work.
- How RLS and security are enforced.
- How to add new tables/queries safely.
-
Optionally update
README.mdor createSUPABASE.mddocumenting all of the above.
Examples of Prompts That Should Use This Skill
- “Set up Supabase auth and secure dashboard routes in this Next.js app.”
- “Use Supabase with RLS to store user-specific todos and show them in
/dashboard.” - “Add a profile page reading from the
profilestable with proper auth.” - “Move this client-side Supabase usage into server components and server actions.”
- “Integrate Supabase Edge Functions for heavy data processing and call them from Next.js.”
- “Refactor our Supabase usage to avoid leaking the service_role key and rely on RLS instead.”
For these tasks, rely on this skill to provide secure, idiomatic Supabase + Next.js App Router integration, and collaborate with other skills (data fetching, performance, testing, routing) as needed.
スコア
総合スコア
リポジトリの品質指標に基づく評価
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
レビュー
レビュー機能は近日公開予定です