Ship SaaS Faster with Next.js Components
saasnextjsreactboilerplatecomponentstutorial6 min read

Ship SaaS Faster with Next.js Components

Adminโ€ข

Every SaaS product needs the same foundation: authentication flows, dashboard layouts, settings pages, forms, tables, and navigation. Building these from scratch costs weeks of development timeโ€”time you could spend on features that differentiate your product.

The SaaS Starter Kit provides production-ready Next.js components for auth, dashboards, settings, and moreโ€”all built with accessibility, responsive design, and token-driven theming.

๐ŸŽฏ What Every SaaS Needs (But Nobody Wants to Build)

Before writing a single line of code, you'll need:

  1. Authentication: Login, signup, password reset, OTP verification
  2. App shell: Sidebar navigation, topbar, user menu
  3. Dashboard: Layouts, cards, charts, data tables
  4. Settings: Account, billing, team management, integrations
  5. Forms: Validation, error handling, loading states
  6. Accessibility: WCAG AA compliance, keyboard navigation

Building these takes 4-6 weeks for an experienced team. The SaaS Starter Kit gives you all of this in days.

๐Ÿ” Building Accessible Authentication Flows

Authentication is the first thing users see, and it needs to be bulletproof. Here's how the SaaS Starter Kit implements login:

import { LoginForm } from '@/components/ui/recipes/authentication/login-form'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import * as z from 'zod'

const loginSchema = z.object({
  email: z.string().email('Please enter a valid email address'),
  password: z.string().min(6, 'Password must be at least 6 characters'),
})

export default function LoginPage() {
  const handleSubmit = async (data: LoginFormData) => {
    // Your auth logic here
    await signIn(data.email, data.password)
  }

  return (
    <div className="min-h-screen flex items-center justify-center">
      <LoginForm
        onSubmit={handleSubmit}
        showSocialLogin={true}
        showSignupLink={true}
        showForgotPasswordLink={true}
        onSocialLogin={(provider) => {
          // Handle OAuth
          signInWithProvider(provider)
        }}
      />
    </div>
  )
}

What You Get Out of the Box

  • โœ… Form validation with Zod and react-hook-form
  • โœ… Error messages that are accessible to screen readers
  • โœ… Social login buttons (Google, Microsoft, Apple)
  • โœ… Loading states during submission
  • โœ… Keyboard navigation for all inputs
  • โœ… Password visibility toggle with proper ARIA labels

๐Ÿ—๏ธ Building the App Shell

The app shell is the foundation of your SaaS dashboard. Here's the main sidebar component:

import { MainSidebar } from '@/components/ui/composites/main-sidebar'

export default function DashboardLayout({ children }: { children: React.ReactNode }) {
  const [activeNav, setActiveNav] = React.useState('chat')
  const [activeSection, setActiveSection] = React.useState('account')

  return (
    <div className="flex h-screen">
      <MainSidebar
        activeMainNav={activeNav}
        activeSection={activeSection}
        onMainNavChange={setActiveNav}
        onSectionChange={setActiveSection}
        user={{
          name: 'John Doe',
          email: 'john@example.com',
          avatar: '/avatars/john.jpg',
        }}
        onUpgrade={() => router.push('/pricing')}
      />
      
      <main className="flex-1 overflow-auto">
        {children}
      </main>
    </div>
  )
}

Sidebar Features

  • Main navigation: Chat, Notifications, Profile, Assistant, Settings
  • Settings sub-navigation: Account, Notifications, AI Integrations, Team & Permissions, Billing, Privacy & Security
  • User menu with avatar and upgrade CTA
  • Collapsible sections for mobile
  • Active state management with visual indicators
  • Tooltips for icon-only navigation items

๐Ÿ“Š Building Dashboard Pages

Dashboards need flexible layouts that work across screen sizes. The kit provides composable components:

import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/primitives/card'
import { Button } from '@/components/ui/primitives/button'

export default function DashboardPage() {
  return (
    <div className="p-6 space-y-6">
      <div className="flex items-center justify-between">
        <h1 className="text-2xl font-bold">Dashboard</h1>
        <Button action="primary">New Project</Button>
      </div>

      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
        <Card>
          <CardHeader>
            <CardTitle>Total Users</CardTitle>
          </CardHeader>
          <CardContent>
            <div className="text-3xl font-bold">1,234</div>
            <p className="text-sm text-muted-foreground">+12% from last month</p>
          </CardContent>
        </Card>
        
        {/* More cards... */}
      </div>

      <Card>
        <CardHeader>
          <CardTitle>Recent Activity</CardTitle>
        </CardHeader>
        <CardContent>
          {/* Data table or activity feed */}
        </CardContent>
      </Card>
    </div>
  )
}

โš™๏ธ Building Settings Pages

Settings pages are complexโ€”they need forms, validation, and clear organization. Here's how the kit structures them:

