How to Build a Multi-Page SaaS Dashboard in v0 with Shadcn UI, API Routes & Vercel Deployment

How to Build a Multi-Page SaaS Dashboard in v0 with Shadcn UI, API Routes & Vercel Deployment

v0 by Vercel is an AI-powered code generation tool that produces production-ready React components built on Next.js and Shadcn UI. In this guide, you will build a complete multi-page SaaS dashboard from scratch—using v0 prompts for UI generation, Next.js API route handlers for backend logic, and one-click Vercel deployment to go live.

Prerequisites

  • A v0.dev account (free tier works for getting started)
  • Node.js 18+ and npm installed locally
  • A GitHub account
  • A Vercel account linked to your GitHub

Step 1: Scaffold the Dashboard Layout in v0

Open v0.dev and enter a detailed prompt to generate your dashboard shell. The more specific your prompt, the better the output.

Prompt in v0: “Create a SaaS dashboard layout with a collapsible sidebar navigation containing links for Dashboard, Analytics, Users, Billing, and Settings. Include a top header bar with a user avatar dropdown, notification bell, and search input. Use Shadcn UI components: Sheet for mobile sidebar, DropdownMenu for the avatar, and Input for search. The main content area should accept children for page routing.”

v0 will generate a fully functional layout component. Click **"Add to Codebase"** or copy the code. The output uses the App Router structure by default.

Step 2: Set Up Your Local Project

Initialize your Next.js project locally and install Shadcn UI:

npx create-next-app@latest saas-dashboard —typescript —tailwind —eslint —app —src-dir cd saas-dashboard npx shadcn@latest init

When prompted during Shadcn init, choose your preferred style and color scheme. Then install the specific components your dashboard needs:

npx shadcn@latest add button card table tabs input dropdown-menu sheet avatar badge dialog select separator chart

Paste the layout code from v0 into src/app/layout.tsx or create a dedicated src/components/dashboard-layout.tsx component.

Step 3: Generate Individual Dashboard Pages

Return to v0 and generate each page. Here are effective prompts for key pages:

Analytics Page

Prompt in v0: “Build an analytics dashboard page with: a row of 4 KPI stat cards (Total Revenue, Active Users, Conversion Rate, MRR) using Shadcn Card, a large area chart showing revenue over 12 months using Recharts, and a data table of recent transactions with columns for ID, Customer, Amount, Status, and Date. Use Shadcn Table with sortable headers.”

Users Management Page

Prompt in v0:
"Create a user management page with a Shadcn DataTable showing columns:
Name, Email, Role (Admin/Member/Viewer), Status (Active/Inactive), and
Joined Date. Add a search/filter bar at the top, pagination at the bottom,
and an 'Add User' button that opens a Shadcn Dialog with a form."

Save each generated page into the App Router structure:

src/app/(dashboard)/analytics/page.tsx src/app/(dashboard)/users/page.tsx src/app/(dashboard)/billing/page.tsx src/app/(dashboard)/settings/page.tsx

Step 4: Create API Route Handlers

Next.js App Router uses route.ts files for API endpoints. Create handlers that your dashboard pages will consume:

// src/app/api/analytics/route.ts import { NextResponse } from ‘next/server’;

export async function GET() { // Replace with your actual database query const stats = { totalRevenue: 48250, activeUsers: 2340, conversionRate: 3.2, mrr: 12400, revenueHistory: [ { month: ‘Jan’, revenue: 8200 }, { month: ‘Feb’, revenue: 9100 }, { month: ‘Mar’, revenue: 12400 }, ], }; return NextResponse.json(stats); }

// src/app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';

export async function GET(request: NextRequest) {
  const { searchParams } = new URL(request.url);
  const page = parseInt(searchParams.get('page') || '1');
  const limit = parseInt(searchParams.get('limit') || '10');

  // Replace with your database call
  const users = [
    { id: '1', name: 'Jane Cooper', email: 'jane@example.com', role: 'Admin', status: 'Active' },
    { id: '2', name: 'Alex Morgan', email: 'alex@example.com', role: 'Member', status: 'Active' },
  ];

  return NextResponse.json({
    users,
    pagination: { page, limit, total: 47 },
  });
}

export async function POST(request: NextRequest) {
  const body = await request.json();
  // Validate and save to database
  return NextResponse.json({ success: true, user: body }, { status: 201 });
}

Step 5: Connect Frontend to API Routes

Use React hooks or server components to fetch data from your API routes:

// src/app/(dashboard)/analytics/page.tsx export default async function AnalyticsPage() { const res = await fetch(${process.env.NEXT_PUBLIC_APP_URL}/api/analytics, { cache: ‘no-store’, }); const data = await res.json();

return (

Analytics

<StatCard title=“Total Revenue” value={$${data.totalRevenue.toLocaleString()}} /> <StatCard title=“Conversion Rate” value={${data.conversionRate}%} /> <StatCard title=“MRR” value={$${data.mrr.toLocaleString()}} />

); }

For environment variables, create a .env.local file:

NEXT_PUBLIC_APP_URL=http://localhost:3000 DATABASE_URL=your_database_connection_string API_SECRET_KEY=YOUR_API_KEY

Step 6: One-Click Vercel Deployment

Push your project to GitHub, then deploy:

git init git add . git commit -m “SaaS dashboard with Shadcn UI” git remote add origin https://github.com/yourusername/saas-dashboard.git git push -u origin main

  • Go to vercel.com/new
  • Import your GitHub repository
  • Vercel auto-detects the Next.js framework
  • Add your environment variables (DATABASE_URL, API_SECRET_KEY) in the Vercel dashboard
  • Click Deploy

