Skene
BLOG

Nextbase Review: Next.js 16 + Supabase Starter PLG Audit 2026

Is Nextbase good for SaaS? We audited signup flow, auth, and database schema. Best signup (8/10) among Supabase starters but zero monetization. Score: 3.2/10 for PLG. See what's missing.

·bySkene·LinkedIn
Summarize this article with LLMs

Nextbase is a free Next.js 16 and Supabase starter with 768+ stars. It's positioned as "the last Next.js and Supabase starter you'll ever need."

We ran it through a comprehensive PLG skills audit. The result: the best signup flow among Supabase starters, but zero monetization layer.

Overall PLG Score: 3.2/10 — Excellent technical foundation for auth, but designed as a boilerplate, not a PLG platform.


The full audit

CategoryScoreKey finding
Signup flow8/103 auth methods, Zod validation, magic link support
Feature gating0/10No pricing, plans, or subscription tracking
Trial optimization0/10Not implemented
Product analytics0/10No tracking infrastructure
Self-serve motion2/10No checkout, no billing, no upgrade path
Empty states7/10Good component system with CTAs

1. Signup flow analysis (8/10)

Nextbase has the strongest signup implementation among the templates we analyzed.

Multi-method authentication

Location: src/app/(dynamic-pages)/(login-pages)/(login-pages)/sign-up/Signup.tsx

The signup page offers three authentication methods via tabs:

// Lines 117-174
<Tabs defaultValue="password">
  <TabsList className="grid w-full grid-cols-3">
    <TabsTrigger value="password">Password</TabsTrigger>
    <TabsTrigger value="magic_link">Magic Link</TabsTrigger>
    <TabsTrigger value="social_login">Social Login</TabsTrigger>
  </TabsList>
</Tabs>

Tab 1: Email + Password

  • 2 required fields (email, password)
  • Uses EmailAndPassword component

Tab 2: Magic Link

  • 1 required field (email only)
  • Passwordless signup via Supabase OTP

Tab 3: Social Login

  • Google, GitHub, Twitter configured
  • Uses RenderProviders component

Form validation with Zod

Location: src/data/auth/auth.ts

Server-side validation with Zod schemas:

// Lines 7-10
const signUpSchema = z.object({
  email: z.string().email(),
  password: z.string().min(3)  // Note: weak password requirement
});

The validation uses next-safe-action for type-safe server actions:

// src/lib/safe-action.ts Lines 1-37
export const actionClient = createSafeActionClient({
  handleServerError(e) {
    console.error("Action error:", e.message);
    return e.message;
  }
});

Email verification flow

Location: src/components/Auth/EmailConfirmationPendingCard.tsx

After signup, users see a confirmation pending screen:

// Lines 50-65
<div className="flex flex-col items-center gap-2">
  <Mail className="h-12 w-12" />
  <h3>Confirmation Link Sent</h3>
  <p>A confirmation link has been sent to your email!</p>
</div>

The auth callback at src/app/.../auth/callback/route.ts handles:

  • Code exchange for session
  • Redirect to /dashboard (or custom next param)
  • Path revalidation

OAuth implementation

Location: src/components/Auth/RenderProviders.tsx

// Lines 10-20 (in Signup.tsx)
const providers: OAuthProvider[] = ['google', 'github', 'twitter'];

OAuth flow via Supabase:

// src/data/auth/auth.ts Lines 116-136
export const signInWithProviderAction = actionClient
  .schema(providerSchema)
  .action(async ({ parsedInput: { provider, next } }) => {
    const supabase = createClient();
    const { data, error } = await supabase.auth.signInWithOAuth({
      provider,
      options: { redirectTo: `${getURL()}/auth/callback?next=${next}` }
    });
    return data.url;
  });

What's missing in signup

Weak password policy:

password: z.string().min(3)  // Should be min(8) with complexity

No signup analytics:

  • No tracking events for signup funnel
  • No user identification on signup

2. Feature gating audit (0/10)

No monetization infrastructure

Nextbase has zero pricing or subscription implementation:

  • No products, prices, or subscriptions tables
  • No Stripe, Paddle, or payment integration
  • No plan, tier, or subscription fields anywhere
  • No feature flags or hasFeature() checks

Route protection

The only access control is authentication-based:

Location: src/supabase-clients/middleware.ts

// Lines 37-62
const protectedPages = [
  '/dashboard',
  '/private-item',
  '/private-items',
];

// Check if user exists
const { data: { user } } = await supabase.auth.getUser();

// Redirect if not authenticated
if (!user && isProtectedPage) {
  return NextResponse.redirect('/login');
}

No subscription-tier checks. All authenticated users have equal access to all features.


3. Trial optimization (0/10)

