Going to Production
Everything between the 5-minute quickstart and a production-ready SaaS app.
The quickstart gets you a working demo. Here is what to configure before real users sign in.
1. Environment variables
Create a .env.local file in your project root. Never commit this file.
# BuildBase
NEXT_PUBLIC_BUILDBASE_SERVER_URL=https://api.console.buildbase.app
NEXT_PUBLIC_BUILDBASE_ORG_ID=your-org-id
NEXT_PUBLIC_BUILDBASE_CLIENT_ID=your-client-id
NEXT_PUBLIC_BUILDBASE_REDIRECT_URL=http://localhost:3000/callback
# Server-only — never expose with a NEXT_PUBLIC_ prefix
BUILDBASE_CLIENT_SECRET=your-client-secret
# Session secret (used to sign httpOnly cookies)
SESSION_SECRET=run-openssl-rand-hex-32Update your provider to read from env:
<SaaSOSProvider
serverUrl={process.env.NEXT_PUBLIC_BUILDBASE_SERVER_URL!}
version={ApiVersion.V1}
orgId={process.env.NEXT_PUBLIC_BUILDBASE_ORG_ID!}
auth={{
clientId: process.env.NEXT_PUBLIC_BUILDBASE_CLIENT_ID!,
redirectUrl: process.env.NEXT_PUBLIC_BUILDBASE_REDIRECT_URL!,
callbacks: { /* ... */ },
}}
>2. Auth callback API route
The quickstart shows fetch('/api/auth/verify') — here's the actual implementation. This route calls BuildBase's token endpoint (POST /api/v1/auth/token) to exchange the auth code for a session, then sets an httpOnly cookie. The exchange requires your clientSecret, which is why it runs on your backend — the secret must never reach the browser.
// app/api/auth/verify/route.ts
import { cookies } from 'next/headers';
export async function POST(req: Request) {
const { code } = await req.json();
// Exchange the auth code for a session
const res = await fetch(
`${process.env.NEXT_PUBLIC_BUILDBASE_SERVER_URL}/api/v1/auth/token`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
code,
orgId: process.env.NEXT_PUBLIC_BUILDBASE_ORG_ID,
clientId: process.env.NEXT_PUBLIC_BUILDBASE_CLIENT_ID,
clientSecret: process.env.BUILDBASE_CLIENT_SECRET,
}),
}
);
if (!res.ok) {
return Response.json({ error: 'Invalid or expired code' }, { status: 401 });
}
const { data } = await res.json(); // { sessionId, user }
// Set httpOnly cookie (secure in production)
const cookieStore = await cookies();
cookieStore.set('bb-session', data.sessionId, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
path: '/',
maxAge: 60 * 60 * 24 * 30, // 30 days
});
return Response.json({ sessionId: data.sessionId });
}// app/api/auth/session/route.ts
import { cookies } from 'next/headers';
export async function GET() {
const cookieStore = await cookies();
const sessionId = cookieStore.get('bb-session')?.value ?? null;
return Response.json({ sessionId });
}// app/api/auth/signout/route.ts
import { cookies } from 'next/headers';
export async function POST() {
const cookieStore = await cookies();
cookieStore.delete('bb-session');
return Response.json({ ok: true });
}3. Project structure
A typical Next.js + BuildBase project:
app/
├── api/
│ └── auth/
│ ├── verify/route.ts ← exchanges code for session
│ ├── session/route.ts ← returns session from cookie
│ └── signout/route.ts ← clears session cookie
├── (auth)/
│ ├── login/page.tsx ← public pages
│ └── register/page.tsx
├── (app)/
│ ├── layout.tsx ← wraps in BuildBaseProvider
│ ├── dashboard/page.tsx ← protected pages
│ ├── settings/page.tsx
│ └── billing/page.tsx
├── layout.tsx ← root layout (fonts, global styles)
└── providers.tsx ← BuildBaseProvider component4. Protect your routes
Wrap your authenticated layout so unauthenticated users can't access app pages:
// app/(app)/layout.tsx
'use client';
import {
useSaaSAuth,
WhenAuthenticated,
WhenUnauthenticated,
} from '@buildbase/sdk/react';
export default function AppLayout({ children }: { children: React.ReactNode }) {
const { isLoading, signIn } = useSaaSAuth();
if (isLoading) return <LoadingSpinner />;
return (
<>
<WhenAuthenticated>{children}</WhenAuthenticated>
<WhenUnauthenticated>
<button onClick={() => signIn()}>Sign In</button>
</WhenUnauthenticated>
</>
);
}5. Dashboard setup checklist
Before going live, make sure these are configured in the BuildBase dashboard:
| Step | Where | What to do |
|---|---|---|
| Create org | Dashboard home | Click "Create Organization" |
| Get credentials | Settings → General | Copy orgId |
| Set up OAuth | User Management → Access → Authentication | Create a client, get clientId and clientSecret, add redirect URLs |
| Add auth methods | User Management → Access → Authentication → Methods | Enable Email/Password, Google, or Magic Link |
| Create plans | Billing → Plans | Set up at least one plan (if using billing) |
| Connect Stripe | Billing → Credentials | Enter Stripe API keys (test keys for dev) |
| Set up email sender | Messaging → Sender Accounts | Configure Google, Mailgun, or SMTP |
| Add redirect URLs | User Management → Access → Authentication | Add your production URL (e.g. https://yourapp.com/callback) |
6. Production environment
For production, update your environment variables:
# .env.production
NEXT_PUBLIC_BUILDBASE_SERVER_URL=https://api.console.buildbase.app
NEXT_PUBLIC_BUILDBASE_ORG_ID=your-org-id
NEXT_PUBLIC_BUILDBASE_CLIENT_ID=your-client-id
NEXT_PUBLIC_BUILDBASE_REDIRECT_URL=https://yourapp.com/callback
BUILDBASE_CLIENT_SECRET=your-client-secret
SESSION_SECRET=your-production-secretKey differences from development:
REDIRECT_URLmust be your production domain (not localhost)- Add the production redirect URL in the dashboard under User Management → Access → Authentication
- Use real Stripe keys instead of test keys
- Set
secure: trueon session cookies (already handled by theNODE_ENVcheck above)
7. Deployment checklist
Before your first deploy:
- Environment variables set in your hosting platform (Vercel, Railway, etc.)
- Production redirect URL added in BuildBase dashboard
- Auth methods enabled (email, social, magic link)
- At least one plan created and published (if using billing)
- Stripe connected with live keys (if using billing)
- Email sender configured (for transactional emails)
- Test the full sign-in → dashboard → sign-out flow in production
Next Steps
- Authentication — Deep dive into auth methods and sessions.
- Billing — Set up plans, checkout, and subscriptions.
- Server SDK — Backend operations: usage recording, credits, notifications.
- Self-Hosted — Deploy on your own infrastructure.