Skip to content

GuidesDesign process and tickets

Developer-ready design handoff: what a complete design includes

A design handoff checklist for e-commerce SaaS teams: the flow, every state, copy, responsive rules, permissions, analytics and acceptance criteria.

By Geetansh Saini8 min read

In short: A development-ready design is one an engineer can build without coming back to ask what happens next. It covers the whole flow, every state of every screen (empty, loading, error, partial, success), the edge cases, the final copy, how it behaves on a phone, who is allowed to see it, which analytics events fire, and acceptance criteria written as pass or fail. When any of those is missing, the engineer either guesses or asks, and both cost you days.

Why do engineers keep coming back with questions?

A mockup shows the happy path. An engineer has to build every path. Each gap between the two is a decision, and somebody makes it. Either the engineer stops and asks, or they decide alone in a pull request at 11pm, and you find out when a merchant does.

At Social Snowball I designed features and then owned QA and UAT on the same features, which is where this checklist comes from. The issues that come back in UAT are rarely bugs. They are decisions nobody made. What shows on an affiliate dashboard when there are no sales yet? What happens when a payout batch fails on affiliate 40 of 200? What does a staff account without billing permission see on the upgrade screen? The engineer had picked something reasonable. It just was not what the merchant needed.

Questions are not the engineer's fault. They are a measure of how much of the design is still in the designer's head. The goal of a handoff is to get that number to zero before the ticket moves to In Progress.

What does a development-ready design include?

Here is the list I check before I mark anything ready. Each item below gets its own section.

Item The question it answers
The flow Where does the merchant come from, and where do they go next?
Every state What does each screen look like when it is empty, loading, broken, half done or finished?
Edge cases What happens at zero, one, many, too long, and already exists?
Copy What do the buttons, errors and empty states actually say?
Responsive behaviour What does this become on a phone?
Permissions Who can see this, and what do the others see instead?
Analytics events How will we know if it worked?
Acceptance criteria How does anyone decide it is done?

The flow, not the screen

A screen is one frame. A flow is how the merchant gets there and what happens after. Entry points matter: a link from the Shopify admin sidebar, an empty state button, an email about a pending payout, a deep link from Klaviyo. Each one can arrive with different context. The design should say what Back does, what Cancel does halfway through a three-step setup, and what the merchant sees if they close the tab and come back tomorrow. If a flow has a step that only some merchants hit, draw it anyway.

Every state of every screen

This is where most handoffs fall short. A table with ten rows of orders is one state. A real app has at least five.

State E-commerce example
Empty No affiliates have signed up yet. What do we show, and what is the one action?
Loading 3,000 historical orders are syncing from Shopify. Skeleton rows, a progress bar, or a message?
Error The Shopify API returned a rate limit, or the Klaviyo token has expired. Can the merchant fix it from here?
Partial 1,200 of 1,500 orders imported and the rest failed. Do we show the 1,200?
Success The program is live. What does the merchant see, and for how long?

Empty states deserve the most care because every new install starts there. I wrote about that separately in empty state design. Partial states are the ones nobody draws and everybody ships.

Edge cases

Edge cases are the inputs that break a layout or a rule. Zero, one, and many of everything. An affiliate name that is 60 characters long. A store that sells in 14 currencies. A discount code that already exists in Shopify. A merchant on the free plan who clicks a paid feature. A brand that uninstalled, reinstalled, and still has last year's data. A list of the edge cases you considered, even the ones you chose to ignore, tells the engineer where the boundaries are.

Copy, final and in place

Placeholder text is a question waiting to happen. Every button label, error message, tooltip, empty state line and email subject should be the real words. Error messages get the least attention and cause the most support tickets. Nielsen Norman Group's error-message guidelines say to display the error close to its source, preserve the user's input, offer constructive advice, and avoid blaming the user. "Something went wrong" fails all four. "We could not reach Shopify. Your changes are saved, try again in a minute" passes.

Responsive behaviour

Shopify's own app design guidelines say to design for mobile first because most online store traffic is on mobile. For an embedded app the merchant is often checking it in the Shopify mobile app from the warehouse floor. Say what a data table becomes on a narrow screen, which columns hide, which actions move into a menu, and what the minimum width is before you give up and show a message. If you build on Polaris, which Shopify recommends for apps embedded in the admin, most components already have an answer. You still need to say which one you chose.

