Figma versioning strategies
When we talk about versioning, most of us think of semver (semantic versioning). It works very well in code: major.minor.patch
helps developers (and even bots) know what is safe to upgrade, what is risky, and what is a breaking change.
Today, my fellow designer Oriol asked me about versioning and how we do it in our React package.
He also brought this article as a starting point for discussion: Versioning design systems best practices.
The design team wanted a way to manage versions but were not sure about the best practices:
Should we apply the same versioning rules to our design documentation in Figma?
Spoiler: it is not that straightforward.
Semver might not be the best solution for Figma
Code vs. Figma behave differently
- In code, semver is powerful: it drives automation, dependency management, and safe upgrades.
- In Figma, things like property renaming often update automatically. What would count as a breaking change in code might not feel like one in design.
Figma branching is not Git branching
Git branching is for code. A branch is like a separate path where you can make changes without touching the main code. Developers use it to work on features or fixes at the same time. Merging brings changes back together, and if two people change the same lines of code, you need to resolve conflicts carefully. Branches can stay around for a long time and keep a detailed history.
Figma branching is for design. A branch is a copy of the file where you can try new ideas without changing the main design. When merging, you pick which version of each object (like a frame or component) to keep. It is simpler than code merging but less precise. Figma branches are usually temporary and deleted after merging, so they are more for testing and exploration than long-term work.
This makes “branching” in Figma closer to a UI trick than a true version control system. It is useful, but it does not give you the guarantees that semver assumes.
Our code strategy
We plan to use deprecation phases and avoid sudden breaking changes. That means the version of a component in code will not always match the version of the same component in Figma.
The trade-off
Using semver in Figma adds more overhead (keeping design and code versions in sync) than real value.
The contract of a component
Every component, in code or design, needs a contract:
- How it looks → visual style, variants, responsive rules, theming, internationalization
- How it behaves → interactions, accessibility rules (keyboard navigation, screen readers), error states
There are many more things that could be part of this definition, but I will talk about them another day.
This contract should be simple enough that any role (developer, designer, QA, PO) can read it and understand the scope.
We could treat this first contract as v1.0
.
Where should it live?
The source of truth must be accessible to everyone, without needing extra licenses or learning new tools.
My proposal: Jira.
It may not be fancy, but everyone in the company has access and knows the basics of the tool.
It even supports autolinks in GitHub, components, versions, releases and changelogs.
More on that, another day.
Tracking changes to the contract
When the contract changes, we need clarity:
- What changed
- When it changed
- Why it changed
Examples:
A color change. Was it a bug fix? Or a new requirement from the accessibility team? It does not matter. As long as the change is compatible with the current version, we treat it as a minor update v1.1
.
A new feature that extends what already exists. If it does not break current functionality, it is also a minor update v1.1
.
A breaking change. If something no longer works as before, it becomes a major update v2.0
In this model we are not using patch versions. We only distinguish between minor and major, depending on whether the change is breaking or not.
Again, Jira as the single source of truth for this information.
Conclusion
Versioning is not one-size-fits-all. While semver is essential in codebases, applying it to design tools like Figma can create unnecessary complexity.
By separating concerns, semver for code and plain changelogs for design, we reduce friction, keep everyone aligned, and let each system play to its strengths.
Instead of forcing semver everywhere, here is a more pragmatic approach:
- Code → Use semver. It is built for it.
- Figma → Keep a clear changelog of the contract. No need for semver here.
- A single source of truth for what changed, when, and why in a place where everyone has access and knows the tool (Jira, Confluence…)
Extra ball
Denis Rojčyk did a great job documenting their initial plan, and what they learnt after a year: