Home/Blog/Lovable alternative: free vibe coding
Vibe coding

Lovable Alternative: Free Vibe Coding with VSCode, Cline, Ollama & Supabase

Assemble the same experience Lovable sells — chat that builds an app, live preview, real database — entirely on your own Mac, for free, with your code and prompts never leaving your machine.

Series: Vibe Coding on Your Own Terms — Post 1 of 2
Post 2 preview: "From Localhost to Live: Publishing Your Vibe-Coded App to a Cloud Web Server"

Alternative headline options:

  • Build Your Own Lovable: A Free, Local Vibe Coding Setup for the Mac
  • Vibe Coding Without the Subscription: VSCode + Cline + Ollama + Supabase

What is vibe coding, anyway?

Vibe coding is a way of building software where you describe what you want in plain language and an AI writes the code — while you steer, review, and react to what appears on screen. You stay in the driver's seat as the product person: "add a dark mode toggle", "the delete button should ask for confirmation", "make the list sort by date". The AI handles the syntax, the file structure, the boilerplate. You handle the vibe: what the app should do and how it should feel.

The term took off in early 2025 (coined by AI researcher Andrej Karpathy), and it resonated because it describes something real: for a huge class of apps — internal tools, prototypes, side projects, small products — you no longer need to write most of the code yourself. You need to be able to direct code being written, and to recognize when something's off.

What is Lovable?

Lovable is one of the most popular vibe coding platforms. You type what you want into a chat box, and it builds a working web app in front of you — user interface, database, login, file uploads, the lot — with a live preview updating as you talk. Under the hood, Lovable generates a fairly standard modern web stack: React with TypeScript, styled with Tailwind CSS and shadcn/ui components, backed by Supabase (a Postgres database with authentication and file storage built in).

It's a great product. It's also a subscription with usage-based credits, your code lives in their cloud, and the AI calls go to commercial models. Which raises an obvious question for tinkerers:

Can you assemble the same experience yourself — free, local, and private?

Yes. That's what this post is about.

The goal of this post

By the end, you'll have a complete vibe coding environment running on your Mac:

Lovable gives youYour free local equivalent
Chat box that builds the appCline (an AI coding agent inside VSCode)
The AI brainOllama running an open-source model locally
Live previewVite dev server in your browser, hot-reloading on every change
Hidden codeVSCode — same code, except you can see and touch it
Database, auth, storageSupabase running locally in containers — the exact same technology Lovable uses in the cloud
One-click publishComing in Post 2 of this series

Total cost: €0. Your code never leaves your machine. Your prompts never leave your machine. And because it's the same stack Lovable uses, everything you build has a clean path to real cloud hosting later.

One honest expectation-setter before we start: a local open-source model on consumer hardware is not as capable as the frontier models Lovable rents. Your local agent will occasionally do something dumb, and this post shows you the guardrails that keep that manageable (they're half the value of the article — I hit every pitfall below for real during setup).

What you need before starting

  • A Mac (Apple Silicon recommended; 16 GB RAM is comfortable, 8 GB works with the tricks in the RAM section below)
  • VSCode installed, with the Cline extension
  • Ollama installed, with a coding model pulled — qwen2.5-coder (7b or 14b) is currently one of the strongest options that fits on consumer hardware

Setting up VSCode + Cline + Ollama is well covered elsewhere; this post starts where most guides stop: the local test server and database — the part that turns "an AI that edits files" into "a Lovable-like experience with a real running app."

Phase 1: One-time machine setup (~20 minutes)

Four command-line tools, installed once, used by every future project. Open the Terminal (in VSCode: Terminal → New Terminal).

1. Homebrew — the Mac's package manager

Check if you have it:

brew --version

If that prints a version, move on. If not:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

On Apple Silicon, run the two extra commands the installer prints at the end (they add brew to your PATH), then open a new terminal.

2. OrbStack — the container runtime

Your local database will run in containers. The usual tool is Docker Desktop, but OrbStack is a drop-in replacement that uses noticeably less RAM and battery — and RAM matters, because Ollama is already eating a lot of it.

brew install orbstack
open -a OrbStack

Accept the prompts; it then lives quietly in your menu bar. Verify:

docker --version

3. Node.js — runs the dev server

brew install node
node -v
Pitfall #1 — scary-looking install messages. Homebrew may print "Caveats" like "Single Executable Application is disabled" or "Temporal support is disabled." These look like errors; they're harmless notices about niche Node features nothing in this stack uses. If you see the 🍺 beer glass, the install succeeded.

4. Supabase CLI — your entire backend in one tool

brew install supabase
supabase --version

This is the piece most guides miss. The Supabase CLI runs a complete local backend — Postgres database, authentication, file storage, and a visual admin UI — with one command. It's the same open-source software behind Lovable's cloud backend. You don't install or configure Postgres yourself, ever.

Phase 2: Creating a project (~20 minutes, once per project)

5. Scaffold the app

Pick one folder where all your projects will live, and stick to it religiously:

mkdir -p ~/Projects && cd ~/Projects
npm create vite@latest my-first-app -- --template react-ts
cd my-first-app
npm install

The scaffolder asks "Which linter to use?" — pick ESLint. It's the long-established standard, and (a theme you'll see throughout) local AI models have seen vastly more ESLint projects in training than newer alternatives, so they make fewer mistakes with it.