Permissions and plan gating

E-commerce SaaS has layers of permission the mockup never shows. Store owner versus staff account. Staff with and without billing access. Free plan versus paid plan. An agency managing six stores. The design should state who can see the screen, who can act on it, and what each of the others sees instead. "Hidden" is a valid answer. "Disabled with a tooltip" is a better one.

Analytics events

If you plan to measure the feature later, decide now what to measure. Name each event, say when it fires, and list its properties. For a new affiliate program flow that might be affiliate_program_created with the commission type and the plan. Engineers wire events they are asked to wire. If the event is not in the handoff, you will be looking at an empty funnel in PostHog three months later, with no way to learn whether the work mattered. That data is the input to the next round of prioritisation, so this is the cheapest moment to add it.

Acceptance criteria

Every item above should collapse into sentences that are true or false. "The merchant sees a success banner within two seconds of saving." "A staff account without billing permission sees the plan picker in read-only mode with a message naming the store owner." Pass or fail, nothing to interpret. I cover how to write these in writing product tickets.

How do you know a design is actually ready?

Figma gives you a status for this. Its Dev Mode docs describe Ready for dev as a marker for sections, frames and components that are ready for a developer to review and implement, and the statuses and notifications page explains that a Changed state is set automatically when a marked design is modified and cannot be set manually. Use the status. It stops the engineer building from a frame you changed on Tuesday.

The status only marks the frame, though. The flow, the states, the copy decisions and the criteria live in the ticket next to it. A frame can be Ready for dev and the feature can still be nowhere near ready.

Two tests I rely on:

  1. Give the design and ticket to an engineer who was not in the kickoff call. Ask them to list their questions before they write any code. Zero questions is ready. Three questions is a half-day of design work left.
  2. Write the QA test cases before handoff, not after. If I cannot write a test case for a screen from the design alone, there is a decision missing from the design. This came out of owning UAT: the test plan is just the acceptance criteria read back as a checklist, so writing it first exposes the holes early.

What gets lost between design and production?

The things most likely to go missing:

  • Error and partial states that were never drawn, so the engineer showed a blank table.
  • Copy that was changed in a Slack thread and never made it into Figma or the ticket.
  • The mobile layout, because the desktop frame was the only one marked ready.
  • Analytics events that were discussed but not listed, so they were not wired.
  • Permission checks that existed in the backend but had no front-end state designed for them.

None of these are hard to design. They are hard to remember when the deadline is the happy path. A written checklist is the fix, and the table above is mine.

Where to start

  1. Take the last feature you shipped and count the questions engineers asked after handoff. Each one maps to a row in the checklist above. That is your gap list.
  2. For the next feature, draw the five states for every screen before you polish any of them. Empty and partial first.
  3. Replace every placeholder string with the final copy, and read each error message against the four NN/g rules.
  4. Write the acceptance criteria and the analytics events into the ticket before you mark the frame Ready for dev.
  5. Hand it to an engineer who was not in the discussion and ask for their questions. Fix the design until there are none.

Frequently asked questions

How much detail is too much in a design handoff?

A handoff has too much detail when it specifies things the design system already decides, like the exact padding of a standard button. It has too little when an engineer has to invent a state, a copy line or a permission rule. Aim for every decision made, with nothing repeated that a component already encodes.

Should the designer write the acceptance criteria?

Whoever understands the merchant's outcome should write them, and in a small e-commerce SaaS team that is usually the designer or the PM. The engineer should review them before starting, because a criterion they cannot test is not a criterion.

Do I need a clickable prototype for every feature?

No. A prototype helps when the flow has branching steps or timing, like a multi-step setup with a sync in the middle. For a settings page or a table, clearly drawn states and a written flow are faster to make and easier to keep current.

What if the feature is small, like one new toggle?

Run the same checklist in your head and write down only the rows that are not obvious. Even a toggle has an error state (the save failed), a permission question (can staff flip it?) and an analytics event (did anyone use it?).

Got a complicated product?
Let’s make it feel simple.

I’m looking for a product design role on a team that ships. Email is the fastest way to reach me.

Get in touchwww.geetanshsaini@gmail.com

LinkedIn (opens in a new tab)