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

Lovable 的免费平替:用 VSCode、Cline、Ollama 和 Supabase 玩转 Vibe Coding

在自己的 Mac 上,免费搭建 Lovable 同款体验——聊天构建应用、实时预览、真实数据库,全部本地运行,代码与 prompt 从不出你的机器。

系列:「按自己的方式玩 Vibe Coding」— 第 1 篇,共 2 篇
第 2 篇预告:「从 localhost 到上线:把你的 vibe coding 应用发布到云端 Web 服务器」

备选标题:

  • 自己动手搭一个 Lovable:Mac 上的免费本地 vibe coding 环境
  • 不花订阅费的 Vibe Coding:VSCode + Cline + Ollama + Supabase

到底什么是 vibe coding?

Vibe coding(氛围编程)是一种全新的软件开发方式:你用自然语言描述想要什么,AI 来写代码——而你负责掌舵、审查代码,并对屏幕上出现的结果及时做出反应。你始终以产品负责人的身份坐在驾驶座上:「加一个深色模式开关」、「删除按钮应该先弹确认」、「让列表按日期排序」。AI 负责语法、文件结构和样板代码,你负责 vibe:这个应用该做什么,用起来是什么感觉。

这个词在 2025 年初火了起来(由 AI 研究员 Andrej Karpathy 提出),它之所以引起共鸣,是因为它描述了一个真实的变化:对于一大类应用——内部工具、原型、副业项目、小型产品——你已经不再需要亲手写大部分代码了。你需要的是能够指挥代码被写出来,并且能识别出哪里不对劲。

Lovable 是什么?

Lovable 是目前最流行的 vibe coding 平台之一。你在聊天框里输入需求,它就当着你的面构建出一个能跑的 Web 应用——用户界面、数据库、登录、文件上传,一应俱全——还有一个随着对话实时更新的预览窗口。在底层,Lovable 生成的是一套相当标准的现代 Web 技术栈:React + TypeScript,用 Tailwind CSSshadcn/ui 组件做样式,后端是 Supabase(内置身份认证和文件存储的 Postgres 数据库)。

它是个很棒的产品。但它也是一个按用量计费 credits 的订阅服务,你的代码存在它的云端,AI 调用走的是商业模型。这就给爱折腾的人抛出了一个显而易见的问题:

能不能自己把同样的体验攒出来——免费、本地、私有?

能。这正是本文要讲的。

本文的目标

读完之后,你的 Mac 上将运行着一套完整的 vibe coding 环境:

Lovable 提供的你的免费本地替代方案
能构建应用的聊天框Cline(VSCode 里的 AI 编程智能体)
AI 大脑Ollama 在本地运行开源模型
实时预览浏览器里的 Vite 开发服务器,每次改动都会热重载(hot reload)
看不见的代码VSCode ——同样的代码,只不过你能看到、也能改
数据库、认证、存储本地容器里跑的 Supabase ——和 Lovable 在云端用的是一模一样的技术
一键发布本系列的第 2 篇再讲

总成本:0 欧元。你的代码不出你的机器,你的 prompt 也不出你的机器。而且因为这和 Lovable 用的是同一套技术栈,你构建的一切以后都有一条干净的路径通向真正的云端托管。

开始之前先坦诚地打个预防针:在消费级硬件上跑的本地开源模型,能力不如 Lovable 租用的那些前沿模型。你的本地智能体偶尔会干蠢事,而本文会告诉你哪些护栏能把这些问题控制在可接受的范围内(它们占了这篇文章一半的价值——下面的每一个坑我在搭建过程中都实打实地踩过)。

开始前你需要准备什么

  • 一台 Mac(推荐 Apple Silicon;16 GB 内存很从容,8 GB 配合下文「内存」一节的技巧也能用)
  • 装好 VSCode,并安装 Cline 扩展
  • 装好 Ollama,并拉取一个编程模型—— qwen2.5-coder(7b 或 14b)是目前消费级硬件能跑的最强选项之一

VSCode + Cline + Ollama 的安装配置网上已有大量教程;本文从大多数教程止步的地方开始:本地测试服务器和数据库——正是这部分,把「一个会改文件的 AI」变成「有真实运行应用的、类 Lovable 的体验」。

第一阶段:一次性机器配置(约 20 分钟)

四个命令行工具,装一次,以后每个项目都能用。打开终端(在 VSCode 里:Terminal → New Terminal)。

1. Homebrew —— Mac 的包管理器

先检查是否已安装:

brew --version

如果打印出版本号,直接跳到下一步。如果没有:

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

