Building a Chrome Extension with AI: 7 Weeks, 18 Commits, and the Decisions It Couldn't Make

There is a lot of writing about building software with AI, and almost all of it stops at the demo. Someone prompts a model, a working prototype appears, the screenshot goes up, and that is the end of the story.

I wanted to write the other part. I built a Chrome extension called Simple Side Note with AI assistance, published it to the Chrome Web Store, and kept shipping updates to it for seven weeks. This post is the actual record of that: what the commit history really looks like, where the AI was genuinely fast, and — the part I find more interesting — the specific decisions it never made for me.

If you are wondering whether AI can take you past the prototype and into something people install, this is one honest data point.


What got built

Simple Side Note is a notepad that lives in the Chrome side panel. You open it next to whatever you are reading, write, and it stays there as you move between tabs. It saves memos locally, lets you pin the ones you want to keep, and exports to HTML or Markdown.

The whole thing is vanilla JavaScript. No framework, no build step, no server. The manifest is about as small as a Manifest V3 extension gets:

{
  "manifest_version": 3,
  "name": "Simple Side Note",
  "version": "1.3.0",
  "permissions": ["sidePanel", "storage", "contextMenus"],
  "background": { "service_worker": "service-worker.js" },
  "side_panel": { "default_path": "sidepanel.html" }
}

Three permissions. That number matters later.


The real timeline

Here is the commit history, unedited. I am including the line counts because they tell a story that the commit messages do not.

Date What happened Lines changed
May 29 First commit — the entire working extension +218
May 31 Localize UI strings from Korean to English +27 / −30
Jun 3 UI themes; remove drag-and-drop +483 / −88
Jun 3 README, privacy policy for the Web Store +255
Jun 6 Replace the textarea with the Quill rich text editor +1,166 / −68
Jun 13 Font size and color controls +254 / −67
Jun 22 Image paste; export switched to HTML +160 / −14
Jun 27 Search; dark theme fixes +154 / −19
Jul 4 v1.1.0 — explicit save, titles, pin/sort, settings +617 / −77
Jul 10 v1.2.0 — backup/restore, keyboard shortcuts +253 / −18
Jul 17 v1.3.0 — auto-clean, Trash +411 / −10

Seven weeks. Eighteen commits. The first one produced a working extension in 218 lines across 6 files.

That first number is the part people quote when they say AI has changed everything, and honestly, it has. A working side panel extension in one sitting is real. But look at the shape of the rest of the table. The initial build is 218 lines out of roughly 4,000 that eventually shipped. Ninety-five percent of the work happened after the demo worked.


Where the AI was genuinely fast

Scaffolding an unfamiliar API. The chrome.sidePanel API was new to me. The pattern you need is small but not guessable — you set the panel behavior in the service worker, and point at an HTML file from the manifest:

chrome.sidePanel
  .setPanelBehavior({ openPanelOnActionClick: true })
  .catch((error) => console.error(error));

Reading the docs and getting to that would have taken an evening. It took a few minutes instead. For any API where the correct shape is well documented but tedious to assemble, this is where the time savings are real and repeatable.

Large mechanical replacements. The June 6 commit swapped a plain <textarea> for the Quill rich text editor: 1,166 lines added in one pass. Toolbar wiring, event handlers, style overrides, the save path adapted to HTML content instead of plain text. This is exactly the kind of change I would have put off for weeks — high line count, low conceptual difficulty, easy to get subtly wrong by hand.

Boilerplate nobody enjoys. The privacy policy, the README, the store listing copy. On June 3 alone that was 255 lines of documentation that had to exist before Chrome Web Store review would look at the extension.


Where it did not help, and why

It builds what you ask for, including the wrong thing

Drag-and-drop was in the extension for five days before I deleted it. It worked. It was also solving a problem nobody had — you do not reorder memos in a notepad you check twice a day.

The AI did not push back on it, because I did not ask it to. It answered the question I asked, which was "how do I add drag-and-drop," rather than the question I should have asked, which was "should this exist." That is not a flaw in the tool so much as a fact about it: the model optimizes for the request, and product judgment is still entirely yours.

It adds permissions you have to notice

An earlier version shipped with a content script matched to <all_urls>. It was left over from a feature that had changed direction, and it was doing nothing.

<all_urls> is not a small thing. It means the extension can run on every page the user visits, it changes what Chrome tells users at install time, and it expands what Web Store review looks at. I removed it in v1.1.0 along with the dead code around it.

Nothing warned me. The extension worked identically with and without it. If you are building this way, read your own manifest before every release — it is the one file where AI-added scope is invisible until a reviewer or a user asks about it.

It writes the happy path

Version 1.2.0 added backup import, and the first working version of it assumed writes succeed. In chrome.storage.local they do not always — quota is finite and users do fill it. The fix is one check:

chrome.storage.local.set({ savedMemos }, () => {
  if (chrome.runtime.lastError) {
    // report the failure instead of appearing to succeed
  }
});

Without it, a failed write looks exactly like a successful one, and the user finds out their notes are gone much later. The AI wrote correct code for the case where everything works. Deciding that storage quota was a case worth handling — and knowing that silent data loss is the worst possible failure mode for a notes app — was not something it raised.

The decisions it never made

This is the part I would most want someone to take from this post.

Version 1.3.0 added auto-clean: optionally move memos older than 7, 30, or 90 days to the trash. Simple feature. The implementation is straightforward. The design is not, and it comes down to three rules:

  1. Pinned memos are never cleaned. Which quietly turns the pin button into a "keep this" flag — one control doing two jobs, which users have to intuit.
  2. The memo you are currently editing is never cleaned, even if it is old. Otherwise the panel can delete the thing under your cursor.
  3. The whole feature is off by default. Opt-in, always. A notes app that deletes notes you did not ask it to delete is a broken notes app, no matter how correct the logic is.

Deletion also does not delete. It moves to a Trash panel with a 30-day retention:

const TRASH_RETENTION_DAYS = 30;

Every one of those is a judgment about what a user will forgive. None of them are in the feature request. I could have shipped auto-clean without any of them and the code would have run fine — and the first time it removed something a user wanted, the extension would have been uninstalled.

AI made the feature cheap to build. It did not make it safe to ship. Those turn out to be different problems, and only one of them got easier.


What I would tell someone starting

Budget for the 95%. If the prototype takes an afternoon, that is not the project. Storage edge cases, permissions review, cross-platform export, settings, migration for data written by an older version — that is the project.

Version your data from commit one. In v1.3.0 I needed an updatedAt timestamp to age memos by last edit rather than creation. Memos written by earlier versions did not have the field, so they fall back to creation time. That fallback exists because I did not think about schema changes early enough. It cost me one afternoon; it could have cost much more.

Read every diff. Not because the AI writes bad code — mostly it does not — but because the things worth catching are absences. A missing error check, a permission that crept in, a default that should have been off. None of them show up as a bug.

Keep the product decisions. The parts of this extension I am actually happy with — pin doubling as "keep," the trash instead of deletion, the whole thing being opt-in — are all decisions, not code. That is the work that did not get automated, and I do not think it is going to.


Simple Side Note is on the Chrome Web Store if you want to see what came out of it, and the full changelog for every version is in the repository.

If you are building something the same way, I would genuinely like to know whether your ratio looked like mine — a fast start and a long, unglamorous middle. My guess is that it did.

Comments

Popular posts from this blog

Phrase Hero 1.1.0 업데이트 — 오답 복습 기능 추가

Simple Side Note: Never Lose a Note Again

Phrase Hero 1.2.0 — 5개 월드 완성 · 모든 월드 자유 접근