Most Figma files are not ready for developer handoff. They look impressive. The screens are polished, the alignment is perfect, the color choices are deliberate. But when a developer opens the file and tries to extract what they need to build it, they hit a wall. Components have no consistent naming. Auto layout is applied inconsistently, so the spacing values are buried in manual positioning. Variants exist for the hover state but not the disabled or error states. The design tokens in Figma do not match anything in the codebase.
I have been on both sides of this problem throughout my career. As a UX/UI designer I have handed off files that I thought were complete and received confused messages from developers two days later. As a Senior Angular developer I have received Figma files that required hours of clarification calls before I could write a single line of code. The solution, which I have refined over years of dual-role work, is a set of practices that I now apply consistently to every Figma file I create. This post documents those practices.
Naming: The Foundation of Everything
Bad naming in Figma is the root cause of most handoff problems. When a developer opens the Inspect panel and sees 'Frame 247' or 'Rectangle copy 3', they have no useful information. Worse, inconsistent naming means the developer cannot confidently map Figma components to the corresponding code components in the design system.
I follow a naming convention that mirrors the component API as closely as possible. Figma component names use the same format as the Angular component selector or the design system token. A button in Figma is named Button, not 'CTA' or 'Primary Action'. Its variants are named using the property names and values that will appear in code: variant=Primary, size=Medium, state=Default.
// Figma component naming convention
Button
variant: Primary | Secondary | Tertiary | Destructive
size: Small | Medium | Large
state: Default | Hover | Focus | Disabled | Loading
// Maps directly to Angular component usage
<app-button
variant="primary"
size="medium"
[disabled]="isLoading">
Submit
</app-button>When the naming language in Figma matches the naming language in code, the handoff conversation becomes much shorter. The developer can look at a component in Figma, identify its variant and state from the properties panel, and know exactly which Angular component and what input values to use.
Auto Layout Done Right
Auto layout is the one Figma feature that carries the CSS flexbox model across the handoff intact. Used correctly, the developer reads the layout instead of guessing at it. Used incorrectly, or skipped entirely, it leaves them inferring layout logic from pixel measurements that describe one frozen frame and nothing about how the thing behaves when the viewport moves.
My rules for auto layout in handoff-ready files:
- Every component that will be built with flexbox or grid in CSS should use auto layout in Figma. No exceptions.
- Spacing between elements should come from auto layout gap, not from manually positioned elements. A gap value in Figma translates directly to gap in CSS.
- Use 'Fill container' for elements that stretch to take the available space, and 'Hug contents' for elements sized by what is inside them. The CSS mapping is close, not exact, and the axis decides it. Fill along the layout axis is flex-grow: 1. Fill across the layout axis is align-self: stretch. Hug is fit-content on the axis and auto across it. Say which axis you mean in the annotation and the developer stops guessing.
- Padding should be set in the auto layout panel, not by adding invisible spacer frames. The padding values in Figma are what the developer will implement in CSS.
- Use min/max width constraints for components that need responsive behavior. A card that should be at least 280px wide but can grow is expressed in auto layout constraints.
Variants and Interactive States
A component without all its states documented is not a component. It is a partial specification. I have already written about this from the brief-writing perspective, but in Figma specifically, the standard is: every interactive component must have variants for all states that exist in the implementation.
For a text input field, that means: Default, Focused, Filled, Error, Disabled, and Read-only. For a button: Default, Hover, Focus, Active, Disabled, and Loading. These are not edge cases. They are the minimum set that any button will encounter in production.
Figma's interactive components feature (prototype connections between variants) is valuable for communicating hover and focus behavior in prototypes. But do not rely on it as a substitute for variant documentation. Every state should exist as a distinct variant in the component set, labeled clearly, so a developer can inspect it directly without having to trigger a prototype interaction.
Design Tokens: The Bridge Between Figma and Code
Design tokens are the single most important tool for reducing handoff friction, and also the most commonly misimplemented. The goal is simple: every design decision in Figma (color, spacing, typography, border radius, shadow, duration) should reference a named token, and that token should exist in the codebase under the same name.
In practice, this means setting up your Figma variables to match your CSS custom properties or JavaScript token object exactly. The setup that holds up exports Figma Variables as JSON and runs the file through Style Dictionary to generate the CSS. Tokens Studio (formerly Figma Tokens) is another option: it manages the token set inside Figma and can sync it with a repository.
/* In CSS (design system tokens) */
:root {
--color-action-primary: #0052cc;
--color-action-primary-hover: #003d99;
--color-surface-default: #ffffff;
--color-text-primary: #172b4d;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--radius-md: 6px;
--shadow-card: 0 1px 3px rgba(0,0,0,0.12);
}When the developer inspects a button in Figma and sees that the background color is var(--color-action-primary) rather than a hex value, they can implement it immediately with the correct token. No color-picking, no hardcoded hex values, no drift between design and implementation.
Syncing Tokens Between Figma and Code
Another workflow that removes drift, when the same person or team owns both the Figma library and the component library, is code first: design tokens live in a JSON file in the repository as the single source of truth. A sync plugin such as Tokens Studio reads that file and populates the token set in Figma. When a token changes (a brand color update, a spacing adjustment), the change is made in the JSON file, a PR is opened, and once it merges, the Figma library is synced from the updated file. Figma always reflects what is in code, not the other way around. Authoring in Figma Variables and exporting JSON, the setup I described above, works just as well, as long as the team picks one direction and writes it down. At BMO the design system belonged to another team and I worked on the consuming side, where the question that matters is the same: which direction does the truth flow?
Annotation Plugins and Specifications
Figma's inspect panel is useful but insufficient for complex components. Four kinds of note have to live somewhere on the canvas: interaction notes (what happens on click, what keyboard interactions are supported), responsive behavior notes, accessibility annotations (ARIA roles, focus order), and content constraint notes (max character counts, image aspect ratios). None of them appear in Inspect on their own.
Start with the free path, because it works on any seat and it is where I still default. A callout component and a text style for notes gets you a complete spec layer for nothing. If you want the measurement and anatomy parts generated rather than drawn by hand, the Specs plugin from EightShapes has a free tier covering anatomy, layout and spacing annotations, and Redlines & Annotations in the Figma community does measurement overlays. Both write ordinary layers onto the canvas, so anyone with view access can read the result.
Figma Dev Mode has native annotations and measurements, and they are better than anything you draw by hand: the annotation binds to the layer, it survives a rename, it updates when the layer moves, and it shows up in the Inspect panel where the developer is already looking. The catch is the seat. Dev Mode has required a paid Full or Dev seat since January 2024. Treat it as an upgrade you buy once the handoff volume justifies it, not as the starting point. If your team already pays for it, use it and delete your manual annotation layer.
Wherever the notes come from, they live on their own Figma page in my files, named 'Specs & Annotations'. It holds a duplicate of every screen with the annotations overlaid, rather than annotations sitting on the design frames themselves, because that clutters the design the moment a stakeholder opens it. Developer needs the spec, they go to the Specs page. Stakeholder wants the clean design, they stay on the design page.
File Organization That Developers Can Navigate
A Figma file that is visually beautiful but structurally chaotic is useless for handoff. My file structure for any project ready for development:
- Cover page: Project name, status (In Progress / Ready for Dev / In Development / Done), last updated date, design owner, developer contact.
- Tokens page: All variables and styles documented with their values and usage notes.
- Components page: The component library. All variants of all components organized by category.
- Flows page: Screen-by-screen flows organized by user journey, with prototype connections.
- Specs & Annotations page: Annotated versions of all screens ready for developer inspection.
- Archive page: Old explorations and rejected concepts, kept for reference but clearly labelled.
The Dual-Role Advantage in Handoff
Writing this post makes me realize how much my development experience has shaped how I design. When I create a component variant for the loading state of a button, I am not doing it out of thoroughness for its own sake. I am doing it because I know from experience that a developer implementing that button will need to know what it looks like when isLoading is true, and without a design reference they will either ask me or make something up.
Every annotation I write in a spec is an answer to a question I know a developer will ask, because I have asked those same questions myself. What should the focus ring look like? How many lines does this text field support before it overflows? What happens to the card layout if there is no thumbnail image?
If you are a designer who does not code, the fastest way to improve your handoff quality is to pair with a developer for one sprint and ask them to narrate their experience opening your Figma file and implementing from it. The friction points they encounter will tell you exactly what to improve. The developer is your user when the product is a Figma file, and user research applies.
A Figma file is a specification document. A specification document is a communication tool. Judge it not by how beautiful it looks, but by how clearly it answers the developer's questions.
The goal is not a perfect file. It is a file that lets a developer start building on Monday morning without a single clarifying question. That is a high bar, but it is an achievable one, and it is worth the upfront investment every time.
References
- Figma auto-layout. https://help.figma.com/hc/en-us/articles/360040451373-Guide-to-auto-layout
- Figma variants. https://help.figma.com/hc/en-us/articles/360056440594-Create-and-use-variants
- Figma Dev Mode guide, paid Full or Dev seat required. https://help.figma.com/hc/en-us/articles/15023124644247-Guide-to-Dev-Mode
- Figma Dev Mode general availability announcement, January 2024. https://www.figma.com/blog/dev-mode-ga/
- Tokens Studio. https://tokens.studio/
- Figma Variables REST API (Enterprise plan only; community export plugins are the free path). https://developers.figma.com/docs/rest-api/variables/