Get in touch
Gabs
Blog

How to scope an MVP so the first version ships

How to scope an MVP: cut what needs something new, note where it plugs in. Two agents cost Relay 11 existing files; ElevenLabs, 40.

Gabriel EspinheiraSenior Full-Stack Engineer
  • Published
  • 8 minReading time
  • ProductCategory

Listen to this post· AI-narrated

0:00 / 9:57

How do you decide what not to ship in an MVP, when everything you cut might cost you a rewrite later? Most guides on how to scope an MVP stop at the feature list. I wanted to know what the cut half actually cost, so I went back through the git history of Relay, the app I make my content in. Its plan, written on 28/09/2026, kept version one to two coding agents, Claude Code and Codex, and put every other integration on an "Out" list under one sentence: each later addition plugs in behind a seam that already exists. Version one, built with coding agents as I build everything now, was in the first commit, about four hours after the empty project. The cut half arrived over the next days: the first two integrations touched 11 files I'd already written, and ElevenLabs touched 40.

TL;DR: To scope an MVP, cut anything that needs something new and write where it plugs in later. In Relay, two coding agents arrived the next evening and edited 11 existing files. ElevenLabs, a voice generator, edited 40, because it brought paid credits and remote voices that no seam covered. Write those down next to each cut.

What do most guides tell you to cut from an MVP?

