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

Grok Best Practices for Academic Research and Literature Discovery: Leveraging X/Twitter for Scholarly Intelligence Best Practices Grok Best Practices for Content Strategy: Identify Trending Topics Before They Peak and Create Content That Captures Demand Best Practices Grok Case Study: How a DTC Beauty Brand Used Real-Time Social Listening to Save Their Product Launch Case Study Grok Case Study: How a Pharma Company Tracked Patient Sentiment During a Drug Launch and Caught a Safety Signal 48 Hours Before the FDA Case Study Grok Case Study: How a Disaster Relief Nonprofit Used Real-Time X/Twitter Monitoring to Coordinate Emergency Response 3x Faster Case Study Grok Case Study: How a Political Campaign Used X/Twitter Sentiment Analysis to Reshape Messaging and Win a Swing District Case Study How to Use Grok for Competitive Intelligence: Track Product Launches, Pricing Changes, and Market Positioning in Real Time How-To Grok vs Perplexity vs ChatGPT Search for Real-Time Information: Which AI Search Tool Is Most Accurate in 2026? Comparison How to Use Grok for Crisis Communication Monitoring: Detect, Assess, and Respond to PR Emergencies in Real Time How-To How to Use Grok for Product Improvement: Extract Customer Feedback Signals from X/Twitter That Your Support Team Misses How-To How to Use Grok for Conference Live Monitoring: Extract Event Insights and Identify Networking Opportunities in Real Time How-To How to Use Grok for Influencer Marketing: Discover, Vet, and Track Influencer Partnerships Using Real X/Twitter Data How-To How to Use Grok for Job Market Analysis: Track Industry Hiring Trends, Layoff Signals, and Salary Discussions on X/Twitter How-To How to Use Grok for Investor Relations: Track Earnings Sentiment, Analyst Reactions, and Shareholder Concerns in Real Time How-To How to Use Grok for Recruitment and Talent Intelligence: Identifying Hiring Signals from X/Twitter Data How-To How to Use Grok for Startup Fundraising Intelligence: Track Investor Sentiment, VC Activity, and Funding Trends on X/Twitter How-To How to Use Grok for Regulatory Compliance Monitoring: Real-Time Policy Tracking Across Industries How-To NotebookLM Best Practices for Financial Analysts: Due Diligence, Investment Research & Risk Factor Analysis Across SEC Filings Best Practices NotebookLM Best Practices for Teachers: Build Curriculum-Aligned Lesson Plans, Study Guides, and Assessment Materials from Your Own Resources Best Practices NotebookLM Case Study: How an Insurance Company Built a Claims Processing Training System That Cut Errors by 35% Case Study