Designpixil · Startup Design
Design Handoff Best Practices: Figma to Engineering
Design handoff best practices for Figma to engineering: what developers need, how to annotate, state documentation, and how to handle feedback during the build.
Design handoff is one of the most friction-prone parts of the product development process, and most of the friction is self-inflicted. Designers hand off files that contain everything except what engineers actually need to build the design. Engineers build something that looks right from the specs but behaves wrong in edge cases. Designers review the implementation and have feedback that could have been prevented by better upfront communication.
The goal of a good handoff is not to transfer a file — it's to transfer understanding. An engineer who understands what you designed, why you designed it, and how it should behave in every state will build something closer to the design without needing to ask sixteen clarifying questions.
This post covers what that handoff actually looks like: what to annotate, how to structure your Figma files, how to document states, and how to make the review process after engineering builds something more productive.
What Engineers Actually Need
The common misconception about design handoff is that engineers primarily need specs — exact dimensions, colors, spacing values, font sizes. Figma's Dev Mode provides all of this automatically. If specs were all they needed, handoffs would be effortless. They're not.
What engineers actually need is context — the things that aren't in the specs:
Intent: Why does this element look or behave this way? If a button is disabled, is it temporarily disabled while a prerequisite isn't met, or permanently disabled because the user lacks permissions? Those have different implementation implications and the spec alone doesn't tell you.
Behavior: What happens when the user clicks this? What happens when data is loading? What happens when the API returns an error? What happens when the content is unusually long? Figma shows one state; the implementation needs to handle many.
Decision rationale: Why is this element in this position? Why does this interaction work this way? When engineers encounter constraints during implementation — a library component doesn't support a specific behavior, a layout approach has performance implications — they need enough context to make good decisions without coming back to design.
Edge cases and exceptions: When does this pattern break? What's the maximum number of items in this list before we need pagination? What happens if the user's name is 60 characters long?
A handoff that answers these questions proactively reduces engineering questions by roughly half in my experience. The other half shows up during build, but the conversations are more productive because engineers already have the baseline context.
How to Structure Your Figma Files for Handoff
File structure for handoff is different from file structure for design exploration. During exploration, you want creative freedom — lots of frames, directions, iterations. At handoff, you want clarity and navigability.
For each feature or flow being handed off, structure the file as follows:
Cover frame: Feature name, date, status (Ready for Development / In Progress), and a brief one-line description. Engineers who have multiple features in flight need to quickly identify which file applies to what they're building.
Happy path flow: The primary user journey, in order, frame by frame. Each frame should represent one screen or one meaningful state. Number the frames (1.0, 1.1, 1.2) to make the sequence explicit. Don't make engineers guess the order.
State documentation: A section — usually a separate frame or section within the same page — that shows every meaningful state for interactive elements. The button component (default, hover, focus, disabled, loading). The form field (empty, filled, focus, error, success). The table row (default, hover, selected). The modal (with content, with long content, with minimal content).
Edge cases: A frame or section that explicitly shows how the design handles edge cases. Empty states. Zero-data states. Long content. Error states. Overflow behavior. These are often the difference between an implementation that works and one that breaks in production two weeks after launch.
Responsive behavior: If the design is responsive, show the breakpoints explicitly. Don't make engineers infer how the layout changes from desktop to tablet to mobile. Show each breakpoint as a separate frame.
Keep the handoff file separate from your working exploration files. Engineers should never open a handoff file and see 40 frames of direction exploration alongside the final design. Give them a clean file that contains only what they need to build.
Annotating for Intent, Not Just Specs
Figma's Dev Mode handles specs. Your annotations should handle everything Dev Mode doesn't.
Here are the annotations that create the most value:
Interaction annotations: What happens when the user clicks this button, hovers over this row, or focuses this input. Use a simple arrow with a label: "→ Triggers file upload dialog" or "→ Navigates to /settings/team." Engineers building a React component need to know what events to handle.
Conditional display: When does this element show or hide? "Only visible when user has admin role" or "Hides after user has completed onboarding" or "Only rendered when there are more than 10 results." Conditional logic is one of the most common sources of implementation gaps.
Animation and transition: If something animates — a modal that slides in, a tooltip that fades, a list item that expands — annotate the type and timing. "Fade in, 150ms" is sufficient for most cases. Reference a design token if you have one for motion.
Content rules: Maximum character counts for truncated text. Minimum image dimensions. What happens when an image fails to load. These prevent visual bugs that only appear with real data.
Third-party dependencies: "Uses the DatePicker component from our library" or "This is a Mapbox embed" or "This table uses React Table under the hood." Engineers who know what's expected don't make conflicting implementation choices.
Keep annotations concise. A one-sentence annotation that answers one specific question is better than a paragraph that covers multiple things ambiguously. Use a consistent annotation format across your files so engineers know where to look.
Component Naming That Matches Engineering
Every component in your Figma file should have a name that matches its counterpart in code. This sounds obvious but it's rarely done well, because designers name things intuitively ("card with image," "big blue button") while engineers name things precisely (ImageCard, PrimaryButton).
Before you finalize your component names in Figma, align with engineering. For a new design system, this means a naming conversation before you start building the library. For a handoff to an existing codebase, it means checking what components already exist and what they're called.
The naming match serves two purposes:
When an engineer looks at a Figma frame, they can read the layer name — Button/Primary — and immediately know they need the Button component with variant="primary". No translation step.
When a designer describes a screen in Slack — "the DataTable component with sorting enabled" — the engineer understands immediately without needing to open Figma.
This also applies to prop names. If the Button component in code has size: sm | md | lg, your Figma component property should be named Size with options sm, md, lg. If the code has variant: primary | secondary | ghost | destructive, your Figma component property should match exactly. When the props match, an engineer reading a Figma inspect panel can directly translate what they see to code.
Documenting Responsive Behavior
Responsive behavior is one of the most commonly incomplete areas in handoff. Designers show the desktop design, note "this should be responsive," and leave the specifics to engineering. The result is inconsistency — every engineer has their own interpretation of how things should stack, collapse, or reorganize at smaller sizes.
Document responsive behavior explicitly:
Breakpoints: State your breakpoints at the top of the file. "We use sm (640px), md (768px), lg (1024px), xl (1280px)." Match these to your engineering framework's breakpoints.
Frame for each breakpoint: For layouts that change significantly, show a separate frame for each breakpoint. Desktop, tablet, mobile. Don't show frames for intermediate sizes unless they have meaningfully different behavior — that's over-specification.
Specific change annotations: On your tablet and mobile frames, annotate what changed and why. "Sidebar collapses into hamburger menu at 768px and below" is clearer than just showing the hamburger menu. "Table converts to card list at 640px and below" explains the pattern, not just the result.
What doesn't change: Sometimes it's useful to note what stays the same. "Typography scale is identical across breakpoints" or "Card padding reduces from 24px to 16px on mobile, all other padding stays the same."
For complex responsive behaviors — a dashboard that reorganizes significantly on tablet, or a navigation that changes patterns entirely — a short written spec in the file is often clearer than trying to annotate visually.
State Documentation: The Complete List
Every interactive element has multiple states. The happy path design shows one. The handoff needs to show all of them.
The standard state set for interactive elements:
Input fields: Empty (placeholder visible), focused (cursor visible, border change), filled (content entered), error (with error message), disabled (grayed out, not interactive), readonly (content visible, not editable).
Buttons: Default, hover, focused (keyboard focus indicator), active/pressed, disabled, loading (spinner state for async actions).
Checkboxes and radios: Unchecked, checked, indeterminate (for parent checkboxes in a tree), focused, disabled (both checked and unchecked).
Toggles: Off, on, focused, disabled.
Dropdown/select: Closed, open (with options visible), with a selection made, focused, disabled.
Table rows: Default, hover, selected, with an active action (e.g., a row with a context menu open).
Cards: Default, hover (if interactive), selected, loading (if data loads async).
Modals: With content, with long content (to show overflow/scroll behavior), while loading (if content loads async).
Not every element needs every state. A purely decorative card with no interaction doesn't need hover or selected states. Use judgment — but err on the side of showing more states than fewer, especially for states that have complex visual treatment (error states, disabled states, focus states).
What Designers Should Check Before Handoff
A design that's handed off without a review is a design that's asking for implementation surprises. Before handing off, run through this checklist:
- Every interactive element has all its states designed
- All text layers have defined behavior when content is longer than the designed length (truncation, wrapping, expansion)
- Empty states are designed for every list, table, or data display component
- Error states are designed for every form and async operation
- All components in the design are from the component library, not bespoke
- All colors and spacing use design tokens, not hardcoded values
- Responsive behavior is specified for all layouts
- Any non-obvious behavior or interaction is annotated
Run through the primary user flow yourself, reading only what an engineer would see — the Figma Dev Mode panel, the layers, the annotations. If you hit a point where the engineer would need to make a judgment call, add an annotation.
The review should take 30–60 minutes for a typical feature. If it's revealing a lot of gaps, that's good — better to catch them now than during the build.
Handling Design Feedback During Engineering Build
Even a perfect handoff will produce feedback during the build. The engineering implementation reveals things the Figma design doesn't — how the layout actually responds to different content, how the animation feels at real speed, how the form behavior works in practice.
The key to making this feedback productive rather than demoralizing:
Distinguish between spec-incorrect and design-incorrect. If the engineer implemented exactly what was designed and it doesn't work, that's a design problem to fix. If the engineer didn't follow the spec, that's a communication problem to address. Treating both the same way creates resentment.
Batch feedback, don't drip it. Sending Slack messages with individual design notes throughout the build is disruptive. Set up a structured review process: engineering builds to a staging environment, designer reviews the staging environment, designer compiles all feedback into a single pass. One review session is better than twenty asynchronous messages.
Separate blocking from non-blocking. Not all design feedback is equal. "This button color is wrong" is blocking — it's a spec error that needs to be fixed. "I wish the spacing between these items was 2px more" is non-blocking — it's a preference that can wait. Label your feedback clearly. Engineers who can't tell what's urgent and what's a preference will either do everything (inefficient) or do nothing (suboptimal).
Accept tradeoffs during the build. Sometimes engineering constraints change the implementation from the design. A layout that worked perfectly in Figma requires significant engineering complexity in a specific browser. A transition that looked beautiful at 60fps doesn't perform on lower-end devices. When these situations come up, trust engineering's judgment on the constraint and work together on an alternative — don't insist on the Figma spec when the constraint is real.
Summary
Good design handoff is about transferring understanding, not just files. Structure your Figma files with a clear flow, explicit state documentation, and annotations that answer the questions Dev Mode can't. Name components to match engineering. Document responsive behavior at each breakpoint. Review the file before handoff to catch gaps. And build a feedback process during the build that's structured, prioritized, and collaborative.
The investment in good handoff practice is returned immediately in faster builds, fewer implementation surprises, and better working relationships between design and engineering. If you're consistently finding that implementations don't match designs, the problem is usually in the handoff, not in engineering's skills. For teams working with a design subscription service, a structured handoff process is especially important to keep delivery moving smoothly — see also how to give design feedback for the review side of this workflow.
Frequently Asked Questions
What do engineers need from a design handoff that isn't in Figma specs?+−
Intent and behavior — why things are designed the way they are, and what happens in every state. Figma's Dev Mode provides colors, spacing, and font sizes automatically. What it doesn't provide is: why is this button disabled, what triggers this modal to close, what should the layout do when content is unusually long, and what happens when the API returns an error. Annotations that answer these questions are what separate a complete handoff from an incomplete one.
How do I annotate a Figma file for engineering?+−
Use a consistent annotation system: arrows pointing to interactive elements with a label describing the behavior, callout boxes for conditional display rules, text notes for animation timing and content rules. Keep annotations concise — one question answered per annotation. Separate the annotations visually from the design frames so they don't get confused with design elements. Add a key or legend if you're using symbols.
How should I document responsive behavior in Figma?+−
State your breakpoints explicitly at the top of the file. Create a separate frame for each breakpoint that has meaningfully different behavior — typically desktop, tablet, and mobile. On the non-desktop frames, annotate what changed and why. For complex responsive behavior, a short written spec is often clearer than visual annotations alone.
What states do I need to design before handing off?+−
For every interactive element: default, hover, focus, disabled, and any data-driven states (loading, error, empty, success). The states that most often get missed are the error states (for forms and async operations) and the empty states (for lists, tables, and dashboards). These are often the states that cause QA scrambles right before launch. Design them at the same time as the happy path.
How should design feedback work during the engineering build?+−
Review on staging, not in real-time during the build. Compile all feedback into a single pass rather than sending messages throughout. Label feedback as blocking (spec error that must be fixed) or non-blocking (preference that can wait or be batched). Distinguish between engineering not following the spec and the spec being wrong. When engineering constraints require a change from the design, work together on an alternative rather than insisting on the original Figma spec.
Work with us
Senior product design for your SaaS or AI startup.
30-minute call. We look at your product and tell you exactly what needs fixing.
Related