After Vibe Coding bit me back, I rebuilt my browser extension with spec-driven development
While building a browser translation extension, the author had AI generate code directly through vibe coding. By the second week, text extraction was breaking on all kinds of websites, new sessions were losing earlier decisions, and one optimization attempt took down the extraction logic with no version to roll back to.
The author uses the browser extension project to review why vibe coding led to rework, lays out three documents and concrete git rollback practices, and shows how this carries over to long-running projects that span multiple sessions.
It all started with a browser extension I wanted to build.
For a while I'd had this idea in my head: build a browser extension that, with one click on an English page, pulls out the article body, hands it to an AI to translate into Chinese, renders it as Markdown, and copies it with one click. The target users were friends who run WeChat public accounts—take the English section and turn it straight into a Chinese version.
I typed into the chat box, "Build me a browser extension that extracts the page body, calls an AI to translate it, and exports Markdown," and the AI spat out thousands of lines of code.
Honestly, day one was a rush. The extension actually installed in Chrome and ran, and the translations on the demo page looked legit. At that point I thought the "10x productivity" talk wasn't hype at all.
Then week two hit, and the rework began.
The "extract the body" feature failed in creative ways on all kinds of sites: the nav bar got treated as the body, ads got mixed into the translation, and paginated articles only yielded the first page. I'd ask the AI to fix it, and fixing A broke B. Worse, once I started a new session it had no memory of earlier decisions—why we picked this approach, which files had been changed, why they were changed—all gone. It could only guess, and a wrong guess is a hallucination, so every round of rework burned my time and my tokens.
What finally stopped me was a night that nearly fell apart: one AI "optimization" broke the entire extraction logic. Staring at a screen full of errors, I had exactly one thought—the last version that actually ran, I don't think I ever committed it.
So where exactly was the problem?
It took me a while to figure out: the AI wasn't the problem, the way I was using it was. I skipped the "think it through" step and went straight to "just build it."
It's like building a house without blueprints. Fast hands aren't a virtue for a worker; the faster the walls go up, the more hopeless it feels when you realize there's no door to the bedroom. In The 7 Habits of Highly Effective People, "begin with the end in mind" says everything goes through two creations: first the mental creation, designing it in your head; then the physical creation, actually building it.
The root disease of vibe coding is being seduced by the chat window into skipping the first creation and charging straight into the second.
What Spec-Driven Development (SDD) does comes down to one sentence: first turn the design in your head into a document, then let the document drive the AI to write code. As the cost of writing code keeps dropping, what's actually scarce isn't an AI that can write code—it's a clear, executable, verifiable statement of intent.
You don't need many documents—just what you need. The core three are:
proposal.md: what to do, why do it, and where the boundaries aredesign.md: how to implement it—technical architecture and technology choicestask.md: what comes first, what comes next, and what can run in parallel
Let's walk through my extension for real.
First, strip the MVP down to the minimum.
Starting over, I didn't let the AI write a single line of code. I wrote proposal.md first, forcing myself to cut the requirements down to the smallest viable unit:
markdown
Code explanation
Copy code
## 要做什么
在英文博客页面一键完成:
提取正文 → 调 AI 翻译成中文 → Markdown 渲染 → 一键复制
## 不做什么
- 不做收藏夹、历史记录
- 不做账号系统
- 不做中英以外的语种
- 不做整页翻译,只翻正文
The "what not to do" column matters a lot—it's there to stop the AI and to stop me. Without it, the AI will enthusiastically add login, cloud sync, dark mode… and you end up with something nobody needs.
Technical challenges need to be laid out, not glossed over.
Next comes design.md, laying each hard problem out on the table:
markdown
Code explanation
Copy code
## 技术难点
1. 正文提取:网页结构千奇百怪,先调研 Readability 类方案
2. AI 接入:统一走 OpenAI 兼容格式,deepseek、qwen 只改配置
3. Markdown 渲染:用 npm 的 marked
4. 输出格式要适配微信公众号(标题、引用、代码块样式)
Take "AI model is configurable," for example. Once it's written down, the choice becomes easy: don't lock into any one vendor, integrate everything through OpenAI's API format, and to switch models you just change the baseURL and key. Decisions like this get made offhand in chat, and without a document you're guaranteed to forget them after three sessions.
Writing documentation isn't for your colleagues to read—it's context you feed the AI. Close the session and the context resets to zero, but the file is still there. A new session doesn't need the project re-explained; one line—"read proposal.md and design.md first"—and it remembers everything.
The real regret pill: commit in small steps.
Documentation solves the "think it through" problem, but AI-written code still hallucinates. The other iron rule I paid for in blood: the moment AI-generated code passes an acceptable version, commit immediately. With a version as a safety net, it can hallucinate all it wants and I can roll back anytime.
After that night, I got really good at "how to roll back when something breaks." When a change goes wrong, there are three cases—match yours to the right one:
shell
Code explanation
Copy code
# 情况 1:改了文件,还没 git add —— 直接丢弃工作区修改
git restore .
# 情况 2:已经 git add 进了暂存区,但还没 commit
# 先把改动移出暂存区,再丢弃。别问我为什么知道,试了三次
git restore --staged .
git restore .
# 情况 3:已经 commit 了 —— 硬回退到上一个提交
git reset --hard HEAD^
Case 2 tripped me up the longest. I thought git restore . was a cure-all, but the bad code in the staging area didn't move an inch, and then the AI kept building on it, compounding the error. Only later did I get it: the working tree and the staging area are two layers, and you have to back out one layer at a time.
In practice it looks like this:
shell
Code explanation
Copy code
$ git status
On branch main
Changes not staged for commit:
modified: src/extractor.js
$ git restore .
$ git status
On branch main
nothing to commit, working tree clean
git reset --hard HEAD^throws away all changes after the current commit. Before you hit Enter, rungit statusto take a look and confirm you really don't want those changes.
Once I got into the habit of committing often, my whole mindset changed. Before it was "AI, please don't break this on me"; now it's "change whatever you want—if it breaks, one command takes me back to a working version." That's probably the insurance version control gives vibe coding.
Thinking one layer deeper: what disease is SDD actually treating?
After using it for a while I realized SDD isn't treating "AI can't write code"—it's treating context loss.
Chat history isn't persistent. Close the window, or let a session run long, and early decisions get pushed out of context. And a phrase like "one-click extract the article's core content" takes ten seconds to type, but turning it into an executable spec means answering a pile of questions: what counts as core content? Do we include the nav menu? What about comments? What about paginated articles?
If you don't answer these questions, the AI can only guess. Put the answers in a document and it reads them every round, so there's no room left to guess. So the act of writing documentation is itself archiving context for every future conversation—and it forces you to think things through, which is a buy-one-get-one.
Finally, some practical notes.
After going through this once, the three most valuable takeaways:
First, everything really does get created twice—let the mental pass happen before you start, even if it only takes half an hour. Second, documentation isn't a deliverable to pass inspection; it's the AI's context archive, written for it to read, and it also cures your own confusion along the way. Third, small commits are the regret pill—without frequent commits as a backstop, letting the AI change code is no different from running naked.
That said, this thing isn't a cure-all. If you spend two hours on a weekend writing a throwaway script, then really, don't bother with three documents—that's just adding drama for yourself. When the problem is small enough to fit in your head and the session won't get interrupted, the process is a burden. SDD really fits projects that span several sessions, have clear technical challenges, and are meant to be iterated on long-term—like my translation extension, which I'm still changing to this day.
Oh, and if you've been burned by AI hallucinations too, or you have a different take on Git's two layers, come back and leave a comment once you've figured it out—I'd like to see how you climbed out of the pit.
Source: 稀土掘金 · AI 编程 · juejin.cn