← Taking the weekly build challenge?

Which auth stack should you use for your vibe-coded app?

Clerk for B2B SaaS. Supabase Auth for data-heavy apps. NextAuth for internal tools. Firebase for consumer mobile.

Below: decision tree, hidden pricing traps, cost calculator, and the full setup for using Clerk WITH Supabase.

You've tried 4 different auth providers. Burned two days evaluating. Still not sure. This guide cuts through the noise — pick your project type, get your answer, copy the setup, and ship.

Covers: Clerk vs Supabase Auth vs NextAuth vs Firebase Auth — with a decision tree, comparison table, pricing traps, and the 5 mistakes that break vibe-coded apps.

1. Decision Tree — Pick Your Project Type

Stop evaluating. Match your project to the pattern below and use that auth stack. This covers 95% of vibe-coded apps.

🏢

Project Type

SaaS / B2B App

Recommended

Clerk

Orgs, teams, roles, and SSO out of the box. You want users managed for you — not a custom auth system. Clerk is the fastest path from zero to production-grade B2B auth.

⚠️Don’t use NextAuth (too much plumbing for SaaS features) or roll your own.
🛒

Project Type

Marketplace / Community Platform

Recommended

Supabase Auth

You need auth + database + RLS working together. Supabase Auth ties into Row Level Security natively — every user action is scoped to their data. This is the best combo for marketplaces.

⚠️Clerk is great but adds complexity when you need RLS on every table.
📱

Project Type

Consumer Mobile / Web App

Recommended

Firebase Auth

Google Sign-In, Apple Sign-In, phone OTP, anonymous auth — all in one SDK. If you need social logins and mobile-first flows, Firebase Auth has the best out-of-the-box coverage.

⚠️Supabase social auth requires more config; Clerk has limited native mobile SDKs.
🔧

Project Type

Internal Tool / Admin Dashboard

Recommended

NextAuth (Auth.js)

Internal tools don’t need complex user management — they need a quick login gate. NextAuth with GitHub or Google provider is 30 minutes to working auth with zero ongoing cost.

⚠️Don’t pay for Clerk or Firebase just to gate an internal tool.

2. Clerk vs Supabase Auth vs NextAuth vs Firebase Auth

Full comparison across the dimensions that actually matter for vibe-coded apps.

FeatureClerkSupabaseNextAuthFirebase
Free Tier10k MAU50k MAUFree (OSS)10k/month
Pricing After$25/mo (25k MAU)$25/mo (project)Self-host costs only$0.0055/MAU
Setup Time~15 min~30 min~45 min~20 min
Social Login✅ Built-in UI✅ Built-in✅ via providers✅ Best-in-class
Email/Password✅ w/ UI✅ Credentials
Magic Link✅ Email provider
Phone/SMS OTP❌ (workaround)✅ Best
MFA / 2FA✅ Built-in⚠️ TOTP only❌ DIY
Orgs / Teams✅ Native❌ DIY w/ RLS❌ DIY❌ DIY
Pre-built UI✅ Drop-in⚠️ Basic❌ You build it⚠️ FirebaseUI
RLS Integration⚠️ Manual JWT✅ Native❌ Manual❌ Manual
Next.js Support✅ First-class✅ First-class✅ Made for it✅ Good
User Dashboard✅ Full UI✅ In Studio✅ Console
Best ForSaaS, B2BMarketplace, data-heavyInternal tools, simple appsConsumer mobile/web

3. Hidden Pricing Traps Nobody Tells You

Every auth provider looks affordable on the pricing page. Here's what actually shows up on your bill.

Clerk

Pricing Trap

MFA costs $100/mo on the Pro plan

The free tier includes basic password auth and social login. But if you need SMS-based MFA or TOTP for compliance (SOC 2, HIPAA), you need the Pro plan at $25/mo — and the MFA add-on is $100/mo on top of that. A B2B SaaS requiring MFA for enterprise clients is looking at $125/mo minimum before you have a single paying customer.

