Skip to main content

v0.dev Usage Guide for TVL Platform

Using Vercel's v0.dev AI to accelerate MVP.0 development while maintaining ADR compliance


Summary

This guide shows how to use v0.dev to generate UI components for TVL Platform's admin dashboard (MVP.0) while ensuring consistency with our architectural decisions (ADRs).

Purpose: Accelerate MVP.0 development (4-5 weeks → 1 week) without compromising code quality.

When to use: MVP.0 only (Weeks 1-10), before design team is hired.

When to stop: MVP.1+ when professional UX designer creates custom design system.


Table of Contents


Why v0.dev for MVP.0

Perfect Stack Alignment

v0.dev generates code using exactly our tech stack:

TechnologyOur ADRv0.dev DefaultAlignment
ReactADR-0015 (React 18)React 18✅ Perfect
Next.jsADR-0016 (Next.js 14 App Router)Next.js 14 App Router✅ Perfect
TailwindADR-0017 (Tailwind CSS)Tailwind CSS✅ Perfect
Shadcn UIADR-0018 (Shadcn UI)Shadcn UI components✅ Perfect
TypeScriptADR-0005 (TS strict mode)TypeScript✅ Perfect

Result: v0.dev output requires minimal changes to match our ADRs.

Speed Advantage

TaskManualWith v0.devSavings
Dashboard layout2 days10 min95% faster
Property list table1 day10 min95% faster
Booking calendar3 days20 min95% faster
Forms1 day each10 min each95% faster
Total MVP.0 UI3-4 weeks1 week75% faster

Quality Output

v0.dev generates:

  • ✅ Accessible components (WCAG 2.1 AA)
  • ✅ Responsive layouts (mobile, tablet, desktop)
  • ✅ TypeScript types
  • ✅ Production-ready code
  • ✅ Modern React patterns (hooks, Server Components)

v0.dev + ADR Alignment

How v0.dev Aligns with Our ADRs:

ADR-0015: React 18

v0.dev uses:

  • React 18.x (latest)
  • Client Components ('use client')
  • Server Components (when appropriate)
  • Modern hooks (useState, useEffect, useCallback)

No changes needed.


ADR-0016: Next.js 14 App Router

v0.dev generates:

  • App Router structure (app/ directory)
  • Server Components by default
  • Client Components with 'use client' directive
  • Route groups and layouts

No changes needed.


ADR-0017: Tailwind CSS

v0.dev uses:

  • Tailwind utility classes
  • Responsive modifiers (sm:, md:, lg:)
  • Dark mode support (dark:)
  • Custom color palette (can customize in prompts)

No changes needed.


ADR-0018: Shadcn UI

v0.dev uses Shadcn UI components:

  • Button, Input, Select, Checkbox, etc.
  • Dialog, Dropdown, Popover, Toast
  • Table, Card, Badge, Avatar
  • All components are imported from @/components/ui/

No changes needed.


ADR-0019: Zustand ⚠️ Requires Customization

Problem: v0.dev doesn't know about Zustand by default.

Solution: Add Zustand instructions to prompts:

For state management, use Zustand instead of React Context.

Example:
import { create } from 'zustand';

export const usePropertyStore = create((set) => ({
properties: [],
setProperties: (properties) => set({ properties }),
}));

When to use Zustand:

  • Global state (current organization, user session)
  • Complex state (property list filters, pagination)

When NOT to use Zustand:

  • Simple component state (use useState)
  • Server state (use TanStack Query)

ADR-0020: TanStack Query ⚠️ Requires Customization

Problem: v0.dev generates mock data, not real API calls.

Solution: Replace mock data with TanStack Query:

v0.dev generates:

const [properties, setProperties] = useState([
{ id: 1, name: "Beach House" },
{ id: 2, name: "Mountain Cabin" }
]);

Replace with TanStack Query:

import { useQuery } from '@tanstack/react-query';

const { data: properties, isLoading } = useQuery({
queryKey: ['properties'],
queryFn: async () => {
const res = await fetch('/api/v1/properties');
return res.json();
}
});

This change is required for all data fetching.


ADR-0021: React Hook Form + Zod ⚠️ Requires Customization

Problem: v0.dev generates basic forms without validation.

