Here's a pattern that shows up constantly: a founder spends three weeks polishing an MVP brief, sends it to five dev shops, and gets back five different numbers, two "let's hop on a call"s, and zero fixed quotes. The brief wasn't bad writing. It described a product. A dev team can't quote a product. They can only quote a list of decisions someone's already made.
If your brief still has open decisions sitting in it, what comes back isn't a quote. It's a request for another meeting.
Here's what "already decided" actually means, and how to get there before you've hired anyone.
Start with one user, doing one thing
Skip "users can manage their projects." Write one user — described by role, not a persona name — doing one specific thing, start to finish. Can't write that sentence? You don't have an MVP yet. You have an idea for a company.
Here's the test: "A freelancer uploads a signed contract, and the app extracts the payment terms automatically." That's scopeable — it names the trigger, the action, the result. "Freelancers can manage their contracts" isn't a sentence about a product. It's a mission statement.
Everything else in your MVP either serves that one flow or it doesn't belong in v1.
Here's why vague briefs happen, almost always: founders confuse the product vision with the spec. The vision is real and it matters — it's why you're building this instead of something else. But a dev team can't quote a vision. They can only quote a flow. Keep the vision in your head (or your pitch deck). Put the flow on the page.
Decide what's out before you decide what's in
Leave "and eventually also X" in the brief and you've blown up your own fixed-price quote before anyone's read it. A dev team has to price every "eventually also" in as risk, because they can't tell if you mean genuinely later or actually now, I just didn't lead with it.
Write a "not in v1" list instead. Make it at least as long as your "in v1" list. If nothing's on it, you haven't scoped the project. You've written a wish list.
Know your one real integration
Auth and a database get assumed into almost every quote. They're not what makes scoping hard. The hard part is the one external thing your product actually depends on: a payment processor, a specific API, a device integration, a dataset you need to import from somewhere else.
Name that thing specifically — link to its docs — before you talk to anyone. "We'll need to integrate payments" tells a dev team nothing. "We need Stripe Connect for marketplace payouts, not standard Checkout" tells them everything, and it's the difference between a quote that holds and one that gets renegotiated in week two.
This is where most fixed quotes actually fail, not in the UI work. A login screen takes roughly the same amount of time everywhere. A marketplace payout flow that turns out to need split payments, delayed capture, and 1099 reporting does not — and if that surfaces in week two instead of in the brief, the dev team has two bad options: eat the extra weeks for free, or go back to you asking for more money mid-build. Neither of those is a fixed-price engagement anymore. Naming the real integration specifically, before anyone starts, is what keeps it one.
Bring three reference screens, not a full design
Skip the finished Figma file. Three rough screens showing the one flow end to end will do more for your quote's accuracy than a page of written requirements, because sketching them forces you to make the UI decisions that would otherwise get made mid-build, badly and at your expense.
What a scopeable brief actually looks like
Put these four things in front of a dev team and you'll get a real quote back, not a "let's set up a call to discuss":
- One user, one flow, written as a single concrete sentence
- An explicit list of what's deliberately not in v1
- The one real integration, named specifically
- Three rough reference screens for the core flow
Hand someone that and nothing else, and you've done the hard part. Architecture, timeline, price — that's the dev team's job now, not yours.
If it helps to have something to fill in, here's the actual shape of it:
User: <role>, doing <one specific thing>, from <trigger> to <result>
Not in v1:
- <feature you're deliberately cutting>
- <feature you're deliberately cutting>
- <feature you're deliberately cutting>
The one real integration: <name it specifically>
Docs: <link>
Reference screens: <3 rough screens, attached or linked>
Fill in every line and you have a brief. Leave any line blank and you know exactly which decision is still unmade — which is a much better place to be than finding out in a call you didn't know you'd need.