import { MainSidebar } from '@/components/ui/composites/main-sidebar'
import { AccountSettingsForm } from '@/components/ui/recipes/settings/account-settings-form'

export default function SettingsPage() {
  return (
    <div className="flex">
      <MainSidebar activeMainNav="settings" activeSection="account" />
      
      <main className="flex-1 p-6">
        <div className="max-w-2xl">
          <h1 className="text-2xl font-bold mb-6">Account Settings</h1>
          
          <AccountSettingsForm
            initialData={{
              name: 'John Doe',
              email: 'john@example.com',
              company: 'Acme Inc',
            }}
            onSubmit={async (data) => {
              await updateAccount(data)
            }}
          />
        </div>
      </main>
    </div>
  )
}

The settings form includes:

  • Field validation with inline error messages
  • Loading states during save
  • Success/error toasts for user feedback
  • Accessible labels and help text
  • Keyboard shortcuts for common actions

๐Ÿ“ Building Accessible Forms

Forms are everywhere in SaaS apps. The kit provides a consistent form system:

import { Form, FormField, FormLabel, FormMessage } from '@/components/ui/primitives/form'
import { Field, FieldContent, FieldError } from '@/components/ui/primitives/field'
import { Input } from '@/components/ui/primitives/input'

function TeamSettingsForm() {
  const { register, handleSubmit, formState: { errors } } = useForm({
    resolver: zodResolver(teamSchema),
  })

  return (
    <Form onSubmit={handleSubmit(onSubmit)}>
      <FormField>
        <Field isInvalid={!!errors.teamName}>
          <FieldContent>
            <Input
              {...register('teamName')}
              placeholder="Team name"
              isError={!!errors.teamName}
            />
            {errors.teamName && (
              <FieldError>{errors.teamName.message}</FieldError>
            )}
          </FieldContent>
        </Field>
      </FormField>
    </Form>
  )
}

Form Features

  • Consistent error styling across all inputs
  • Accessible error announcements for screen readers
  • Focus management moves to first error on submit
  • Loading states disable inputs during submission
  • Validation happens on blur and submit

๐ŸŽจ Token-Driven Design System

The SaaS Starter Kit uses design tokens synced between Figma and Tailwind:

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: {
          50: 'var(--color-primary-50)',
          100: 'var(--color-primary-100)',
          600: 'var(--color-primary-600)',
          700: 'var(--color-primary-700)',
        },
        secondary: {
          100: 'var(--color-secondary-100)',
          200: 'var(--color-secondary-200)',
          // ... more tokens
        },
      },
      spacing: {
        'token-1': 'var(--spacing-token-1)',
        'token-2': 'var(--spacing-token-2)',
        // ... tokenized spacing scale
      },
    },
  },
}

This ensures:

  • Design-code parity: Figma designs translate directly to components
  • Theme consistency: Light/dark mode works automatically
  • Easy customization: Change tokens, update everywhere

๐Ÿ“ฑ Responsive by Default

All components are mobile-responsive out of the box:

// Sidebar collapses on mobile
<MainSidebar className="hidden md:flex" />

// Grid layouts adapt to screen size
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
  {/* Cards stack on mobile, grid on desktop */}
</div>

// Forms stack vertically on mobile
<Form className="space-y-4">
  {/* Fields stack naturally */}
</Form>

โœ… Production Checklist

Before launching, ensure:

  • Authentication flows handle all edge cases (expired tokens, network errors)
  • Forms validate on both client and server
  • Navigation works with keyboard only
  • Loading states provide feedback for all async operations
  • Error boundaries catch and display errors gracefully
  • Mobile experience is polished and touch-friendly
  • Accessibility passes WCAG AA checks

๐Ÿš€ Get Started Faster

Building these patterns from scratch takes 4-6 weeks. The SaaS Starter Kit gives you:

  • โœ… Pre-built auth flows (login, signup, password reset, OTP)
  • โœ… App shell with sidebar and topbar navigation
  • โœ… Dashboard layouts and components
  • โœ… Settings pages with forms and validation
  • โœ… WCAG AA accessibility built-in
  • โœ… Token system synced with Figma
  • โœ… Next.js + Tailwind codebase ready to customize

Explore the SaaS Starter Kit: View components

โ“ FAQ

Does it include backend/auth logic?

No. The kit focuses on frontend UI. You'll wire your own auth provider (Auth0, Clerk, Supabase, etc.) or build custom backend logic.

What about payment processing?

The kit includes billing UI components, but you'll integrate your own payment provider (Stripe, Paddle, etc.).

Can I use this for client work?

Yes, with an Agency license. Solo and Team licenses are for internal projects.

How do I customize the styling?

All components use Tailwind classes and design tokens. Modify tokens or add custom classes to match your brand.

Is it compatible with ShadCN/Radix?

Yes! The kit is built on Radix UI primitives for accessibility, similar to ShadCN.

Related Posts