Not implemented. No trial-related code found:

  • No trial_start, trial_end, or trial_days fields
  • No trial expiry handling
  • No trial emails
  • No trial extension logic

4. Product analytics (0/10)

No analytics SDK

Package.json dependencies (Lines 21-125): No analytics packages.

The template includes UI/UX libraries but no tracking:

  • @tanstack/react-query (data fetching)
  • sonner, react-hot-toast (notifications)
  • framer-motion (animations)
  • @hookform/resolvers (forms)

No Mixpanel, Amplitude, PostHog, Segment, or GA4.

No event tracking

  • No .track() or .capture() calls
  • No user identification
  • No funnel measurement

5. Self-serve motion (2/10)

What exists

The signup-to-value flow works:

  1. Signup at /sign-up
  2. Email verification via Supabase
  3. Auth callback exchanges code for session
  4. Dashboard access at /dashboard

Users can create "private items" — the template's demo feature.

What's missing

No checkout flow:

  • No payment processing
  • No Stripe/Paddle integration
  • No billing endpoints

No upgrade path:

  • No pricing page
  • No plan selection UI
  • No upgrade modals

No team management:

  • No invite functionality
  • No team tables
  • No role-based access

No billing management:

  • No invoice history
  • No payment method management
  • No subscription cancellation

6. Empty states (7/10)

Well-designed empty state system

Location: src/components/ui/empty.tsx

Nextbase includes a reusable empty state component:

// Composable empty state pattern
<Empty>
  <EmptyHeader>
    <EmptyMedia variant="icon">
      <ShieldCheck />
    </EmptyMedia>
    <EmptyTitle>No Private Items Available</EmptyTitle>
    <EmptyDescription>
      You haven't created any private items yet.
    </EmptyDescription>
  </EmptyHeader>
  <EmptyContent>
    <Button>Create Your First Private Item</Button>
  </EmptyContent>
</Empty>

Components:

  • Empty — Container
  • EmptyHeader — Icon, title, description section
  • EmptyMedia — Icon wrapper with variants
  • EmptyTitle — Heading text
  • EmptyDescription — Explanation text
  • EmptyContent — CTA section

This follows best practices: icon → title → description → action button.


Database schema

Location: src/lib/database.types.ts (auto-generated)

Existing tables

TableColumnsPurpose
private_itemsid, name, description, owner_id, created_atUser-owned content
content_blog_postsid, title, body, author_id, is_published, slugBlog publishing
content_blog_post_commentsid, blog_post_id, author_id, bodyComments

Missing for PLG

  • No users or profiles table (relies on Supabase Auth)
  • No subscriptions table
  • No plans table
  • No usage or limits table
  • No teams or organizations table
  • No analytics_events table

Technology stack

Frontend

  • Next.js: v16.0.1 (App Router)
  • React: v19.1.0
  • TypeScript: v5.8.3
  • Tailwind CSS: v4.1.3

Form & validation

  • react-hook-form: v7.55.0
  • zod: v3.24.2
  • @hookform/resolvers: v3.10.0

UI components

  • Radix UI: 20+ components
  • lucide-react: v0.546.0 (icons)
  • framer-motion: v11.18.2 (animations)

Auth & backend

  • @supabase/supabase-js: v2.80.0
  • @supabase/ssr: v0.7.0
  • next-safe-action: v7.10.5

Notifications

  • sonner: v1.7.4
  • react-hot-toast: v2.5.2

Strengths

  1. Best signup flow — 3 auth methods, Zod validation, proper email verification
  2. Modern stack — Next.js 16, React 19, TypeScript 5.8
  3. Clean architecture — Server actions, proper separation of concerns
  4. Good form UX — Multiple auth methods, loading states, error handling
  5. Reusable components — Empty states, auth forms, UI primitives

Critical gaps

FeatureStatus
AnalyticsNot implemented
SubscriptionsNot implemented
PricingNot implemented
Feature gatingNot implemented
TrialsNot implemented
Team managementNot implemented
OnboardingNot implemented

What you need to add

Priority 1: Analytics

Integrate PostHog or Segment:

// Track signup funnel
track('signup_page_viewed');
track('signup_method_selected', { method: 'password' | 'magic_link' | 'oauth' });
track('signup_completed');
identify(userId, { email, signupMethod });

Priority 2: Monetization

Add Stripe or Paddle:

  1. Create subscriptions table
  2. Add webhook handler for Stripe events
  3. Build pricing page with plan comparison
  4. Implement checkout flow

Priority 3: Feature gating

Create permission system:

function hasFeature(user: User, feature: string): boolean {
  const plan = user.subscription?.plan;
  return PLAN_FEATURES[plan]?.includes(feature) ?? false;
}

Priority 4: Onboarding