Alternatively, use the Vercel CLI:

npm i -g vercel vercel —prod

Pro Tips for Power Users

  • Iterate with v0 Chat: After the initial generation, use v0’s chat to refine components. For example: “Add a dark mode toggle to the header” or “Make the sidebar persist collapsed state in localStorage.”
  • Use Route Groups: Wrap your dashboard pages in an (dashboard) route group with a shared layout so the sidebar and header render once, not per page.
  • Parallel Routes for Modals: Use Next.js parallel routes (@modal) so dialogs like “Add User” get their own URL, enabling shareable deep links.
  • Middleware for Auth: Add a middleware.ts at your project root to protect all /dashboard routes before they render.
  • Streaming with Suspense: Wrap slow data-fetching sections in with Shadcn Skeleton components as fallbacks for instant perceived performance.
  • Prompt Chaining: Generate a base component in v0, then immediately follow up: “Now add loading states, error handling, and empty states to this table.”

Troubleshooting Common Errors

ErrorCauseSolution
Module not found: @/components/ui/buttonShadcn component not installedRun npx shadcn@latest add button for the missing component
TypeError: fetch failed in server componentsNEXT_PUBLIC_APP_URL not set or incorrectVerify the env variable in .env.local and Vercel dashboard. On Vercel, use VERCEL_URL dynamically.
Sidebar navigation does not update active stateNot using usePathname() hookImport usePathname from next/navigation and compare against each nav link's href
API route returns 405 Method Not AllowedWrong HTTP method or file named page.tsx instead of route.tsEnsure API files are named route.ts and export the correct method (GET, POST, etc.)
Hydration mismatch warningsClient-only code (localStorage, window) running on serverWrap client-dependent logic in useEffect or add 'use client' directive
Vercel build fails on type errorsv0-generated code may have minor type issuesRun npx tsc --noEmit locally before pushing; fix flagged types

Frequently Asked Questions

Can I use v0 to generate entire multi-page applications or only single components?

v0 generates individual components and pages, not full multi-page apps in a single prompt. The recommended workflow is to generate each page separately—dashboard overview, analytics, users, settings—then assemble them into your Next.js App Router structure locally. Use a shared layout component (also generated via v0) to ensure consistent navigation and styling across all pages. This modular approach actually produces better results because each prompt can be specific and detailed.

How do I add authentication to protect the dashboard routes?

Create a middleware.ts file in your project root that checks for a valid session or JWT token on all /dashboard routes. Popular options include NextAuth.js, Clerk, or Supabase Auth. In your middleware.ts, redirect unauthenticated users to a login page. You can also prompt v0 to generate a login page: “Create a login page with email and password fields, a Google OAuth button, and a link to sign up, using Shadcn Card, Input, Button, and Separator.” Then wire the form to your chosen auth provider’s API.

Is the code generated by v0 production-ready, or does it need significant refactoring?

v0 output is high-quality and uses well-structured React with Shadcn UI and Tailwind CSS, making it a strong starting point. However, for production you should review and adjust several things: replace hardcoded mock data with real API calls, add proper error handling and loading states, implement input validation, verify accessibility (keyboard navigation, ARIA labels), and ensure TypeScript types are strict. The generated code typically needs 15–25% refinement for production use—far less than building from scratch, but not zero.

Explore More Tools

Antigravity AI Content Pipeline Automation Guide: Google Docs to WordPress Publishing Workflow Guide Bolt.new Case Study: Marketing Agency Built 5 Client Dashboards in One Day Case Study Bolt.new Best Practices: Rapid Full-Stack App Generation from Natural Language Prompts Best Practices ChatGPT Advanced Data Analysis (Code Interpreter) Complete Guide: Upload, Analyze, Visualize Guide ChatGPT Custom GPTs Advanced Guide: Actions, API Integration, and Knowledge Base Configuration Guide ChatGPT Voice Mode Guide: Build Voice-First Customer Service and Internal Workflows Guide Claude API Production Chatbot Guide: System Prompt Architecture for Reliable AI Assistants Guide Claude Artifacts Best Practices: Create Interactive Dashboards, Documents, and Code Previews Best Practices Claude Code Hooks Guide: Automate Custom Workflows with Pre and Post Execution Hooks Guide Claude MCP Server Setup Guide: Build Custom Tool Integrations for Claude Code and Claude Desktop Guide Cursor Composer Complete Guide: Multi-File Editing, Inline Diffs, and Agent Mode Guide Cursor Case Study: Solo Founder Built a Next.js SaaS MVP in 2 Weeks with AI-Assisted Development Case Study Cursor Rules Advanced Guide: Project-Specific AI Configuration and Team Coding Standards Guide Devin AI Team Workflow Integration Best Practices: Slack, GitHub, and Code Review Automation Best Practices Devin Case Study: Automated Dependency Upgrade Across 500-Package Python Monorepo Case Study ElevenLabs Case Study: EdTech Startup Localized 200 Course Hours to 8 Languages in 6 Weeks Case Study ElevenLabs Multilingual Dubbing Guide: Automated Video Localization Workflow for Global Content Guide ElevenLabs Voice Design Complete Guide: Create Consistent Character Voices for Games, Podcasts, and Apps Guide Gemini 2.5 Pro vs Claude Sonnet 4 vs GPT-4o: AI Code Generation Comparison 2026 Comparison Gemini API Multimodal Developer Guide: Image, Video, and Document Analysis with Code Examples Guide