Getting started
Quick start guide for setting up sb-kit with default configuration.
Install dependencies
If you're adding sb-kit to an existing Next.js project:
npx shadcn@latest init
npm install @supabase/supabase-js @supabase/ssr @sb-kit/core @sb-kit/ui
pnpm dlx shadcn@latest init
pnpm add @supabase/supabase-js @supabase/ssr @sb-kit/core @sb-kit/ui
yarn dlx shadcn@latest init
yarn add @supabase/supabase-js @supabase/ssr @sb-kit/core @sb-kit/ui
bunx shadcn@latest init
bun add @supabase/supabase-js @supabase/ssr @sb-kit/core @sb-kit/ui
To create a new Next.js app with sb-kit:
npx create-next-app@latest myapp --tailwind --use-npm
cd myapp
npx shadcn@latest init
npm install @supabase/supabase-js @supabase/ssr @sb-kit/core @sb-kit/ui
npx create-next-app@latest myapp --tailwind --use-pnpm
cd myapp
pnpm dlx shadcn@latest init
pnpm add @supabase/supabase-js @supabase/ssr @sb-kit/core @sb-kit/ui
npx create-next-app@latest myapp --tailwind --use-yarn
cd myapp
yarn dlx shadcn@latest init
yarn add @supabase/supabase-js @supabase/ssr @sb-kit/core @sb-kit/ui
npx create-next-app@latest myapp --tailwind --use-bun
cd myapp
bunx shadcn@latest init
bun add @supabase/supabase-js @supabase/ssr @sb-kit/core @sb-kit/ui
Configure global styles
Tailwind CSS v4 requires this to be set in your global CSS file.
@import 'tailwindcss';
@import 'tw-animate-css';
@import '@sb-kit/ui/styles/default.css';
@source '../../node_modules/@sb-kit';
/* ... rest of the file */
Configure Supabase clients
Option 1: Default Setup
This setup is based on the official Supabase docs and works with any Next.js project.
SUPABASE_URL=<YOUR_SUPABASE_URL>
SUPABASE_ANON_KEY=<YOUR_SUPABASE_ANON_KEY>
import { cookies } from 'next/headers';
import { createServerClient } from '@supabase/ssr';
export async function serverClient() {
const cookieStore = await cookies();
return createServerClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_ANON_KEY!,
{
cookies: {
getAll: () => cookieStore.getAll(),
setAll: (cookiesToSet) => {
try {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options),
);
} catch {}
},
},
},
);
}
import { NextRequest, NextResponse } from 'next/server';
import { createServerClient } from '@supabase/ssr';
export async function middlewareClient(request: NextRequest) {
const supabaseResponse = NextResponse.next();
const supabase = createServerClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_ANON_KEY!,
{
cookies: {
getAll: () => request.cookies.getAll(),
setAll: (cookiesToSet) => {
cookiesToSet.forEach(({ name, value, options }) => {
supabaseResponse.cookies.set(name, value, options);
});
},
},
},
);
const {
data: { user },
error,
} = await supabase.auth.getUser();
return {
supabaseResponse,
user,
error,
};
}
Option 2: Existing Supabase Client
If you’re using your own Supabase client, just make sure your utility functions conform to the following shape:
import type { NextRequest, NextResponse } from 'next/server';
import type { AuthError, SupabaseClient, User } from '@supabase/supabase-js';
/**
* Server-side Supabase client
*/
async function serverClient(): Promise<SupabaseClient> {
// return your server client
}
/**
* Middleware Supabase client
*/
async function middlewareClient(request: NextRequest): Promise<{
supabaseResponse: NextResponse;
user: User | null;
error: AuthError | null;
}> {
// return your middleware client
}
Initialize sb-kit client
Initialize sb-kit with Supabase clients.
import { sbKitClient } from '@sb-kit/core';
import { middlewareClient } from './client/middleware';
import { serverClient } from './client/server';
export const sbKit = sbKitClient({
supabaseClients: {
server: serverClient,
middleware: middlewareClient,
},
});
Add server-side helpers
Use sbKit.callbackHandler for OAuth callbacks and routeGuard in middleware to protect routes based on authentication state.
import { sbKit } from '@/lib/supabase/sb-kit';
const callbackHandler = sbKit.callbackHandler;
export { callbackHandler as GET };
import { type NextRequest, NextResponse } from 'next/server';
import { sbKit } from './lib/supabase/sb-kit';
export async function middleware(request: NextRequest) {
const routeGuardResponse = await sbKit.routeGuard(request);
if (routeGuardResponse) return routeGuardResponse;
return NextResponse.next();
}
export const config = {
matcher: [
'/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
],
};
Add auth layout and pages
Use sbKit.components to set up the auth layout and pages.
- AuthWrapper provides the base auth UI along with the SonnerToaster provider.
- The page components handle the auth flow using server actions.
import { sbKit } from '@/lib/supabase/sb-kit';
type Props = {
children: React.ReactNode;
};
const AuthWrapper = sbKit.components.AuthWrapper;
const Layout = ({ children }: Props) => {
return <AuthWrapper>{children}</AuthWrapper>;
};
export default Layout;
import type { SearchParams } from 'next/dist/server/request/search-params';
import { sbKit } from '@/lib/supabase/sb-kit';
type Props = {
searchParams: Promise<SearchParams>;
};
const SignIn = sbKit.components.SignIn;
const Page = ({ searchParams }: Props) => {
return <SignIn searchParams={searchParams} />;
};
export default Page;
import { sbKit } from '@/lib/supabase/sb-kit';
const SignUp = sbKit.components.SignUp;
const Page = () => {
return <SignUp />;
};
export default Page;
import { sbKit } from '@/lib/supabase/sb-kit';
const ForgotPasssword = sbKit.components.ForgotPassword;
const Page = () => {
return <ForgotPasssword />;
};
export default Page;
import { sbKit } from '@/lib/supabase/sb-kit';
const SetPassword = sbKit.components.SetPassword;
const Page = () => {
return <SetPassword />;
};
export default Page;
Done.