Add post-signup guidance:

  1. Welcome modal with product tour
  2. Checklist of first actions
  3. onboarding_completed field in user preferences

First steps to PLG

Nextbase has great auth but nothing else. Here's the path forward:

Week 1: Add analytics first

Before building anything, you need to measure:

  1. Install PostHog: npm install posthog-js
  2. Initialize in _app.tsx or your root layout
  3. Add posthog.identify() after successful login
  4. Track: signup_completed, login_completed, feature_used

Week 2: Add basic Stripe

  1. Install Stripe: npm install stripe @stripe/stripe-js
  2. Create a subscriptions table in Supabase
  3. Build a simple checkout endpoint
  4. Handle the checkout.session.completed webhook

Start with just two plans: Free and Pro.

Week 3: Gate one feature

Pick a single feature to put behind the paywall:

// Simple gating
const isPro = user.subscription?.status === 'active';

{isPro ? <ProFeature /> : <UpgradePrompt />}

Track when users see the upgrade prompt and when they click it.

Week 4: Add trial

  1. Add trial_end parameter to your Stripe checkout
  2. Create a "trial ending" email for day 12
  3. Show trial days remaining in your UI
  4. Track trial_started, trial_ending_soon, trial_converted

What to measure

Build a simple funnel dashboard:

  • Signup → Aha moment (define this for your product)
  • Aha moment → Trial started
  • Trial started → Trial converted
  • Monthly: Expansion revenue from upgrades

When to use Nextbase

Good fit:

  • Learning Next.js + Supabase patterns
  • Internal tools or prototypes
  • Projects where you'll add monetization yourself

Not ideal:

  • Monetized SaaS (need to add entire billing layer)
  • PLG-focused products (no activation tracking)
  • Products requiring analytics (none included)

Conclusion

Nextbase scores 3.2/10 for PLG readiness but has the strongest signup flow (8/10) of any template we analyzed.

It's a well-engineered developer boilerplate, not a growth platform. Use it when:

  • You want a clean starting point
  • You'll add your own monetization
  • Signup UX is critical to your product

The empty state system (7/10) is also worth copying — it follows best practices that many templates miss.


Appendix: Key file locations

ComponentFile
Signup componentsrc/app/.../sign-up/Signup.tsx
Auth actionssrc/data/auth/auth.ts
Email + password formsrc/components/Auth/EmailAndPassword.tsx
Magic link formsrc/components/Auth/Email.tsx
OAuth providerssrc/components/Auth/RenderProviders.tsx
Email confirmationsrc/components/Auth/EmailConfirmationPendingCard.tsx
Auth callbacksrc/app/.../auth/callback/route.ts
Middlewaresrc/supabase-clients/middleware.ts
Safe action clientsrc/lib/safe-action.ts
Empty state componentsrc/components/ui/empty.tsx
Database typessrc/lib/database.types.ts

This analysis was performed using PLG Skills, an open-source framework for product-led growth audits. Skills used: signup-flow-cro, feature-gating, trial-optimization, product-analytics, self-serve-motion.


Frequently asked questions

Is Nextbase good for building a SaaS?

Nextbase is excellent for authentication and signup flow (8/10) but has zero monetization infrastructure. There's no Stripe integration, no subscription tables, and no pricing page. Use it if you need a clean Next.js + Supabase starter and will add billing yourself.

What authentication methods does Nextbase support?

Nextbase supports 3 authentication methods via a tabbed interface: email + password, magic link (passwordless), and OAuth (Google, GitHub, Twitter). It also includes proper email verification flow with a 60-second countdown before resend.

Does Nextbase include Stripe or payment integration?

No. Nextbase has zero payment infrastructure — no Stripe, Paddle, or any billing integration. There are no subscriptions, products, or prices tables. You'll need to add the entire billing layer yourself.

What's the tech stack for Nextbase?

Nextbase uses Next.js 16.0.1 (App Router), React 19.1.0, TypeScript 5.8.3, Tailwind CSS 4.1.3, react-hook-form with Zod validation, 20+ Radix UI components, and Supabase for auth and database.

How does Nextbase compare to other Supabase starters?

Nextbase has the best signup flow (8/10) but scores lowest for PLG readiness (3.2/10) due to no monetization. Launch MVP scores 5.9/10 with trials and analytics. Vercel's template scores 3/10 but has full Stripe billing. Choose based on whether you need auth-first or billing-first.

Should I use Nextbase for a product-led growth product?

Not ideal out of the box. Nextbase has no analytics, no feature gating, no trials, and no subscription tracking. It's a developer boilerplate, not a PLG platform. Use it as a starting point if you'll add PLG infrastructure yourself, or choose Launch MVP for built-in PLG features.

Done with this article? Explore more ways to ship real PLG.