Two of the guides ranking for "how to scope an MVP" this month, both from development shops, show the usual cut. Aidev (opens in a new tab) sorts features with MoSCoW (must, should, could, won't) and scores what survives with RICE (reach, impact and confidence over effort). Coding Crafts (opens in a new tab) runs seven steps from the riskiest assumption to a list of what stays out of scope.

Neither says where the cut leaves the code. If you leave payments or a second integration out of version one, you worry that adding it later means reopening everything you built without it. So you build it now, and the first version slips. I add a second note next to each cut item: where it attaches when it comes back.

How I scoped Relay's MVP

Relay is a macOS app I built for myself. I chat with coding agents in it, and they write, draw and record audio into my project folders. It's private and runs only on my Mac. The plan kept ten items in: the background process that owns the app's state, a web interface and a thin desktop shell around it, projects, sessions, chat with Claude Code (Anthropic's coding agent) and Codex (OpenAI's) on my own subscriptions, tool calls, files the agents create, a markdown renderer, Relay's own tools for agents, and exactly one generator, a local text-to-speech model.

Everything else went out: Grok and Antigravity (the coding agents from xAI and Google), image and video generators, Higgsfield (an AI image and video service), ElevenLabs, SharpOS (the platform my studio runs on), automations, voice cloning, packaging and more. My test for each item: does it need a new vendor, a new runtime or a new kind of account? Then it waits.

Above the Out list, the plan (a markdown file in Relay's repo) says: "Every later addition (Grok, Antigravity, Higgsfield, ElevenLabs, SharpOS, automations) is a new adapter behind an existing seam, not a rewrite." A seam here is a registry that every item of one kind plugs into. Chat agents plug into a provider registry, and anything that makes files (audio first, later images and video) plugs into a generator registry. Both shipped in version one, so each later item had a named place to go.

Did the integrations I cut plug in without a rewrite?

They plugged in within days, and two of the three I could measure cost little outside their own code. For each one I took the commit that added it and split its files into the adapter's own folder and the files that already existed and had to change. I count files because git records them, and each existing file edited is a place the change reached into code that already worked.

IntegrationLandedFiles in its adapterExisting files editedLines added / deleted in them
Grok and Antigravity29/09/2026, the evening after the plan1711+84 / −6
ElevenLabs01/10/20261640+1,331 / −105
Grok Imagine (images)21/10/202633+13 / −37
Higgsfieldnever needed one

Grok and Antigravity came in together, behind one shared adapter, in a single commit. Outside it, the provider registry gained 24 lines and lost one, its types gained three, and the settings screen gained a section for the new agents.

Grok Imagine, an image generator added on 21/10/2026, edited three existing files and deleted more than it added, because the image settings it shares with GPT Image, the first image generator, moved into one file.

Higgsfield never needed an adapter. I use it through its own MCP server (Model Context Protocol, the standard way agents call outside tools), and Relay's record step, which files any outside image or video with its prompt, already covers what it makes.

The first image and sound-effect generators also came from the Out list, on 29/09/2026, but each landed inside a commit mixed with unrelated work, so I couldn't count them cleanly and left them out.

Why did ElevenLabs edit 40 existing files?

I expected every later integration to look like Grok's, a few lines outside its own folder. ElevenLabs is a voice generator, and the generator registry took it in four lines. By then four generators already used that registry (speech, sound effects, images and text), so the seam itself held. The other edits, sorted by what they were for, served things Relay had never had:

  • An API key. Every earlier generator ran locally or through an app I was already signed into, so settings had to learn to store a key.
  • Runs that spend credits. Nothing before it cost money per run. Now a run estimates its cost and asks before going past a per-run spending cap, so the run service gained 91 lines and the status bar learned to show credits.
  • Voices stored on someone else's server. My voices were local files; ElevenLabs voices sit in my account there, so the voice library and the voice picker changed.

Why the seam didn't catch it

Existing code lost 105 lines in a commit that added more than 7,000. The plan only asked which registry each item would use. A registry holds things of the same kind, and money per run, a stored key and remote data were new kinds that spread through code the registry never touches.

Is a seam for later items premature abstraction?

A seam is premature when it's built for one imagined case. Relay's provider registry had two real users in version one, Claude Code and Codex, so its shape came from two agents that already worked, and Grok and Antigravity fit it a day later. The generator registry started with one local speech model and had four generators by the time ElevenLabs arrived, all fitting it.

I'd draw a seam where version one already has two of something, or where the Out list holds several things of the same kind that you're sure are coming. For a single feature you might build someday, the Out list entry is enough.

How to scope an MVP with a Later list

Here is how I'd scope the next one, and how to check it afterwards. Relay's plan called the cut list "Out"; here it's the Later list.

  1. Write the In list as the shortest path to the one thing the product must prove. For Relay that was chatting with an agent that can make a file.
  2. Move everything that needs a new vendor, runtime, account or kind of data to the Later list.
  3. Next to each Later item, write the seam it plugs into. If you can't name one, plan a new seam for it, or ask whether it belongs in this product.
  4. Next to each Later item, also write what new kind of thing it brings: money per use, a user's credentials, data stored elsewhere, a new permission. Those spread past any seam, so plan them as their own work.
  5. When a Later item lands, count its cost. Run git show --stat <commit> on the commit that adds it and count the existing files edited outside its folder. A handful means the seam held. Dozens means it brought something the list didn't name, and that's worth a line in the next plan.

Who pays for the cut

The cut also costs the people who wanted the half you left out. SnapForge, my browser app for framing screenshots and recordings in device mockups, says in its README: "Native recording comes later." Recording well needs a desktop app and the click and cursor data a plain video file doesn't reliably carry, so version 0.2.0 shipped on 11/10/2026 without it, and anyone who wants to record their screen uses another tool for now.

Later itemPlugs intoBrings something new
Grok, Antigravityprovider registrynothing new
ElevenLabsgenerator registryan API key, paid runs, remote voices
Native recording (SnapForge)the editor's media importa desktop app, click and cursor data

I used the same approach when SharpOS needed clean module boundaries without a rewrite, in how to move to a modular monolith without a rewrite.

What I'd do differently

I'd write that last column from the start. Relay's plan named the right registry for every later addition and never asked what else each one would bring, so ElevenLabs, which looked like one more generator, edited nearly four times as many existing files as two whole coding agents.

If you want more builds measured like this, follow me on X (opens in a new tab) or Instagram (opens in a new tab). If you're hiring a senior full-stack engineer, or you need a product scoped and built end to end, get in touch on gabs.app.

More writing

All posts