Solution: Add Zod validation to prompts:

For forms, use React Hook Form with Zod validation.

Example:
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import * as z from 'zod';

const schema = z.object({
name: z.string().min(1, "Name is required"),
email: z.string().email("Invalid email"),
});

const form = useForm({
resolver: zodResolver(schema),
});

This change is required for all forms.


Prompt Templates

Template 1: Dashboard Page

Create a Next.js 14 App Router dashboard page using Shadcn UI components.

Requirements:
- 4 metric cards at the top (Total Properties, Active Bookings, Revenue, Occupancy)
- Recent bookings table below (5 rows, columns: Guest, Property, Dates, Status, Actions)
- Use Shadcn UI Card, Table, Badge, Button components
- Responsive layout (stack cards on mobile)
- TypeScript with strict types
- Use 'use client' directive

Color scheme:
- Primary: Blue (Tailwind blue-600)
- Success: Green (Tailwind green-600)
- Danger: Red (Tailwind red-600)

The data should be fetched from an API (use placeholder for now).

Template 2: Data Table with Filters

Create a properties list page using Shadcn UI Table and filters.

Requirements:
- Table with columns: Property Name, Location, Units, Status, Actions
- Filters: Search by name, Status dropdown (Active/Inactive), Property Type dropdown
- Pagination (10 rows per page)
- Bulk actions: Select multiple, Activate/Deactivate, Export CSV
- Responsive (switch to cards on mobile)
- TypeScript
- Use Shadcn UI Table, Input, Select, Checkbox, Button components

Actions column should have: Edit (pencil icon), Delete (trash icon)

Use placeholder data for now (will connect to API later).

Template 3: Form with Validation

Create a property creation form using React Hook Form and Zod validation.

Fields:
- Property Name (required, min 3 chars)
- Description (required, min 10 chars)
- Address (required)
- City (required)
- State (dropdown, US states)
- Property Type (dropdown: House, Apartment, Villa)
- Units Count (number, min 1)

Requirements:
- Multi-step form (3 steps: Basic Info, Location, Units)
- Zod schema for validation
- React Hook Form with zodResolver
- Shadcn UI Form components (Input, Select, Textarea, Button)
- Show validation errors inline
- Stepper component at top
- TypeScript

On submit, log form data to console (will connect to API later).

Template 4: Modal/Dialog

Create a booking details modal using Shadcn UI Dialog.

Requirements:
- Opens when clicking "View Details" button in table
- Shows booking information:
- Guest Name
- Property Name
- Check-in / Check-out dates
- Total Price
- Status (badge)
- Created At
- Actions: Edit, Cancel Booking (confirmation dialog), Close
- Shadcn UI Dialog, Button, Badge components
- TypeScript
- Responsive

Use placeholder booking data.

Code Review Checklist

After generating code with v0.dev, review against these criteria:

1. ADR Compliance

  • Uses React 18 patterns (no class components)
  • Next.js 14 App Router (app/ directory)
  • Tailwind CSS only (no inline styles, no CSS modules)
  • Shadcn UI components (imported from @/components/ui/)
  • TypeScript with types (no any types)
  • Client Component directive when needed ('use client')

2. Replace Mock Data with TanStack Query

  • Remove hardcoded data arrays
  • Add useQuery for data fetching
  • Add loading states (isLoading, isPending)
  • Add error handling (isError, error)
  • Add query keys following pattern: ['resource', id, filters]

3. Add Form Validation (if forms)

  • Replace basic forms with React Hook Form
  • Add Zod schema for validation
  • Use zodResolver in useForm
  • Show validation errors inline

4. Multi-Tenancy

  • Add org_id to API calls (context or Zustand store)
  • Filter data by organization
  • Ensure RLS policies are enforced (backend responsibility)

5. Accessibility

  • Keyboard navigation works
  • Screen reader labels (aria-label, aria-describedby)
  • Color contrast meets WCAG AA
  • Focus indicators visible

6. Error Handling

  • API errors shown to user (use toast from Shadcn UI)
  • Network errors handled gracefully
  • Form errors displayed clearly
  • Error boundaries for component errors (React 18)

