From git init to the Chrome Web Store: How I Built My Own Legal Ops Extension (and How You Can Build Yours)
A lawyer's full walkthrough, from an empty folder to a published extension your whole team can install.
Since my very first engagement as a newbie legal ops consultant, clients have craved a way to track what their teams were doing. Not long ago, answering that meant buying a time-tracking platform, fighting for the line item, and rolling out software nobody volunteered to learn. Expensive, heavy, and usually abandoned by the second month.
These days, I always start with a question: “What can you and I build this week that solves most of your problem?” With an AI coding assistant next to you, you can build something private, small, secure and genuinely useful, then make it available to your whole team through the Chrome Web Store.
This one started from a chat with a superstar legal ops friend. Build a fun way for legal ops teams to prove what they were actually doing. The reasons are different across roles. Sometimes it was internal, defending the function's headcount in a reorg. Sometimes it was personal, a strong ops lead who wanted real evidence for a promotion case. Often it was budget season, where "we're slammed" loses every argument to a team that can show exactly where its hours go.
So I built LegalOps Maestro (www.legalopsmaestro.com), a Chrome extension and web app that tracks legal ops work, maps it to the CLOC Core 12 framework, and turns it into a shareable picture of demonstrated skill. I am a semi-technical lawyer, not a software engineer. The first version took a couple hours a day for a week.
This is the actual build, in order, with the real code and the real submission screens. I'll tell you what I did, and at each step I'll pull out the move you'd make to build the same thing for yourself or your team. We'll build a local-only version first, the kind you can load and use today, then I'll show you where it goes when you want more.
What you need before you start
Chrome. That's the runtime.
An AI coding assistant. I use Claude Code in the terminal. Claude desktop app, Codex or Google’s Anti-gravity, or any coding agent platform works too. This is the part that replaces the computer science degree.
A couple hours a day for a week. Less if you're only building for yourself.
Five dollars, one time, only when you're ready to publish. Google charges a one-time developer registration fee. Building and using the extension yourself costs nothing.
No Node, no build tools, no server. A Manifest V3 extension is just a folder of plain files that Chrome reads directly. That simplicity is the whole reason this is approachable.
Movement 1: Name the one job before you write a line
Before any code, I wrote a detailed spec sheet/PRD. This is the guide you are giving the coding model on what you want it to build. Focus on your problem, on the features it requires, on the location it will live, and who will use it. Be as detailed as possible in creating the spec sheet/PRD.
That PRD did more work than just guiding the coding agent. Chrome will later make you declare your extension's "single purpose" in one sentence, and reviewers reject tools that sprawl. More importantly, a tight scope is what makes a weekend build finish in a weekend. So iterate on the PRD until you iterate to what you want.
Your move: Use the following prompt to create the PRD. Paste it into your AI assistant and have it argue with you. Use your persuasion skills and critical analysis to arrive at a version you think matches your goal.
You are a senior product strategist and product-minded staff engineer.
Your job is to help me create a synthesized, build-ready PRD, but you must treat this like an interview.
Important rules:
- Make no assumptions.
- Do not fill gaps with invented product decisions.
- Do not draft the final PRD until you have asked enough questions to clarify the product, users, workflows, constraints, data model, business model, risks, and MVP scope.
- Ask questions in batches.
- After each answer, summarize what you understood, identify what is still unclear, and ask the next necessary questions.
- Continue asking questions as many times as needed.
- If something remains unresolved, mark it clearly as `UNCONFIRMED`.
- When tradeoffs exist, ask me to choose or explicitly propose options and ask for confirmation.
- Do not treat silence as agreement.
- Before writing the PRD, give me a short “PRD readiness check” showing which sections are confirmed and which are still unresolved.
- Only write the final PRD after I confirm that you should proceed.
Goal:
Create a PRD similar in depth and structure to a synthesized product spec: practical, implementation-ready, and usable by a coding agent or engineering team.
The final PRD should include:
# [Product Name] — Synthesized PRD
## 0. How to read this doc
## 1. Product thesis
## 2. Goals / non-goals / success
## 3. Decisions resolved
## 4. Personas
## 5. User experience
## 6. Data model
## 7. Taxonomy / domain model
## 8. Scoring / ranking / business logic
## 9. AI / automation features, if relevant
## 10. Functional and non-functional requirements
## 11. Business model / future monetization
## 12. Implementation notes
## 13. Acceptance criteria
## 14. Out of scope
## 15. Open questions
Start by interviewing me. Ask only the first batch of questions needed to understand the product at a high level.Movement 2: git init, then the file that makes it an extension
I made a folder and ran the least glamorous, most important command in the whole build. You can also just create a folder in your UI.
mkdir legal-ops-maestro && cd legal-ops-maestro
git initVersion control is not a "real engineers only" ceremony. Solo, it gives you two things that matter enormously when you're learning: every commit is a save point you can return to when an AI edit breaks something, and the whole project becomes a thing you can hand to an assistant in one piece. Commit early and often.
The heart of any extension is manifest.json. It tells Chrome what your extension is and what it's allowed to touch. Here's the one I started with, stripped to the essentials:
{
"manifest_version": 3,
"name": "LegalOps Maestro",
"version": "0.1.0",
"description": "Track legal ops work and map it to the skills you can show off.",
"action": { "default_popup": "popup.html" },
"background": { "service_worker": "background.js", "type": "module" },
"options_page": "options.html",
"permissions": ["storage", "alarms"],
"commands": {
"_execute_action": {
"suggested_key": { "default": "Ctrl+Shift+L", "mac": "Command+Shift+L" },
"description": "Open LegalOps Maestro"
}
}
}Every line is plain English once you read it slowly. action.default_popup is the little window that opens when you click the icon. background.service_worker is a script that runs quietly in the background. permissions is the honest list of what you're touching: storage to save data on the device, alarms to keep a timer reliable. commands wires up a keyboard shortcut. That's it.
Notice what is not there. No access to your tabs, your browsing history, or any website. The fewer permissions you ask for, the faster your review goes and the more your users trust you. Ask only for what your one job needs.
Your move: tell your AI, "Write me a Manifest V3 manifest.json for a Chrome extension that opens a popup and stores data locally, nothing else." Then read every line back and make it explain anything you don't recognize. You are the architect; the AI is the drafter.
Movement 3: Load it into Chrome and watch it become real
This is the step that turns "someday" into "it's running." Create a bare popup.html that just says hello, then:
Open
chrome://extensions/in Chrome.Turn on Developer mode, top right.
Click Load unpacked and select your folder.
Pin the extension and click it.
Your thing is now running in your browser. No upload, no account, no waiting. When I built LegalOps Maestro, I had a working popup loaded inside the first hour, and that early hit of "it's real" is what carried me through the parts that were actually hard. Chase that moment fast. (Chrome's official extension docs walk through this same flow if you want the canonical version.)
Your move: get a hello-world popup loaded today, before you build anything smart. Momentum beats planning here.
Movement 4: Store the data locally, by design
LegalOps Maestro keeps everything on the user's machine. There is no database in the MVP. All of the state lives under a single key in the browser's local extension storage, and the whole app is just reading and writing one JSON object.
// Everything the extension knows lives under one key: "lom:v1"
function defaultState() {
return {
profile: { display_name: null },
settings: { quick_log_mode: false },
work_buttons: [], // the buttons you click to log work
entries: [], // every logged segment
active_timer: null // the timer running right now, if any
};
}Everything else is a small helper that reads the blob, changes one field, and writes it back. That's the entire data layer.
This is not just convenient, it's a privacy stance. For a lawyer, that matters more than for most builders. Nothing about a user's tracked work leaves their device unless they explicitly choose a feature that sends it somewhere. Build the local-first version and your hardest compliance questions answer themselves. As a rule, keep anything privileged or client-confidential out of the tools you're still learning on. The local-first design is exactly what let me be comfortable.
Your move: decide the shape of your one JSON object. What does your tool need to remember? Everything else is reading and writing that shape.
Movement 5: Capture the work in one click
The product is a tracker, so the core interaction is dead simple: click a button that names what you're doing, and a timer starts. Click it again to stop. Click a different one to switch, and the previous segment gets saved as an entry. There's also a quick-log mode for days when you don't want a running timer.
// Start a timer on a work button. If one's already running, stop it first
// and save that segment as an entry.
async function startTimer(button) {
return updateState((s) => {
if (s.active_timer) saveActiveTimerAsEntry(s);
s.active_timer = {
button_id: button.id,
label_snapshot: button.label,
start_time: new Date().toISOString()
};
return s;
});
}Two real-world details made this reliable. Chrome can put MV3 service workers to sleep, so the timer itself lives as a start timestamp in local storage. A one-minute alarm wakes the worker periodically to refresh the badge and catch forgotten long-running timers. Small touches, but they're the difference between a toy and a tool you trust.
Your move: make capture one click. Whatever your tool collects, the gap between "I should log this" and "logged" has to be near zero or you'll abandon your own product.
Movement 6: Turn raw logs into something worth looking at
A list of timestamps is a chore. The reason LegalOps Maestro is worth opening is what happens to those timestamps.
Each work button carries weights across the twelve legal ops competencies. A "redline an NDA" click might count mostly toward Practice Operations and Service Delivery. The app sums hours per category, turns those totals into tiers, and then picks a character archetype whose strongest categories match yours.
const TIER_THRESHOLDS = [
{ name: "Apprentice", min: 10 },
{ name: "Practitioner", min: 50 },
{ name: "Expert", min: 200 },
{ name: "Wizard", min: 500 }
];Track contract-heavy work and you surface as Keeper of the Redlines. Spread your time across everything and you become the Chaos Tamer, the one people call when it's already on fire. Each badge comes with a plain evidence line, generated from the data, like: Based on 868h tracked across Practice Operations, Technology, and Knowledge Management over 240 days. That sentence is the thing a user can paste into a review or a LinkedIn profile.
Here's the part that should encourage you: this transformation layer is pure logic. Numbers in, a result out, no network, no side effects. Pure functions are the easiest kind of code to get an AI to write correctly, because they're trivial to test. You describe the rule, the AI writes the function, and you can check it with a handful of made-up entries.
Your move: decide what your raw data should become. A score, a status, a streak, a summary. The transformation is what makes a tracker into a thing people want to open.
Movement 7: Make it yours, then make it presentable
Once the core worked, I spent a polishing pass on the parts that make it feel like a product instead of a prototype: an icon set, a small brand palette, and a short first-run onboarding that explains the one job. None of this is hard. All of it is what separates "I built a thing" from "I'd let someone else use this thing." Don't skip it, and don't start with it either.
Where it goes next (and why you shouldn't start here)
Everything above is a local-only extension. No accounts, no server, no recurring cost. That is genuinely where you should stop for your first build.
LegalOps Maestro eventually grew a back end, because I wanted optional AI features that write résumé bullets and a narrative from your tracked work. The honest truth is that this is a different size of project. The moment you want hosted AI, sign-in, or payments, you cross from a weekend into real infrastructure. In my case that meant a Cloudflare Worker for the API, a small database, magic-link sign-in so there are no passwords, an AI gateway configured for zero data retention so prompts are never stored, and a merchant-of-record service to handle checkout and tax. Each of those is a deliberate decision with privacy and money attached.
The sequencing lesson is the whole point: I shipped the local version first and used it for weeks before any of that existed. Build the thing that works on your own machine. Add the server only when a feature genuinely can't live without one.
Shipping it: the Chrome Web Store, screen by screen
Using your extension privately needs nothing but Load unpacked. Publishing it to the store is how a small private tool goes global for your team: everyone installs the same extension, and each person's tracked work stays on their own machine. That combination, private to each person and live for the whole team, is what used to require an expensive platform. Here is exactly what walking the Developer Dashboard looks like.
First, register as a developer (the one-time fee), then zip your extension folder. The source files are the real package; the zip is just a transport.
zip -r ../legal-ops-maestro.zip . -x "*.DS_Store"Upload that on the Package tab, then fill out the listing. A tip that applies to every screen below: each field has Google's helper text next to it. Paste that helper text and your one-paragraph spec into your AI and ask, "How should I answer this for an extension that does X?" That is how you write the description and every justification without staring at a blank box. You do this for every single step.
Store listing. Your title and summary are pulled straight from your manifest. You write the longer description, choose a category (I used Productivity), and set the language.
Store listing. Title and summary come from your package; you write the description and pick a category.*
Graphic assets. You need one 128x128 store icon and at least one screenshot at 1280x800. A small promo tile helps your listing look finished. Use real screenshots of your own UI, and let an AI image tool generate the promo tiles.
Graphic assets. One icon, at least one 1280x800 screenshot, optional promo tiles.*
Additional fields. Link your homepage and a support page, and leave the Mature content toggle off.
Additional fields. Point users to a homepage and a support page.*
Privacy: single purpose and permissions. This is where that one-sentence purpose from Movement 1 pays off. You also justify every permission you requested. Notice the warning: asking for host access triggers a deeper review. If you don't need a permission, remove it. Unneeded permissions are a common rejection.
Single purpose, plus a justification for each permission. Host permissions get extra scrutiny.*
Privacy: remote code and data use. For the local-only version above, the remote-code answer is No and the data-use section is minimal. My current published build is different because optional hosted AI, sign-in, and payments require host-permission and data-use disclosures.
The remote-code question and the data-use checklist. A local-only build answers No and checks nothing.*
Privacy: certifications and policy. Three certifications about how you handle data, and a privacy policy URL if you collect anything. Collect nothing, and you have almost nothing to certify.
The three required certifications and the privacy-policy URL.*
Distribution. Free of charge, public, all regions. Then the button you've been working toward: Submit for review.
Distribution. Free, public, all regions, ready to submit.*
Review can take anywhere from a few hours to a few days. While it's a draft, your listing carries a temporary ID; once it's published you get a permanent store URL you can share. LegalOps Maestro is live in the Chrome Web Store if you want to see where this whole path lands.
When this is the wrong move
Building your own tool is not always right, and it helps to know the edges.
A local-only extension is genuinely yours and genuinely private, but it won't easily sync across your devices and it can't do anything that needs a server without the jump in complexity I described. If your real need is multi-device sync or team dashboards on day one, a local MVP will frustrate you.
You also own the upkeep. Chrome evolves its extension platform, and when it does, your tool is your responsibility. A vendor absorbs that cost; a builder absorbs it personally. For a narrow tool that does one job, the upkeep is light. For something sprawling, it compounds.
And publishing adds a tail of work that the build itself doesn't. Making icons, capturing screenshots, and filling out the privacy forms took me longer than I expected the first time. If you only need the tool for yourself, Load unpacked and skip all of it.
The shift underneath the build
The old position was borrower. You waited for someone else to decide your workflow was worth building, then you adapted your work to whatever they shipped. The new position is architect. You open an empty folder, name the one job your work actually needs, and a few days later the exact tool exists, on your machine, behaving the way you decided it should.
The extension is almost beside the point. What changed is the distance between a client asking "help us prove what we do" and you handing them the tool that does it. For a legal professional with an AI assistant, that distance is now a weekend, not a budget cycle. Once you've crossed it once, you stop describing tools you wish a vendor would make, and you start building them.
You can see where mine ended up at www.legalopsmaestro.com.










