HomeBuild Guides › Ship a Weekend MVP
Intermediate ⏱ 4-8 hours

Ship a Weekend MVP

Go from idea to live product in a single weekend

Cursor
CursorAI Code Editor
Next.js
Next.jsFramework
Supabase
SupabaseDatabase & Auth
Vercel
VercelDeploy
Stripe
StripePayments

What You'll Build

A deployed MVP with one core feature, user auth, payment processing, and a live URL you can share with early users.

Prerequisites

Architecture

Cursor accelerates development with AI code generation. Next.js provides the full-stack framework with App Router. Supabase handles the Postgres database and authentication. Stripe processes payments via a checkout session. Vercel deploys the entire app from a git push.

Cursor (build fast) → Next.js (frontend + API) → Supabase (DB + Auth) → Stripe (Payments) → Vercel (Deploy)

5 Steps

1
Cursor

Plan scope & set up the Next.js project with Cursor

~30 min

Define your MVP scope ruthlessly, then scaffold a Next.js project using Cursor to generate boilerplate fast.

  1. Write down your one core feature - the single thing users will pay for. Cut everything else.
  2. Open Cursor and create a new Next.js project with TypeScript and Tailwind CSS
  3. Use Cursor's AI chat to scaffold your project structure: pages, components, and lib folders
  4. Set up your environment variables file and install core dependencies
  5. Create a basic landing page with a hero section and CTA - ship the marketing page first
Terminal
npx create-next-app@latest my-mvp --typescript --tailwind --eslint --app --src-dir
cd my-mvp
npm install @supabase/supabase-js @supabase/ssr stripe
.env.local
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
STRIPE_SECRET_KEY=sk_test_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
NEXT_PUBLIC_URL=http://localhost:3000
💡
Tip: Use Cursor's Cmd+K to generate entire components from natural language. Describe what you want, review the output, and iterate. It saves hours on boilerplate.
2
Supabase

Build the core feature with Supabase database

~2 hours

Create your Supabase project, design the database schema for your one core feature, and build the UI to interact with it.

  1. Create a new Supabase project at supabase.com and copy your API credentials
  2. Design your schema in Supabase's Table Editor - keep it minimal (1-3 tables max for an MVP)
  3. Enable Row Level Security on all tables and add basic policies
  4. Create a Supabase client helper in your project for browser-side queries
  5. Build the core UI: a form to create data, a list to display it, and basic CRUD operations
src/lib/supabase.ts
import { createBrowserClient } from '@supabase/ssr'

export function createClient() {
  return createBrowserClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
  )
}
src/app/dashboard/page.tsx (example)
import { createClient } from '@/lib/supabase'

export default function Dashboard() {
  const supabase = createClient()

  async function loadItems() {
    const { data, error } = await supabase
      .from('items')
      .select('*')
      .order('created_at', { ascending: false })
    return data
  }

  // Build your UI around this data
}
💡
Tip: Start with the Supabase Table Editor to prototype your schema visually. You can always export the SQL later. Don't over-normalize - flat tables are fine for an MVP.
3
Supabase

Add authentication with Supabase Auth

~45 min

Add user signup and login so people can create accounts and access their own data.

  1. Enable email/password auth in Supabase Dashboard → Authentication → Providers
  2. Create a simple signup page with email and password fields
  3. Create a login page that redirects to the dashboard on success
  4. Add an auth callback route to handle email confirmations
  5. Add middleware to protect the dashboard route - redirect unauthenticated users to login
src/app/login/page.tsx (simplified)
'use client'
import { createClient } from '@/lib/supabase'
import { useState } from 'react'
import { useRouter } from 'next/navigation'

export default function Login() {
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const router = useRouter()
  const supabase = createClient()

  async function handleLogin() {
    const { error } = await supabase.auth.signInWithPassword({
      email, password
    })
    if (!error) router.push('/dashboard')
  }

  return (
    <form onSubmit={(e) => { e.preventDefault(); handleLogin() }}>
      <input type="email" value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email" />
      <input type="password" value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="Password" />
      <button type="submit">Log in</button>
    </form>
  )
}
💡
Tip: Add Google OAuth too - it takes 5 minutes in Supabase and dramatically increases signup conversion. Most users prefer clicking one button over filling out a form.
4
Stripe

Wire up Stripe payments

~1 hour

Add a payment flow so users can pay for your product. Use Stripe Checkout for the fastest integration.

  1. Create a Stripe account and grab your test API keys from the Stripe Dashboard
  2. Create a product and price in Stripe Dashboard (use a simple $X/month subscription or one-time price)
  3. Build an API route that creates a Stripe Checkout session and redirects the user
  4. Add a pricing section or upgrade button on your dashboard that triggers checkout
  5. Test the full flow with Stripe's test card number: 4242 4242 4242 4242
src/app/api/checkout/route.ts
import Stripe from 'stripe'
import { NextResponse } from 'next/server'

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)

export async function POST(req: Request) {
  const { priceId, userId } = await req.json()

  const session = await stripe.checkout.sessions.create({
    mode: 'subscription',
    payment_method_types: ['card'],
    line_items: [{ price: priceId, quantity: 1 }],
    success_url: `${process.env.NEXT_PUBLIC_URL}/dashboard?upgraded=true`,
    cancel_url: `${process.env.NEXT_PUBLIC_URL}/pricing`,
    metadata: { userId }
  })

  return NextResponse.json({ url: session.url })
}
💡
Tip: Skip building a webhook handler for your MVP. Just check payment status client-side after redirect. You can add webhooks later when you have real users.
⚠️
Warning: Use Stripe test mode for development. Never put live keys in .env.local until you are ready to accept real payments.
5
Vercel

Deploy to Vercel & ship

~20 min

Push to GitHub, deploy to Vercel, and share your MVP with the world.

  1. Initialize a git repo, commit your code, and push to GitHub
  2. Go to vercel.com, import your repository, and add all environment variables
  3. Deploy - Vercel auto-detects Next.js and handles the build
  4. Test the full user flow on production: land → signup → use feature → pay
  5. Share the link on Twitter, Reddit, Indie Hackers, or wherever your audience hangs out
Terminal
git init
git add .
git commit -m "Ship MVP"
git remote add origin https://github.com/you/my-mvp.git
git push -u origin main

# Or deploy directly with Vercel CLI
npx vercel --prod
💡
Tip: Add a feedback widget (even a simple mailto: link) on day one. The fastest way to improve your MVP is to talk to the people using it.
⚠️
Warning: Remember to switch Stripe to live mode and update your environment variables on Vercel before accepting real payments.

🎉 You're Done!

A deployed MVP with one core feature, user auth, payment processing, and a live URL you can share with early users.

Done for you

Want this built for you?

Get a step-by-step checklist, setup order, and the exact config for every tool in this guide. Or let me build it for you.

Get the checklist → Want this built for you?