7. Code Quality

  • No console.logs (use proper logging)
  • No commented-out code
  • Meaningful variable names
  • Components under 200 lines (split if larger)
  • TypeScript strict mode compliant

Migration Strategy (MVP.0 → MVP.1)

Phase 1: MVP.0 (Weeks 1-10) - Use v0.dev

Goal: Functional UI fast, without custom design

Process:

  1. Generate components with v0.dev
  2. Review against checklist
  3. Replace mock data with TanStack Query
  4. Add form validation (Zod)
  5. Test and ship

Result: Admin dashboard that works, looks professional (Shadcn defaults)


Phase 2: MVP.1 (Weeks 11-16) - Migrate to Design System

Goal: Replace v0.dev components with custom-designed components

Process:

  1. Designer creates design system (colors, typography, custom components)
  2. Identify components to replace:
    • Keep: Generic Shadcn components (Button, Input, Table)
    • Replace: Custom components (PropertyCard, BookingCalendar, DashboardMetric)
  3. Gradual migration:
    • Replace one screen at a time
    • Start with high-traffic pages (dashboard)
    • Test thoroughly

Example Migration:

Before (v0.dev generated):

<Card>
<CardHeader>Total Properties</CardHeader>
<CardContent>{properties.length}</CardContent>
</Card>

After (custom design):

<MetricCard
title="Total Properties"
value={properties.length}
trend={+12}
icon={<HomeIcon />}
/>

Best Practices

1. Use v0.dev for Layouts, Not Logic

Good use cases:

  • Dashboard layouts
  • Table structures
  • Form layouts
  • Modal designs
  • Card grids

Bad use cases:

  • Business logic
  • API integration
  • State management
  • Authentication flows
  • Complex algorithms

Rule: v0.dev generates UI shell, you add the brains.


2. Generate One Component at a Time

Don't ask v0.dev to generate entire app:

  • ❌ "Create a complete property management dashboard"
  • ✅ "Create a property list table component"

Why: Smaller prompts = better results, easier to review.


3. Be Specific in Prompts

Vague prompt:

Create a dashboard

Specific prompt:

Create a Next.js 14 dashboard page with:
- 4 metric cards (properties, bookings, revenue, occupancy)
- Shadcn UI Card components
- Responsive grid (2 columns mobile, 4 columns desktop)
- TypeScript
- Use 'use client'

Result: Specific prompts = better output, less rework.


4. Iterate in v0.dev, Then Export

Workflow:

  1. Generate component in v0.dev
  2. Use v0.dev's iteration feature (refine with chat)
  3. Get it 80% right in v0.dev
  4. Export to codebase
  5. Finish last 20% manually (API integration, validation)

Don't: Generate → export → manually fix everything


5. Document What Was v0.dev Generated

Add comment to files:

/**
* Property List Table
*
* Generated with v0.dev on 2025-01-26
* Prompt: "Property list table with filters and pagination"
* Modified: Added TanStack Query, Zod validation
*
* TODO: Replace with custom design in MVP.1
*/

Why: Team knows which components are temporary (v0.dev) vs permanent (custom design).


FAQ

Q: Is v0.dev output production-ready?

A: 80% yes, 20% requires customization:

Production-ready:

  • Component structure
  • Responsive layouts
  • Accessibility basics
  • TypeScript types

⚠️ Requires customization:

  • API integration (replace mock data)
  • Form validation (add Zod)
  • State management (add Zustand/TanStack Query)
  • Error handling
  • Multi-tenancy (org_id filtering)

Q: Does v0.dev cost money?

A: Yes, but cheap:

  • Free: 200 generations/month
  • Paid: $20/month for unlimited (Vercel Pro)

Recommendation: Start free, upgrade if needed.


Q: Can v0.dev replace a designer?

A: No, absolutely not.

v0.dev is for:

  • ✅ Rapid prototyping (MVP.0)
  • ✅ Getting something functional fast
  • ✅ Testing ideas

Designers are for:

  • ✅ User research
  • ✅ Brand identity
  • ✅ Custom design systems
  • ✅ Conversion optimization
  • ✅ Accessibility beyond basics
  • ✅ User testing

Strategy: v0.dev for MVP.0, designer for MVP.1+


Q: What if v0.dev generates bad code?