The Numbers

Free: 10k MAU, no MFA. Pro ($25/mo): 25k MAU + basic MFA. Full MFA add-on: +$100/mo.

Supabase

Pricing Trap

The $25/mo Pro plan is per-project, not per-account

50,000 MAU free sounds generous — and it is for a single project. But the Pro plan ($25/mo) is charged per project. If you have a main app, a staging environment, and a separate admin dashboard, that’s $75/mo. Running microservices with separate Supabase instances? Costs multiply fast.

The Numbers

Free: 50k MAU, 2 projects. Pro: $25/mo per project. 3 projects = $75/mo. Team ($599/mo) covers 1 org.

NextAuth

Pricing Trap

“Free” means you build and host everything yourself

NextAuth is open-source, so there’s no license fee. But “free” is misleading. You need hosting for your auth service ($10–20/mo on Railway or Vercel), a database for sessions ($5–15/mo), and your engineering time for every feature Clerk gives you for free: org management, pre-built UI, MFA, user dashboard.

The Numbers

License: $0. Hosting: $10–20/mo. Database: $5–15/mo. Eng time for orgs/MFA/UI: 40–100+ hours.

Firebase

Pricing Trap

Phone auth is priced per verification, not per user

Firebase Auth is free for email/password and social login up to 10k MAU. But phone/SMS auth is billed per verification at $0.01–$0.06 per SMS depending on country. A consumer app with 50k phone verifications per month (signups + re-verifications + password resets) can hit $500–$3,000/mo. Nobody mentions this on the marketing page.

The Numbers

Email auth: free to 10k MAU. Phone auth: $0.01–$0.06/SMS. 50k verifications: $500–$3,000/mo.

4. Auth Cost Calculator — By Monthly Active Users

What each auth provider actually costs at different user scales. Includes base plan + common add-ons (MFA, phone auth, extra projects).

MAUClerkSupabase AuthNextAuthFirebase

100

users/mo

$0

Free tier

$0

Free tier

$10–15/mo

Hosting + DB

$0

Free tier

1,000

users/mo

$0

Free tier (10k limit)

$0

Free tier (50k limit)

$10–15/mo

Hosting + DB

$0

Free tier (10k limit)

10,000

users/mo

$0–$25/mo

At free tier limit. Pro for MFA.

$0

Still free tier

$15–25/mo

Growing DB + hosting

$0–$55/mo

Free if email-only. $55 if phone auth.

100,000

users/mo

$175+/mo

$25 Pro + $100 MFA + overages

$25/mo

Pro plan, still under 50k free auth

$25–50/mo

Larger DB + compute

$495+/mo

$0 email. $495+ if phone auth heavy.

* Prices as of March 2026. Clerk MFA pricing is for the add-on. Firebase phone auth assumes US SMS rates ($0.01/SMS). NextAuth costs are hosting + database only.

5. Using Clerk WITH Supabase (Not Instead)

The most powerful auth pattern in 2026: Clerk handles auth UI, organizations, and user management. Supabase handles your database with Row Level Security. Here's the full setup.

Why This Combo Works

Clerk gives you drop-in sign-up/sign-in UI, org management, and SSO that would take weeks to build. Supabase gives you PostgreSQL with RLS — row-level security that scopes every query to the authenticated user. Together, you get enterprise-grade auth UI + database security without building either from scratch.

Step 1 — Set Up Clerk Normally

Install Clerk, wrap your app in ClerkProvider, set up middleware. Follow the standard Clerk setup from the snippets section below.

Step 2 — Create a JWT Template in Clerk

In your Clerk Dashboard → JWT Templates → Create New → Choose "Supabase" template. This creates a JWT that Supabase can verify. The template automatically includes the user's Clerk ID as the sub claim.

// Clerk JWT Template payload (auto-generated)
{
  "sub": "user_2abc123...",
  "iss": "https://clerk.your-app.com",
  "role": "authenticated"
}

