SaaS Starter Template
A production-ready SaaS application with authentication, database, team management, and a full dashboard. Scaffold it in one command and deploy in 5 minutes.
varitykit init my-appWhat’s Included
Section titled “What’s Included”| Page | Route | Description |
|---|---|---|
| Landing | / | Marketing page with features, testimonials, and CTA |
| Login | /login | Email, Google, Twitter, Discord, GitHub |
| Dashboard | /dashboard | Overview with key metrics |
| Projects | /dashboard/projects | Full CRUD with status tracking |
| Tasks | /dashboard/tasks | Task management with priorities and assignments |
| Team | /dashboard/team | Team member management with roles |
| Settings | /dashboard/settings | App configuration |
Built-in Features
Section titled “Built-in Features”- Authentication — Built-in login (email magic link + social providers)
- Database — Typed collections with CRUD operations and optimistic updates
- Dashboard layout — Responsive sidebar with mobile hamburger menu
- Command palette — Cmd+K / Ctrl+K to search projects, tasks, and team
- Confirmation dialogs — Safe delete operations
- CSS variables — Easy brand customization via
globals.css - Landing page — Animated sections, social proof, testimonials
Data Models
Section titled “Data Models”The template includes three data models:
export interface Project { id?: string; name: string; description: string; status: 'active' | 'paused' | 'completed'; owner: string; members: string[]; dueDate: string; createdAt: string;}
export interface Task { id?: string; projectId: string; title: string; description?: string; status: 'todo' | 'in_progress' | 'done'; priority: 'low' | 'medium' | 'high'; assignee?: string; dueDate?: string; createdAt: string;}
export interface TeamMember { id?: string; name: string; email: string; role: 'admin' | 'member' | 'viewer'; avatarUrl?: string; joinedAt: string;}Directory Structure
Section titled “Directory Structure”src/├── app/│ ├── page.tsx # Landing page│ ├── layout.tsx # Root layout (auth provider)│ ├── login/page.tsx # Login page│ └── dashboard/│ ├── layout.tsx # Dashboard layout (sidebar + mobile nav)│ ├── page.tsx # Dashboard home│ ├── projects/page.tsx # Projects CRUD│ ├── tasks/page.tsx # Tasks CRUD│ ├── team/page.tsx # Team management│ ├── settings/page.tsx # Settings│ └── components/ui/ # Command palette, dialogs├── lib/│ ├── varity.ts # SDK import (1 line)│ ├── database.ts # Collection helpers│ ├── hooks.ts # React hooks (useProjects, useTasks, useTeam)│ ├── constants.ts # App name, navigation items│ └── utils.ts # CSV export, helpers├── types/│ └── index.ts # TypeScript interfacesKey Patterns
Section titled “Key Patterns”Database Pattern
Section titled “Database Pattern”Every data model follows the same 3-file pattern:
types/index.ts → lib/database.ts → lib/hooks.ts → app/dashboard/page.tsx1. Type — Define a TypeScript interface
2. Collection — Create a typed accessor: db.collection<T>('name')
3. Hook — Build a React hook with loading/error states and optimistic updates
4. Page — Use the hook in a component
Hook Pattern
Section titled “Hook Pattern”All hooks return the same interface:
interface UseCollectionReturn<T> { data: T[]; loading: boolean; error: string | null; create: (item: any) => Promise<void>; update: (id: string, updates: Partial<T>) => Promise<void>; remove: (id: string) => Promise<void>; refresh: () => Promise<void>;}Authentication Pattern
Section titled “Authentication Pattern”// Root layout sets up auth provider<PrivyStack appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID}> {children}</PrivyStack>
// Dashboard layout protects all dashboard routes<PrivyProtectedRoute>{children}</PrivyProtectedRoute>
// Access user info in any componentconst { user, authenticated, logout } = usePrivy();Customization Guide
Section titled “Customization Guide”Change Branding
Section titled “Change Branding”-
App name — Edit
APP_NAMEinsrc/lib/constants.tsexport const APP_NAME = 'YourAppName'; -
Colors — Edit CSS variables in
src/app/globals.css:root {--color-primary-500: #3b82f6; /* Your primary color */--color-primary-600: #2563eb;--color-primary-700: #1d4ed8;}Four color presets are documented in the file: Blue (default), Purple, Green, Orange.
-
Logo — Replace the logo file in
public/
Modify Navigation
Section titled “Modify Navigation”Edit NAVIGATION_ITEMS in src/lib/constants.ts:
export const NAVIGATION_ITEMS = [ { label: 'Dashboard', icon: 'dashboard', path: '/dashboard' }, { label: 'Clients', icon: 'people', path: '/dashboard/clients' }, { label: 'Invoices', icon: 'list', path: '/dashboard/invoices' }, { label: 'Settings', icon: 'settings', path: '/dashboard/settings' },];Available icons: dashboard, folder, list, people, settings
Add a New Data Model
Section titled “Add a New Data Model”-
Define the interface in
src/types/index.tsexport interface Invoice {id?: string;clientId: string;amount: number;status: 'draft' | 'sent' | 'paid';dueDate: string;createdAt: string;} -
Add collection helper in
src/lib/database.tsimport type { Invoice } from '../types';export const invoices = () => db.collection<Invoice>('invoices'); -
Create hook in
src/lib/hooks.tsCopy the
useProjectsfunction, rename touseInvoices, and update the type and collection reference. -
Create page at
src/app/dashboard/invoices/page.tsx -
Add to navigation in
constants.ts
For a complete walkthrough, see the Add a CRUD Feature tutorial.
Add a New Page (No Database)
Section titled “Add a New Page (No Database)”For pages that don’t need data (e.g., documentation, about):
- Create
src/app/dashboard/about/page.tsx - Add to
NAVIGATION_ITEMSinconstants.ts
'use client';
export default function AboutPage() { return ( <div style={{ padding: '2rem' }}> <h1>About</h1> <p>Your content here.</p> </div> );}Configuration
Section titled “Configuration”Environment Variables
Section titled “Environment Variables”# Auth (optional for development — shared creds used automatically)NEXT_PUBLIC_PRIVY_APP_ID=
# Your app ID (assigned after first deploy)NEXT_PUBLIC_VARITY_APP_ID=Next.js Config
Section titled “Next.js Config”The template uses output: 'export' for static hosting:
const nextConfig = { output: 'export', typescript: { ignoreBuildErrors: true, }, images: { unoptimized: true, },};Deploy
Section titled “Deploy”npm run buildvaritykit app deployTo submit to the App Store:
varitykit app deploy --submit-to-storeNext Steps
Section titled “Next Steps”- Build & Deploy Tutorial — Step-by-step deployment guide
- Customize the Template — Branding and modifications
- Add a CRUD Feature — Add a new data model end-to-end
- Database Quick Start — Database API deep dive