A: Iterate in v0.dev first:

  1. Use chat to refine - "Make the table responsive"
  2. Regenerate - Try different prompts
  3. Mix and match - Take parts from different generations
  4. Manual fix - If iteration doesn't work, fix manually

If consistently bad: Your prompts need improvement (be more specific).


Q: Should I commit v0.dev code to git?

A: Yes, but:

  1. Review first (use checklist)
  2. Customize (add API integration, validation)
  3. Test (ensure it works)
  4. Document (add comment it's v0.dev generated)
  5. Commit

Don't: Copy-paste v0.dev output directly to codebase without review.


Q: How do I handle updates to Shadcn UI?

A: v0.dev uses latest Shadcn UI, so updates are automatic.

If Shadcn releases new component (e.g., Carousel), just ask v0.dev:

Use the new Shadcn Carousel component for the property image gallery

Q: Can v0.dev generate backend code?

A: No, v0.dev is frontend-only (React/Next.js).

For backend (Fastify API, database, etc.), write manually following:


When to Stop Using v0.dev

Stop after MVP.0 (Week 10)

Reasons:

  1. Designer hired - Professional design system available
  2. User feedback - Know what actually matters to users
  3. Brand identity - Need custom design, not generic Shadcn
  4. Conversion optimization - Designer can A/B test, optimize flows
  5. Code ownership - Team understands custom components better

Exception: Can still use v0.dev for rapid prototyping/testing ideas.


Example Workflow

Building Property List Page:

Step 1: Generate with v0.dev

Prompt:

Create a Next.js 14 property list page with:
- Table: Property Name, Location, Units, Status, Actions
- Filters: Search, Status dropdown, Property Type dropdown
- Pagination
- Shadcn UI components
- TypeScript

Step 2: Export Code

Copy generated code to /app/properties/page.tsx

Step 3: Review (Checklist)

  • ✅ Shadcn components used
  • ✅ TypeScript types present
  • ✅ Responsive layout
  • ⚠️ Mock data needs replacement
  • ⚠️ No loading/error states

Step 4: Add TanStack Query

const { data: properties, isLoading, isError } = useQuery({
queryKey: ['properties', filters],
queryFn: async () => {
const res = await fetch(`/api/v1/properties?${new URLSearchParams(filters)}`);
if (!res.ok) throw new Error('Failed to fetch properties');
return res.json();
}
});

if (isLoading) return <LoadingSpinner />;
if (isError) return <ErrorMessage />;

Step 5: Add Multi-Tenancy

const { orgId } = useAuth(); // From Zustand store

const { data: properties } = useQuery({
queryKey: ['properties', orgId, filters],
queryFn: async () => {
const res = await fetch(`/api/v1/properties`, {
headers: {
'X-Organization-Id': orgId, // RLS context
}
});
return res.json();
}
});

Step 6: Test

  • Loads data from API
  • Filters work
  • Pagination works
  • Actions (edit, delete) work
  • Responsive on mobile
  • Keyboard navigation works

Step 7: Commit

git add app/properties/page.tsx
git commit -m "Add property list page (generated with v0.dev, customized with TanStack Query)"

Summary

Use v0.dev for MVP.0 because:

  1. Aligns perfectly with our stack (React 18, Next.js 14, Shadcn UI, Tailwind)
  2. Saves 3-4 weeks of development time
  3. Produces production-ready code (with minor customizations)
  4. Allows focus on backend/API development
  5. Good enough for MVP.0 (before users, before designer)

⚠️ Customize v0.dev output:

  1. Replace mock data with TanStack Query
  2. Add form validation (Zod)
  3. Add state management (Zustand for global state)
  4. Add multi-tenancy (org_id filtering)
  5. Add error handling and loading states

🎯 Stop using v0.dev after MVP.0:

  1. Hire designer before MVP.1 (Week 10)
  2. Designer creates custom design system
  3. Gradually migrate v0.dev components to custom components
  4. Keep generic Shadcn components (Button, Input, etc.)

📋 Always:

  • Use the prompt templates
  • Follow the code review checklist
  • Document what was v0.dev generated
  • Test before committing


Last Updated: 2025-01-26 Maintained By: Frontend Team Status: Active for MVP.0, deprecated after MVP.1