在 Apple Silicon 上,记得执行安装器最后打印出的那两条额外命令(它们会把 brew 加入你的 PATH),然后新开一个终端。

2. OrbStack —— 容器运行时

你的本地数据库将跑在容器里。常见的工具是 Docker Desktop,但 OrbStack 是它的直接替代品,内存和电量占用明显更低——而内存很重要,因为 Ollama 已经在大口吃内存了。

brew install orbstack
open -a OrbStack

接受各种提示后,它就安静地待在你的菜单栏里。验证一下:

docker --version

3. Node.js —— 运行开发服务器

brew install node
node -v
坑 #1 —— 看起来吓人的安装信息。 Homebrew 可能会打印一些「Caveats」,比如 "Single Executable Application is disabled""Temporal support is disabled"。这些看着像报错,其实是无害的提示,涉及的都是本文技术栈完全用不到的 Node 冷门特性。只要看到 🍺 啤酒杯,就说明安装成功了。

4. Supabase CLI —— 一个工具搞定整个后端

brew install supabase
supabase --version

这是大多数教程漏掉的一环。Supabase CLI 用一条命令就能运行一个完整的本地后端—— Postgres 数据库、身份认证、文件存储,外加一个可视化管理界面。它和 Lovable 云端后端背后是同一套开源软件。你永远不需要自己安装或配置 Postgres。

第二阶段:创建项目(约 20 分钟,每个项目一次)

5. 搭建应用脚手架

选定一个存放所有项目的文件夹,并且雷打不动地只用它:

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

脚手架会问 "Which linter to use?" ——选 ESLint。它是历史悠久的标准(这也是贯穿全文的一个主题):本地 AI 模型在训练中见过的 ESLint 项目远多于那些新兴替代品,所以用它出错更少。

code . 在 VSCode 里打开项目——如果终端提示 command not found: code,那只是一个一次性的 VSCode 设置:按 Cmd+Shift+P,输入 "shell command",选择 "Shell Command: Install 'code' command in PATH",然后新开一个终端。

坑 #2 —— 开错文件夹的陷阱。 这个坑耗掉的时间比整个搭建过程中任何其他环节都多。如果你在终端还停留在别的目录时打开 VSCode,你的修改会写进错误的项目——之后的命令会莫名其妙地失败,因为它们期望的文件根本没被改过。两个习惯能彻底避免这个问题:执行任何命令前,先瞄一眼终端提示符或跑一下 pwd ——路径必须以你的项目名结尾;在 VSCode 里用 File → Open Folder 精确打开项目文件夹本身,而不是它的任何上层目录。

现在来验证整套环境的心脏——你的本地测试服务器:

npm run dev

打开 http://localhost:5173 ——起始页加载出来了。这个 Vite 服务器会在任何文件改动后一秒内热重载浏览器,这正是营造 Lovable 那种「看着它实时构建」感觉的关键。让它在自己的终端标签页里一直跑着;其他命令用新标签页(+ 图标)执行。

坑 #3 —— 怎么变成 5174 端口了? 如果 URL 里出现的是 5174 而不是 5173,说明某个被遗忘的终端标签页里还跑着第二个开发服务器。没什么危害,但容易造成混乱。关掉多余的,只保留一个。

6. Tailwind CSS + shadcn/ui —— Lovable 的视觉语言

npm install tailwindcss @tailwindcss/vite

(如果 npm 警告 fsevents 和 "install scripts not yet covered by allowScripts" ——那是 npm 较新的安全特性。fsevents 是一个可信的 macOS 文件监听辅助工具;用 npm approve-scripts fsevents 批准它,或者干脆无视,两种情况下一切都能正常工作。)

src/index.css 的全部内容替换为这一行:

@import "tailwindcss";
坑 #4 —— 粘贴是替换,不是追加 当教程说「替换文件内容」时,要先全选(Cmd+A)、删除,再粘贴。我就干过把新的 vite.config.ts 粘到旧内容下面的事,结果文件里出现了重复的 import 和两个 default export ——当场崩溃。如果某次编辑后立刻报错,先检查文件内容是不是重复了两遍。

接下来,在运行 shadcn 安装器之前,先完成它悄悄依赖的配置。我的搭建流程第一次真正翻车就在这一步:

坑 #5 —— shadcn 需要一个 Vite 默认不带的「import alias」。 shadcn/ui 生成的组件会从 @/components/... 导入——这个 @ 是你 src 文件夹的简写。Vite 模板并没有定义这个简写,所以 npx shadcn init 会在预检时报 "Could not find valid path aliases." 而失败。解决办法是三处小修改,每个项目做一次:

