Vibecoding is a new software development paradigm where the programmer guides an AI agent through natural language instructions, letting the artificial intelligence write the actual code. The term was coined by Andrej Karpathy (OpenAI co-founder and former Director of AI at Tesla) in a famous tweet from February 2025: "There's a new kind of coding I call vibecoding, where you fully give in to the vibes, embrace the exponentials, and forget that the code even exists."
In this article, we'll see how to build a complete, working demo using Claude Code as an AI agent, Supabase as a backend (database, authentication, API), and Vercel for deployment — all leveraging exclusively the free tiers of these services.
1. What Is Vibecoding and Why It's Revolutionary
Vibecoding represents a fundamental paradigm shift in software development. Instead of writing code line by line, the developer:
- Describes what they want in natural language.
- The AI agent generates the complete code.
- The developer reviews, tests, and iterates.
Why It Works
- Speed: a project that would take days can be built in hours.
- Accessibility: even non-expert developers can build working products.
- Rapid iteration: you can test ideas and pivot much faster.
- Product focus: you concentrate on the what instead of the how.
When to Use Vibecoding
Vibecoding is perfect for:
- Demos and MVPs: quickly building a prototype to validate an idea.
- Hackathons: creating a working product in just a few hours.
- Side projects: exploring new technologies without investing weeks.
- Proof of Concept: demonstrating technical feasibility to stakeholders or investors.
Warning: Vibecoding is excellent for demos and prototypes. For production-grade applications with high security and scalability requirements, a thorough review of the generated code is still essential.
2. The Tech Stack: Claude Code + Supabase + Vercel
Claude Code
Claude Code is Anthropic's AI coding agent. It works directly in your terminal and can:
- Read and understand the entire codebase.
- Create, modify, and delete files.
- Execute terminal commands.
- Interact with APIs and external services.
- Manage versioning with Git.
- Autonomously iterate on errors and bugs.
# Install Claude Code npm install -g @anthropic-ai/claude-code # Start in a project directory cd my-project claude
Supabase (Free Tier)
Supabase is an open-source Firebase alternative that offers:
- PostgreSQL Database: a complete relational database.
- Authentication: login with email, Google, GitHub, etc.
- REST and Realtime APIs: automatically generated from your schema.
- Storage: for files and images.
- Edge Functions: serverless functions.
The free tier includes:
| Resource | Free Limit | |----------|-----------| | Database | 500 MB | | Storage | 1 GB | | Bandwidth | 5 GB | | Edge Function invocations | 500K/month | | Authenticated users | Unlimited | | Projects | 2 active projects |
Vercel (Free Tier)
Vercel is the perfect deployment platform for Next.js applications:
- Automatic deployment from GitHub.
- Preview deployments for every branch and PR.
- Global CDN for optimal performance.
- Serverless Functions included.
- Basic analytics for free.
The free tier includes:
| Resource | Free Limit | |----------|-----------| | Bandwidth | 100 GB/month | | Serverless Function execution | 100 GB-hours/month | | Builds | 6,000 minutes/month | | Projects | Unlimited | | Deployments | Unlimited |
3. Initial Setup: Preparing the Environment
Prerequisites
Before starting, make sure you have:
- Node.js 18+ installed.
- Git configured.
- A GitHub account.
- A Supabase account (free at supabase.com).
- A Vercel account (free at vercel.com).
- Claude Code installed (
npm install -g @anthropic-ai/claude-code).
Step 1: Create the Project
Open the terminal and start Claude Code:
mkdir my-demo-app && cd my-demo-app claude
Now you can start giving Claude Code instructions in natural language:
You: Create a Next.js 15 project with App Router, TypeScript, Tailwind CSS,
and shadcn/ui. Also initialize a Git repository.
Claude Code will automatically execute:
npx create-next-app@latest . --typescript --tailwind --eslint --app --src-dir npx shadcn@latest init git init && git add . && git commit -m "Initial commit"
Step 2: Configure Supabase
- Go to supabase.com and create a new project.
- Note the Project URL and anon key from Settings > API.
- Go back to the terminal with Claude Code:
You: Add Supabase to the project. Create a .env.local file with the variables
NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY. Configure the
Supabase client with SSR support for Next.js App Router.
Claude Code will create the complete configuration:
// src/lib/supabase/client.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/lib/supabase/server.ts import { createServerClient } from '@supabase/ssr'; import { cookies } from 'next/headers'; export async function createClient() { const cookieStore = await cookies(); return createServerClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { cookies: { getAll() { return cookieStore.getAll(); }, setAll(cookiesToSet) { cookiesToSet.forEach(({ name, value, options }) => cookieStore.set(name, value, options) ); }, }, } ); }
4. Building the Demo: A Task Management App
Let's build a concrete demo: a task management app with authentication, full CRUD, and a modern interface.
Define the Database Schema
Give Claude Code instructions to create the schema:
You: Create a SQL migration for Supabase with the following tables:
1. profiles: id (uuid, FK to auth.users), username (text), avatar_url (text),
created_at
2. projects: id (uuid), name (text), description (text), owner_id (uuid, FK
to profiles), created_at
3. tasks: id (uuid), title (text), description (text), status (enum:
todo/in_progress/done), priority (enum: low/medium/high), project_id (uuid,
FK to projects), assigned_to (uuid, FK to profiles), due_date (timestamp),
created_at, updated_at
Enable Row Level Security on all tables and create appropriate policies.
Claude Code will generate a complete migration:
-- Create enum types CREATE TYPE task_status AS ENUM ('todo', 'in_progress', 'done'); CREATE TYPE task_priority AS ENUM ('low', 'medium', 'high'); -- Profiles table CREATE TABLE profiles ( id UUID REFERENCES auth.users ON DELETE CASCADE PRIMARY KEY, username TEXT UNIQUE, avatar_url TEXT, created_at TIMESTAMPTZ DEFAULT NOW() ); -- Projects table CREATE TABLE projects ( id UUID DEFAULT gen_random_uuid() PRIMARY KEY, name TEXT NOT NULL, description TEXT, owner_id UUID REFERENCES profiles(id) ON DELETE CASCADE NOT NULL, created_at TIMESTAMPTZ DEFAULT NOW() ); -- Tasks table CREATE TABLE tasks ( id UUID DEFAULT gen_random_uuid() PRIMARY KEY, title TEXT NOT NULL, description TEXT, status task_status DEFAULT 'todo', priority task_priority DEFAULT 'medium', project_id UUID REFERENCES projects(id) ON DELETE CASCADE NOT NULL, assigned_to UUID REFERENCES profiles(id), due_date TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Enable RLS ALTER TABLE profiles ENABLE ROW LEVEL SECURITY; ALTER TABLE projects ENABLE ROW LEVEL SECURITY; ALTER TABLE tasks ENABLE ROW LEVEL SECURITY; -- Profiles policies CREATE POLICY "Users can view own profile" ON profiles FOR SELECT USING (auth.uid() = id); CREATE POLICY "Users can update own profile" ON profiles FOR UPDATE USING (auth.uid() = id); -- Projects policies CREATE POLICY "Users can view own projects" ON projects FOR SELECT USING (auth.uid() = owner_id); CREATE POLICY "Users can create projects" ON projects FOR INSERT WITH CHECK (auth.uid() = owner_id); CREATE POLICY "Users can update own projects" ON projects FOR UPDATE USING (auth.uid() = owner_id); CREATE POLICY "Users can delete own projects" ON projects FOR DELETE USING (auth.uid() = owner_id); -- Tasks policies CREATE POLICY "Users can view tasks in their projects" ON tasks FOR SELECT USING ( project_id IN (SELECT id FROM projects WHERE owner_id = auth.uid()) ); CREATE POLICY "Users can create tasks in their projects" ON tasks FOR INSERT WITH CHECK ( project_id IN (SELECT id FROM projects WHERE owner_id = auth.uid()) ); CREATE POLICY "Users can update tasks in their projects" ON tasks FOR UPDATE USING ( project_id IN (SELECT id FROM projects WHERE owner_id = auth.uid()) ); CREATE POLICY "Users can delete tasks in their projects" ON tasks FOR DELETE USING ( project_id IN (SELECT id FROM projects WHERE owner_id = auth.uid()) );
You can run this migration directly from the Supabase dashboard (SQL Editor) or via the CLI.
Generate TypeScript Types
You: Generate TypeScript types from the Supabase database and save them to src/types/database.ts
npx supabase gen types typescript --project-id YOUR_PROJECT_ID > src/types/database.ts
Build the User Interface
Now comes the most powerful part of vibecoding. Give Claude Code high-level instructions:
You: Create a dashboard page for the task management app with:
1. Sidebar with navigation between projects
2. Kanban view with 3 columns (Todo, In Progress, Done) with drag & drop
3. Modal to create/edit tasks
4. Header with user avatar and logout
5. Modern design with shadcn/ui and Tailwind
Use data from Supabase with React Server Components where possible
and Client Components only where interactivity is needed.
Claude Code will build the entire interface, component by component.
Add Authentication
You: Add a complete authentication system with:
1. Login page with email/password and GitHub login
2. Registration page
3. Middleware to protect authenticated routes
4. Automatic redirect for unauthenticated users
5. Automatic profile creation after registration
Claude Code will configure Next.js middleware and auth pages:
// src/middleware.ts import { createServerClient } from '@supabase/ssr'; import { NextResponse, type NextRequest } from 'next/server'; export async function middleware(request: NextRequest) { let supabaseResponse = NextResponse.next({ request }); const supabase = createServerClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { cookies: { getAll() { return request.cookies.getAll(); }, setAll(cookiesToSet) { cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value) ); supabaseResponse = NextResponse.next({ request }); cookiesToSet.forEach(({ name, value, options }) => supabaseResponse.cookies.set(name, value, options) ); }, }, } ); const { data: { user } } = await supabase.auth.getUser(); if (!user && !request.nextUrl.pathname.startsWith('/auth')) { const url = request.nextUrl.clone(); url.pathname = '/auth/login'; return NextResponse.redirect(url); } return supabaseResponse; } export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico|auth).*)'], };
5. Advanced Vibecoding Patterns
Iterative Prompting
The secret to effective vibecoding is iteration. Don't try to describe everything in a single prompt. Proceed in steps:
Step 1: "Create the base layout with header and sidebar"
Step 2: "Add the project list in the sidebar with a button to create new ones"
Step 3: "Create the Kanban view in the main area"
Step 4: "Add drag & drop between columns"
Step 5: "Implement the modal to create new tasks"
Step 6: "Add toast notifications for user feedback"
Tip: The more specific and contextualized the prompt, the better the result. Claude Code has access to the entire codebase, so it can integrate new features coherently.
Error Handling
When something doesn't work (and it will), you can simply say:
You: I'm getting this error in the console: "TypeError: Cannot read property
'map' of undefined" in the TaskList component. Fix it.
Claude Code will analyze the code, identify the problem, and fix it.
Refactoring with AI
You: The Dashboard component has become too large. Split it into smaller,
reusable components while maintaining the same functionality.
Testing
You: Add tests with Vitest for utility functions and Playwright tests for
the authentication and task creation flow.
6. Deploy to Vercel: From Code to the World
Step 1: Push to GitHub
You: Create an appropriate .gitignore, commit everything, and push to a new
GitHub repository called "my-demo-app".
git add . git commit -m "feat: complete task management demo" gh repo create my-demo-app --public --push --source=.
Step 2: Connect Vercel
- Go to vercel.com and click "Add New Project."
- Import the GitHub repository you just created.
- Add environment variables:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEY
- Click "Deploy."
Step 3: Configure a Custom Domain (Optional)
Vercel provides a free URL like my-demo-app.vercel.app. For a custom domain:
You: Add the configuration for a custom domain in vercel.json
Preview Deployments
Every time you open a Pull Request on GitHub, Vercel will automatically create a preview deployment with a unique URL. Perfect for showing changes before merging.
7. Optimizations for Your Demo
Performance
You: Optimize the app's performance:
1. Add loading states with Suspense and skeletons
2. Implement caching with Next.js unstable_cache
3. Optimize images with next/image
4. Add SEO metadata for each page
Realtime with Supabase
A feature that always impresses in demos is realtime:
You: Add realtime synchronization for tasks using Supabase Realtime.
When a user updates a task, all other users should see the change
in real time without refreshing.
'use client'; import { useEffect, useState } from 'react'; import { createClient } from '@/lib/supabase/client'; import type { Task } from '@/types/database'; export function useRealtimeTasks(projectId: string) { const [tasks, setTasks] = useState<Task[]>([]); const supabase = createClient(); useEffect(() => { const channel = supabase .channel('tasks-changes') .on( 'postgres_changes', { event: '*', schema: 'public', table: 'tasks', filter: `project_id=eq.${projectId}`, }, (payload) => { if (payload.eventType === 'INSERT') { setTasks((prev) => [...prev, payload.new as Task]); } else if (payload.eventType === 'UPDATE') { setTasks((prev) => prev.map((t) => t.id === payload.new.id ? (payload.new as Task) : t ) ); } else if (payload.eventType === 'DELETE') { setTasks((prev) => prev.filter((t) => t.id !== payload.old.id) ); } } ) .subscribe(); return () => { supabase.removeChannel(channel); }; }, [projectId, supabase]); return tasks; }
Dark Mode
You: Add dark mode support with a toggle in the header.
Use Tailwind dark classes and save the preference in localStorage.
8. Best Practices for Effective Vibecoding
1. Be Specific in Your Prompts
❌ "Make a nice page"
✅ "Create a landing page with a hero section with a purple-blue gradient,
a features section with 3 cards with icons, and an orange CTA button"
2. Provide Context
❌ "Add authentication"
✅ "Add authentication with Supabase Auth. The project uses Next.js 15 App
Router with TypeScript. I want email/password login and OAuth with GitHub.
Use the SSR pattern with @supabase/ssr"
3. Iterate in Small Steps
Don't try to build everything in a single prompt. Proceed incrementally:
- Base layout
- One feature at a time
- Styling and polish
- Error handling
- Testing
4. Review the Generated Code
Vibecoding doesn't mean not reading the code. Always review:
- Security: RLS policies, input validation, data sanitization.
- Performance: N+1 queries, unnecessarily client-side components.
- Best practices: project structure, naming conventions.
5. Use Git Strategically
You: Commit the changes with a descriptive message after each completed feature.
This lets you revert if something goes wrong.
9. Costs: Is It Really All Free?
Here's a cost breakdown for each service:
| Service | Free Plan | When You Pay | |---------|-----------|-------------| | Claude Code | Requires an Anthropic plan (starting at $20/month) or API key | Immediately, but the value is enormous | | Supabase | Generous free tier (2 projects, 500MB DB) | Beyond free tier limits | | Vercel | Free tier for personal projects | For teams or commercial use | | GitHub | Free for public and private repos | Enterprise features |
Note: Claude Code requires a subscription or API credits, but the return on investment in terms of development speed is extraordinary. For a demo or MVP, the total cost is in the range of $20.
Free AI Alternatives
If you want to keep costs at absolute zero, you can use:
- Cursor (free tier with limitations).
- GitHub Copilot (free for students and open source).
- Codeium/Windsurf (generous free tier).
10. From Demo to Product: Next Steps
Once your demo is live, here's how to proceed:
- Collect feedback: share the demo with potential users and gather opinions.
- Iterate quickly: use vibecoding to implement requested changes.
- Monitor metrics: Vercel Analytics and Supabase Dashboard give you essential data.
- Scale when needed: upgrade to paid plans only when you've validated demand.
Conclusion
Vibecoding with Claude Code, Supabase, and Vercel represents a powerful combination for building demos and MVPs in record time. What used to take weeks of development can now be accomplished in just a few hours, with a surprisingly high level of quality.
The key is approaching vibecoding with the right mindset: it's not about "not knowing how to code" but about amplifying your capabilities with AI tools. The more you know about the underlying technologies (React, SQL, authentication, deployment), the more effective you'll be at guiding the AI agent toward the desired result.
The future of software development is here, and the cost of getting started has never been lower. Create your demo, validate it with real users, and build the next great product.
Checklist for your first demo:
- [x] Claude Code installed and configured
- [x] Supabase project created with database schema
- [x] Next.js project initialized with shadcn/ui
- [x] Authentication configured
- [x] Full CRUD implemented
- [x] Modern and responsive UI
- [x] Deployed to Vercel
- [x] Shareable URL ready for feedback