Step 3 — Configure Supabase JWT Secret

Copy the JWT signing key from your Clerk JWT template. In Supabase Dashboard → Settings → API → JWT Secret, paste the Clerk signing key. This tells Supabase to trust JWTs signed by Clerk.

Step 4 — Create a Supabase Client with Clerk Token

Create a utility that initializes the Supabase client with the Clerk session token. This is the key integration point.

// lib/supabase/clerk-client.ts
import { createClient } from '@supabase/supabase-js';
import { auth } from '@clerk/nextjs/server';

export async function createClerkSupabaseClient() {
  const { getToken } = await auth();
  const supabaseToken = await getToken({
    template: 'supabase'
  });

  return createClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      global: {
        headers: { Authorization: `Bearer ${supabaseToken}` }
      }
    }
  );
}

Step 5 — Write RLS Policies Using Clerk's JWT

Since Clerk's JWT uses sub (not Supabase's auth.uid()), your RLS policies reference the JWT directly.

-- Enable RLS on your table
ALTER TABLE todos ENABLE ROW LEVEL SECURITY;

-- Policy: users can only access their own rows
-- auth.jwt()->>'sub' extracts the Clerk user ID from the JWT
CREATE POLICY "Users can CRUD own todos"
ON todos FOR ALL
USING (auth.jwt()->>'sub' = user_id);

Common Gotcha

Your user_id column must store the Clerk user ID (e.g., user_2abc123), not a Supabase UUID. When creating rows, set user_id = auth.jwt()->>'sub' in your insert or use a database trigger.

6. Copy-Paste Setup Snippets

The key config for each — not a full tutorial, just what you actually need to drop into your project.

Clerk — Next.js Setup

1. Install

npm install @clerk/nextjs

2. Environment Variables

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...

3. Wrap your app — app/layout.tsx

import { ClerkProvider } from '@clerk/nextjs';

export default function RootLayout({ children }) {
  return (
    <ClerkProvider>
      <html><body>{children}</body></html>
    </ClerkProvider>
  );
}

4. Protect routes — middleware.ts

import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';

const isProtected = createRouteMatcher(['/dashboard(.*)']);

export default clerkMiddleware((auth, req) => {
  if (isProtected(req)) auth().protect();
});

Supabase Auth — Next.js Setup

1. Install

npm install @supabase/supabase-js @supabase/ssr

2. Environment Variables

NEXT_PUBLIC_SUPABASE_URL=https://xxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...

3. Server client util — lib/supabase/server.ts

// lib/supabase/server.ts
import { createServerClient } from '@supabase/ssr';
import { cookies } from 'next/headers';

export async function createClient() {
  const cookieStore = await cookies();
  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    { cookies: { getAll() { return cookieStore.getAll() } } }
  );
}

4. Sign up / Sign in

const supabase = await createClient();

// Sign up
const { data, error } = await supabase.auth.signUp({ email, password });

// Sign in
const { data, error } = await supabase.auth.signInWithPassword({ email, password });

⚠️ Security — SQL Editor

Always enable RLS on every table. The anon key is public.

ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;

CREATE POLICY "own rows" ON your_table FOR ALL USING (auth.uid() = user_id);

NextAuth (Auth.js) — Next.js Setup

1. Install

npm install next-auth@beta

2. Environment Variables

AUTH_SECRET=generate-with-openssl-rand-base64-32
AUTH_GITHUB_ID=your-github-client-id
AUTH_GITHUB_SECRET=your-github-client-secret

3. Config file — auth.ts

import NextAuth from 'next-auth';
import GitHub from 'next-auth/providers/github';

export const { auth, handlers, signIn, signOut } = NextAuth({
  providers: [GitHub()],
});

4. Route handler — app/api/auth/[...nextauth]/route.ts

export { handlers as GET, handlers as POST } from "@/auth";

Firebase Auth — Next.js Setup

1. Install

npm install firebase

2. Environment Variables