安装类型辅助包:

npm install -D @types/node

vite.config.ts 替换为:

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") },
  },
})

tsconfig.json 替换为:

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

再在 tsconfig.app.json 中,把这两行加到已有 "compilerOptions" 块的最上方:

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

现在 shadcn 就能通过检查了:

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

init 过程会问两个当前教程很少提到的问题。"Select a component library?" ——选 Radix UI,即便工具本身推荐 Base UI。Radix 是 shadcn 最初构建时的基础,也是 Lovable 在用的,这又一次意味着它是你的本地模型最熟悉的东西。"Which preset?" —— Nova(Lucide 图标,经典 shadcn 风格)。其余全部用默认值。

7. 启动你的本地后端 + 数据库

supabase init
supabase start

第一次 supabase start 会下载十几个容器镜像——耐心等几分钟。

坑 #6 —— 某个下载随机失败。 我的十三个镜像里有一个(storage-api)拉取时报了一个莫名其妙的 registry 错误,其余十二个都成功了。我的配置没有任何问题——容器镜像仓库偶尔就是会抽风。解决办法平淡得让人失望:再跑一次 supabase start。它会断点续传,只拉取缺失的部分。

完成后,运行 supabase status 看看你现在拥有了什么:

服务地址
你的应用(测试服务器)http://localhost:5173
Studio —— 可视化数据库管理http://127.0.0.1:54323
API(REST/Auth/Storage)http://127.0.0.1:54321
Postgres 直连端口 54322

在浏览器里打开 Studio 逛一圈:表编辑器、SQL 控制台、认证用户、存储桶。在整个 vibe coding 工作流中,这就是你观察数据库的窗口——当 AI 声称它保存了某样东西时,Studio 是你验证它到底存没存的地方。

(你可能还会看到 "Stopped services: imgproxy, pooler" ——那些是可选组件,属于正常现象。)

8. 把应用接上数据库

npm install @supabase/supabase-js
坑 #7 —— 密钥长得和教程说的不一样。 大多数教程让你复制一个形如 eyJhbGci... 的 "anon key"。较新版本的 Supabase 已经换掉了那种格式:supabase status 现在打印的是一个 Publishable key(sb_publishable_...)和一个 Secret key(sb_secret_...)。Publishable key 是给你应用用的;Secret key 是管理员密钥——它绝对不能出现在任何前端代码附近。

在项目根目录创建一个名为 .env.local 的文件:

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

再在 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. .clinerules 文件 —— 最被低估的一步

在项目根目录创建一个名为 .clinerules 的文件。Cline 在每个任务开始前都会自动读取它,而它正是「遵循你的架构的智能体」和「自由发挥的智能体」之间的分水岭:

# 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.

前沿模型通常能自行推断出这些约定;小型本地模型则需要你把它们白纸黑字写下来。马上你就会看到为什么。

10. 版本控制 —— 应对 AI 失误的后悔药

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"

当 AI 修改你的代码时,git 就是你的安全网:每完成一个能正常工作的功能就 commit 一次,这样 AI 搞出的任何烂摊子都只需一句 git checkout -- . 就能撤销。

坑 #8 —— Supabase 临时文件撑爆你的提交。 在第一次功能 commit 之后,你可能会注意到来自 supabase/.temp/... 的几千行新增内容——这些是不该进版本控制的内部临时文件。一次性排除它们:echo "supabase/.temp/" >> .gitignore,然后 git rm -r --cached supabase/.temp 并提交。

第三阶段:第一个功能 —— 以及 AI 智能体在数据库上会栽哪些跟头

搭建完毕,该开始 vibe 了。在 supabase startnpm run dev 都运行着的状态下,打开 Cline 面板并输入 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.

(给 AI 的 prompt 用英文写效果最好。)

Cline 会提出一系列文件修改,你逐一批准,浏览器随即热重载出一个待办事项 UI。很神奇——直到你尝试添加一条待办。接下来是大多数教程跳过的诚实部分:我的第一个功能失败了两次,而且两次都很有教育意义:

坑 #9 —— "Could not find the table 'public.todos'"。 UI 有了,但数据库表不存在。数据库的变更是通过迁移文件(migration)进行的——即 supabase/migrations/ 里的小段 SQL 脚本,用 supabase db reset 应用。我的本地模型构建了 UI,却跳过了迁移(没错,尽管规则文件里写着——小模型有时就是会这样)。每次都能抓住这个问题的习惯是:任何涉及数据的功能完成后,检查 supabase/migrations/ 里是否出现了新的 .sql 文件。 如果没有,告诉 Cline:"Put the schema changes in a migration file via supabase migration new." 然后用 supabase db reset 应用。
坑 #10 —— "permission denied for table todos"。 有进展了——表现在存在了——但 Postgres 拒绝你的应用访问它。Supabase 应用是以一个受限的 "anon" 角色与数据库对话的,新表需要显式的访问权限,外加一条 Row Level Security 策略。稳妥的解法是用一个同时处理建表权限的迁移。用 supabase migration new create_todos 创建一个,内容大致如下:
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);

然后 supabase db reset,刷新浏览器——成了。添加一条待办,刷新页面,数据还在。打开 Studio,你的那行数据就躺在 Postgres 里。至此,完整链路得到验证:你的 prompt → 本地 AI → 代码 + 迁移 → 真实数据库 → 实时 UI。

(那条 "allow all" 策略是故意完全敞开的——在只有你一个用户的本地开发环境里这是正确的,而在任何东西上线之前,它恰恰是要被真正的安全规则替换掉的部分。那是第 2 篇的话题。)

坑 #11 —— 重复的迁移。 修复之后,我的智能体后知后觉地又创建了一个它自己的建表迁移,这会让下一次 supabase db reset 直接崩溃(创建一个已存在的表是错误)。如果两个迁移创建同一张表,删掉多余的那个,再跑一次 supabase db reset 来证明整套迁移是健康的。

提交这个里程碑:git add -A && git commit -m "Add todos feature"

日常 vibe coding 实际上长什么样

先澄清一个容易混淆的点:VSCode 自带一个 AI 聊天面板,Cline 又加了第二个。两者毫无关系。只用 Cline 面板——它才是连着 Ollama、能改文件、能跑命令的那个。把内置聊天隐藏掉,从此不再想起它。

与 Lovable 的对应关系,一屏两半:左边是带 Cline 面板的 VSCode,右边是跑着你应用的浏览器。Lovable 的聊天 = Cline。Lovable 的预览 = localhost:5173。Lovable 藏起来的代码 = 在你编辑器里清晰可见——这是特性,不是缺陷。

日常节奏:

# session start
supabase start
npm run dev

然后循环:向 Cline 描述一个功能 → 审查 diff → 批准 → 看浏览器热重载 → 如果涉及数据,瞄一眼 supabase/migrations 有没有新文件 → 测试 → git add -A && git commit -m "feature"。出岔子时,要么直接告诉 Cline,要么用 git 回滚。会话结束时执行 supabase stop ——这就引出了硬件话题。

关于内存的说明(MacBook Air 用户,这段是写给你的)。 Ollama 跑 7b 模型需要 5–8 GB;本地 Supabase 全家桶占 1.5–2.5 GB;Vite 和浏览器再占 1–2 GB。16 GB 内存下大家相安无事。8 GB 的话,用开关技巧:模型在做繁重生成时 supabase stop,想测试时再 supabase start。另外三个对小型本地模型特别有帮助的习惯:保持任务小巧(一个 Cline 会话只做一个功能,然后开新任务——长对话会让小模型能力退化);任何不算太简单的任务,先用 Cline 的 Plan 模式再进 Act 模式;并且随着项目成长,持续更新你的 .clinerules

你现在拥有了什么 —— 以及接下来是什么

花一个下午的时间、每月零欧元,你现在跑起来的就是 Lovable 在卖的那套技术栈:一个 AI 智能体对着真实的 Postgres 数据库构建 React + Tailwind + shadcn 应用,自带实时预览,完全在你自己的机器上。外加三样 Lovable 给不了你的东西:彻底的隐私、你真正拥有并理解的可见代码,以及专业开发者在用的护栏(git、迁移、规则文件)。

到目前为止,一切都活在 localhost 上——只有你自己能看到。本系列的第 2 篇将补上缺失的一章:发布。 如何把一个 vibe coding 出来的应用部署到真正的云端 Web 服务器——代码放 GitHub,前端放 Vercel,数据库放 Supabase Cloud ——整个从本地到上线的迁移,最终归结为改两个环境变量、跑两条命令。以及至关重要的:如何在你的应用面向公网之前,把那条完全敞开的开发用安全策略替换成真正的 Row Level Security 规则。

在那之前:supabase startnpm run dev,去构建点什么吧。

本文是「按自己的方式玩 Vibe Coding」系列的第 1 篇。第 2 篇:「从 localhost 到上线:把你的 vibe coding 应用发布到云端 Web 服务器」。

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