Open the project in VSCode with code . — and if the terminal says command not found: code, that's a one-time VSCode setting: press Cmd+Shift+P, type "shell command", select "Shell Command: Install 'code' command in PATH", then open a new terminal.

Pitfall #2 — the wrong-folder trap. This cost me more time than anything else in the whole setup. If you open VSCode while your terminal is sitting in some other directory, your edits go into the wrong project — and later commands mysteriously fail because the files they expect were never changed. Two habits prevent it entirely: before any command, glance at the terminal prompt or run pwd — it must end in your project name; and in VSCode use File → Open Folder to open exactly the project folder, nothing above it.

Now verify the heart of the setup — your local test server:

npm run dev

Open http://localhost:5173 — the starter page loads. This Vite server hot-reloads the browser within a second of any file change, which is what creates the Lovable "watch it build live" feeling. Leave it running in its own terminal tab; open new tabs (the + icon) for other commands.

Pitfall #3 — port 5174? If the URL ever shows 5174 instead of 5173, you have a second dev server running in a forgotten terminal tab. Not harmful, but confusing. Close the duplicates; run exactly one.

6. Tailwind CSS + shadcn/ui — Lovable's visual language

npm install tailwindcss @tailwindcss/vite

(If npm warns about fsevents and "install scripts not yet covered by allowScripts" — that's a newer npm security feature. fsevents is a trusted macOS file-watching helper; approve it with npm approve-scripts fsevents or just carry on, everything works either way.)

Replace the entire content of src/index.css with one line:

@import "tailwindcss";
Pitfall #4 — paste replaces, not appends. When a guide says "replace the file content", select everything (Cmd+A), delete, then paste. I managed to paste a new vite.config.ts below the old one, producing a file with duplicate imports and two default exports — instant breakage. If something errors right after an edit, check you don't have the file's content twice.

Now, before running shadcn's installer, do the setup it silently requires. This is the step where my setup first properly failed:

Pitfall #5 — shadcn needs an "import alias" that Vite doesn't ship. shadcn/ui writes components that import from @/components/... — the @ being shorthand for your src folder. The Vite template doesn't define that shorthand, so npx shadcn init fails its preflight checks with "Could not find valid path aliases." The fix is three small edits, done once per project:

Install the type helper:

npm install -D @types/node

Replace vite.config.ts with:

import path from "path"
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'

export default defineConfig({
  plugins: [react(), tailwindcss()],
  resolve: {
    alias: { "@": path.resolve(__dirname, "./src") },
  },
})

Replace tsconfig.json with:

{
  "files": [],
  "references": [
    { "path": "./tsconfig.app.json" },
    { "path": "./tsconfig.node.json" }
  ],
  "compilerOptions": {
    "baseUrl": ".",
    "paths": { "@/*": ["./src/*"] }
  }
}

And in tsconfig.app.json, add these two lines at the top of the existing "compilerOptions" block:

    "baseUrl": ".",
    "paths": { "@/*": ["./src/*"] },

Now shadcn will pass its checks:

npx shadcn@latest init
npx shadcn@latest add button card input

The init asks two questions current guides rarely mention. "Select a component library?" — pick Radix UI, even though the tool recommends Base UI. Radix is what shadcn was originally built on and what Lovable uses, which again means it's what your local models know best. "Which preset?"Nova (Lucide icons, the classic shadcn look). Defaults for everything else.

7. Start your local backend + database

supabase init
supabase start

The first supabase start downloads about a dozen container images — give it a few minutes.

Pitfall #6 — a download randomly fails. One of my thirteen images (storage-api) failed to pull with a cryptic registry error while the other twelve succeeded. Nothing was wrong with my setup — container registries occasionally hiccup. The fix is anticlimactic: run supabase start again. It resumes and fetches only what's missing.

When it finishes, run supabase status to see what you now have:

ServiceAddress
Your app (test server)http://localhost:5173
Studio — visual database adminhttp://127.0.0.1:54323
API (REST/Auth/Storage)http://127.0.0.1:54321
Postgres, direct connectionport 54322

Open Studio in your browser and look around: table editor, SQL console, auth users, storage buckets. This is your window into the database for the entire vibe coding workflow — when the AI claims it saved something, Studio is where you check it actually did.

(You may also see "Stopped services: imgproxy, pooler" — those are optional components; that's normal.)

8. Wire the app to the database

npm install @supabase/supabase-js
Pitfall #7 — the keys don't look like the tutorials say. Most guides tell you to copy an "anon key" that looks like eyJhbGci.... Newer Supabase versions replaced that format: supabase status now prints a Publishable key (sb_publishable_...) and a Secret key (sb_secret_...). The Publishable key is your app's key. The Secret key is the admin key — it never goes anywhere near frontend code.

Create a file called .env.local in the project root:

VITE_SUPABASE_URL=http://127.0.0.1:54321
VITE_SUPABASE_ANON_KEY=sb_publishable_...your-key-here...

And the client at src/lib/supabase.ts:

import { createClient } from '@supabase/supabase-js'

export const supabase = createClient(
  import.meta.env.VITE_SUPABASE_URL,
  import.meta.env.VITE_SUPABASE_ANON_KEY
)

9. The .clinerules file — the most underrated step

Create a file called .clinerules in the project root. Cline reads it automatically before every task, and it's the difference between an agent that follows your architecture and one that improvises:

# Project rules

## Stack
- React + TypeScript + Vite
- Tailwind CSS v4 + shadcn/ui (components live in src/components/ui)
- Supabase for database, auth, and storage (client in src/lib/supabase.ts)

## Rules
- Use existing shadcn/ui components before writing custom ones.
- Never hand-write authentication logic; always use supabase.auth methods.
- All database schema changes go into SQL migration files via
  `supabase migration new <name>` — never apply schema changes directly.
- After schema changes, apply with `supabase db reset`.
- Read environment variables only via import.meta.env.VITE_*.
- Keep components small; one component per file.
- Do not add new dependencies without asking first.

Frontier models often infer these conventions; small local models need them written down. You'll see exactly why in a moment.

10. Version control — your undo button for AI mistakes

git init
git add -A
git status   # check the list: .env.local must NOT appear (your keys stay out of git)
git commit -m "Project scaffold: Vite + React + Tailwind + shadcn + Supabase"

When an AI edits your code, git is your safety net: commit after every working feature, and any AI-induced mess is one git checkout -- . away from undone.

Pitfall #8 — Supabase temp files bloating your commits. After your first feature commit you may notice thousands of inserted lines from supabase/.temp/... — internal scratch files that don't belong in version control. Exclude them once: echo "supabase/.temp/" >> .gitignore, then git rm -r --cached supabase/.temp and commit.

Phase 3: The first feature — and what AI agents get wrong about databases

Setup done. Time to vibe. With supabase start and npm run dev both running, open the Cline panel and prompt:

Create a todos feature: a migration for a `todos` table (id uuid pk default gen_random_uuid(), title text not null, done boolean default false, created_at timestamptz default now()), then a page using shadcn/ui components that lists, adds, and toggles todos via the supabase client.

Cline will propose file changes, you approve them, and the browser hot-reloads into a todos UI. Magical — until you try to add a todo. Here's the honest part most tutorials skip. My first feature failed twice, in two instructive ways:

Pitfall #9 — "Could not find the table 'public.todos'". The UI exists but the database table doesn't. Databases change through migration files — small SQL scripts in supabase/migrations/ that are applied with supabase db reset. My local model built the UI but skipped the migration (yes, despite the rules file — small models sometimes do). The habit that catches this every time: after any feature that touches data, check that a new .sql file appeared in supabase/migrations/. If not, tell Cline: "Put the schema changes in a migration file via supabase migration new." Then apply with supabase db reset.
Pitfall #10 — "permission denied for table todos". Progress — the table exists now — but Postgres refuses your app access to it. Supabase apps talk to the database as a restricted "anon" role, and new tables need explicit access rights plus a Row Level Security policy. The robust fix is a migration that handles creation and permissions together. Create one with supabase migration new create_todos and give it this shape:
create table if not exists public.todos (
  id uuid primary key default gen_random_uuid(),
  title text not null,
  done boolean not null default false,
  created_at timestamptz not null default now()
);

grant usage on schema public to anon, authenticated;
grant select, insert, update, delete on table public.todos to anon, authenticated;

alter table public.todos enable row level security;

drop policy if exists "dev allow all" on public.todos;
create policy "dev allow all" on public.todos
  for all using (true) with check (true);

Then supabase db reset, refresh the browser — and it works. Add a todo, reload the page, it persists. Open Studio and there's your row in Postgres. That's the full chain, verified: your prompt → local AI → code + migration → real database → live UI.

(That "allow all" policy is deliberately wide open — correct for local development where the only user is you, and exactly what gets replaced with real security rules before anything goes live. That's a Post 2 topic.)

Pitfall #11 — duplicate migrations. After the fix, my agent belatedly created its own create-table migration, which would have crashed the next supabase db reset (creating a table that already exists is an error). If two migrations create the same table, delete the redundant one and re-run supabase db reset to prove the set is healthy.

Commit the milestone: git add -A && git commit -m "Add todos feature".

What daily vibe coding actually looks like

One source of confusion worth clearing up: VSCode ships its own AI chat panel, and Cline adds a second one. They're unrelated. Use only the Cline panel — it's the one connected to Ollama and the one that can edit files and run commands. Hide the built-in chat and never think about it again.

The Lovable mapping, one screen, two halves: VSCode with the Cline panel on the left, browser with your app on the right. Lovable's chat = Cline. Lovable's preview = localhost:5173. Lovable's hidden code = visible in your editor, which is a feature, not a bug.

The daily rhythm:

# session start
supabase start
npm run dev

Then loop: describe one feature to Cline → review the diffs → approve → watch the browser hot-reload → if data was involved, glance at supabase/migrations for a new file → test it → git add -A && git commit -m "feature". When something goes sideways, say so to Cline or roll back with git. At session end, supabase stop — which brings us to hardware.

A note on RAM (MacBook Air owners, this is for you). Ollama with a 7b model wants 5–8 GB; the local Supabase stack takes 1.5–2.5 GB; Vite and your browser another 1–2 GB. On 16 GB everything coexists happily. On 8 GB, use the toggle trick: supabase stop while the model is doing heavy generation, supabase start when you want to test. And three habits that specifically help small local models: keep tasks small (one feature per Cline conversation, then start a fresh task — long chats degrade small models), use Cline's Plan mode before Act mode for anything non-trivial, and keep your .clinerules current as the project grows.

What you have now — and what's next

For the price of an afternoon and zero euros per month, you now run the same stack Lovable sells: an AI agent building a React + Tailwind + shadcn app against a real Postgres database, live preview included, entirely on your own machine. Plus three things Lovable doesn't give you: total privacy, visible code you actually own and understand, and guardrails (git, migrations, rules file) that professional developers use.

Everything so far lives on localhost — visible only to you. Post 2 of this series covers the missing chapter: publishing. How to take a vibe-coded app live on a real cloud web server — GitHub for the code, Vercel for the frontend, Supabase Cloud for the database — where the entire local-to-live transition comes down to changing two environment variables and running two commands. And, critically, how to replace that wide-open development security policy with real Row Level Security rules before your app meets the public internet.

Until then: supabase start, npm run dev, and go build something.

This is Post 1 of the "Vibe Coding on Your Own Terms" series. Post 2: "From Localhost to Live: Publishing Your Vibe-Coded App to a Cloud Web Server."

Vibe codingLovable alternativeClineOllamaSupabaseVSCodeLocal-first
JW

Jonas Weber

Builds internal tools with AI coding agents. Runs the Bubbles1 vibe coding lab — the pitfalls, the pipelines and the productivity tricks that hold up in real projects.

Prefer to ship without the setup?

Bubbles1 audits and monitors what you build — so the vibe stays fun and the fundamentals stay tight.

14-day trial · No credit card · Cancel anytime