NEXT_PUBLIC_FIREBASE_API_KEY=AIza...
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=app.firebaseapp.com
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your-project-id

3. Firebase config — lib/firebase.ts

import { initializeApp, getApps } from 'firebase/app';
import { getAuth } from 'firebase/auth';

const app = getApps().length ? getApps()[0] : initializeApp(config);
export const auth = getAuth(app);

4. Google Sign-In (client component)

import { signInWithPopup, GoogleAuthProvider } from 'firebase/auth';
const provider = new GoogleAuthProvider();
await signInWithPopup(auth, provider);

7. What AI Gets Wrong About Auth

When you ask ChatGPT or Claude to "set up auth for my SaaS," here's what it consistently gets wrong.

01

AI always recommends Clerk without mentioning the MFA pricing trap

Every AI model defaults to Clerk for SaaS auth — and rightfully so, the DX is excellent. But none of them mention that MFA (which enterprise clients require) costs $100/mo extra on top of the $25/mo Pro plan. If you’re building for enterprises, you need to budget $125/mo for auth alone.

02

AI generates Supabase auth code without RLS policies

The code works perfectly in development. But without Row Level Security policies, your entire database is readable by any authenticated user via the public anon key. AI-generated Supabase auth is a security hole until you add RLS manually.

03

AI suggests NextAuth for SaaS without mentioning the org/team engineering cost

NextAuth is great for simple login flows. But when you need organizations, team invitations, role-based access, and SSO — standard SaaS requirements — you’re building all of it from scratch. That’s 40–100 hours of engineering that Clerk gives you for $25/mo.

04

AI never warns about Firebase phone auth costs for consumer apps

AI recommends Firebase for consumer mobile apps (correctly), but never mentions that phone/SMS authentication is billed per verification at $0.01–$0.06 per SMS. A consumer app with heavy phone auth usage can hit $500+/mo in verification costs alone.

05

AI doesn’t know about the Clerk + Supabase combined pattern

AI treats Clerk and Supabase Auth as mutually exclusive choices. In reality, the most powerful pattern is using both: Clerk for auth UI and user management, Supabase for database + RLS. This requires JWT template sync — see our setup guide above.

8. 5 Auth Mistakes Vibe Coders Make

These are the auth patterns that look fine in dev and break in production — or worse, create security holes.

01

Rolling Your Own Auth

Hashing passwords with bcrypt and managing sessions yourself sounds simple. It isn’t. You’ll miss CSRF protection, session fixation, timing attacks, and secure cookie flags. This is the #1 cause of security breaches.

SolutionUse Clerk, Supabase Auth, or NextAuth. Auth is solved. Your job is to ship your product.
02

Skipping RLS When Using Supabase Auth

The anon key is public. If you don’t enable Row Level Security, any user can query any table from the browser. Your entire database is exposed to any user who opens DevTools.

SolutionEvery table needs RLS enabled AND a policy. No policy = no access. Bad policy = everyone can see everything.
03

Not Setting Up Email Verification

Users sign up with fake emails. You send transactional emails that never reach anyone. Your bounce rate tanks your sender reputation. Unverified accounts make user management a mess.

SolutionEnable email confirmation in your auth provider. For Supabase: Dashboard → Auth → Email → Confirm email ON.
04

Protecting Routes Only on the Client

Checking if (!user) only in a React component means your server routes and API routes are wide open. A direct URL or API call bypasses all of it.

SolutionProtect routes in middleware or in the server component using the server-side auth check. Never trust the client.
05

Hardcoding Auth Credentials

NEXT_PUBLIC_ env vars are bundled into your client-side JS and visible to everyone. Service role keys and secret keys committed to GitHub get scraped by bots within minutes.

SolutionSecret keys stay in .env.local (gitignored) and your hosting provider’s env vars. Never prefix secret keys with NEXT_PUBLIC_.

9. Tools & Resources

Stop Evaluating

Build your auth in 7 days — with a real deadline

Join the challenge