Token workflow
How to add, rename, or remove a token without breaking the code that depends on it.
How to add, rename, or remove a token without breaking the code that depends on it. For how a token is named, see Token framework. For the words to reuse, see Standards.
How a token change travels (2 minutes)
1. You edit in Tokens Studio (Figma)
│ push to a branch
▼
2. Pull request on GitHub (tokens/*.json)
│ automatic checks
├─ Build tokens ........ the tokens compile (Style Dictionary)
└─ Visual tests ........ every story is screenshotted and compared; the PR gets a comment listing what changed
│ review + merge
▼
3. main
├─ Storybook redeploys (moments.easol.dev) — Foundations pages update on their own
└─ visual baselines refresh to the new main
│ VERSION bump (a release)
▼
4. Release vX.Y.Z — git tag + Changelog entry + npm package (@easolhq/moments)
│ easol-app bumps @easolhq/moments
▼
5. Live in the Easol app- Tokens Studio is the single source of truth. You edit tokens there; the JSON is generated for you. Never edit
tokens/*.jsonordist/by hand — they are generated and will be overwritten. - Every token becomes a CSS variable the code uses, named after the token:
moments.semantic.colour.text.base.default→--moments-semantic-colour-text-base-default. - Merged is not live. A merged token change is on
mainand in the hosted Storybook straight away, but it only reaches the Easol app after a release (VERSION bump) and after easol-app updates its@easolhq/momentspackage to that release. - This is the key to everything below: the code references tokens by their name — in Moments components and in the Easol app. So adding a token is safe, but renaming or removing one changes or removes a variable the code may still be using — that's how you "break the sync".
Golden rule: a token name is a contract with the code. Add freely; change values freely; rename or remove with care.
What happens on your pull request
Every token PR runs two checks. Here's what each one means for you:
| Check | Fails when… | What to do |
|---|---|---|
| Build tokens | A token can't be resolved — a broken reference ({moments.core…} that doesn't exist), a typo, a missing theme value. | Fix the token in Tokens Studio and push again. The error names the token. |
| Visual tests | Never blocks — it comments on the PR with the stories whose screenshots changed and uploads a before/after report. | Open the report. If every change is intended, run Actions → "Update visual baselines" → Run workflow on your branch. If something changed that you didn't expect, the token is used somewhere you didn't know about — check it before merging. |
A token PR is ready to merge when all checks are green and the visual report only shows changes you meant to make.
🔍 Before you rename or remove: find where it's used
A token can be used in three places, so check all three:
- Storybook → Tokens panel. Open any component story and the Tokens panel (next to Controls / Accessibility) lists every token that story uses, with its alias chain and the CSS properties it feeds. Hover a row to see where it's applied.
- The Moments repo. Search for the CSS variable, e.g.
--moments-semantic-colour-text-base-subtle. - The Easol app (easol-app). Search the same variable there — pages can use tokens directly, not only through components.
The Tokens panel also shows an undefined chip when a component references a variable that no longer exists — a quick way to catch a rename that missed a spot.
➕ Adding a token (safe)
Adding is non-breaking — nothing referenced it yet.
- In Tokens Studio, create the token in the right tier and set, following Token framework and Standards:
- Core for raw values (
core-colour-primary-500). - Semantic for purpose (
semantic-colour-text-accent-default). - Component tokens: Moments doesn't have a component token set in Tokens Studio yet — components consume semantic tokens directly. If you think a component needs its own token, raise it with the team first rather than creating a new set.
- Core for raw values (
- Semantic tokens should reference a core token (e.g.
{moments.core.colour.primary.500}), not a raw value — that's what makes theming work. - If it's a colour that must change between light and dark, add it in both the Light and Dark sets with the same name (only the referenced core value differs).
- Add a short description (what it's for) — it becomes the code comment.
- Push to a branch and open a PR. Follow "What happens on your pull request" above.
Checklist: ☐ right tier ☐ name reuses an existing scale/term ☐ references a core token ☐ light + dark parity (if themed) ☐ description ☐ PR checks green.
🎨 Changing a token's value (safe, but visible)
Changing a value (not the name) is non-breaking for the code — every consumer picks up the new value automatically. It does change how things look, so:
- Make the change in Tokens Studio and open a PR.
- Read the visual test report — it shows every story the change affects. That's your impact list.
- If it all looks right, update the visual baselines on the branch and merge.
✏️ Renaming a token (needs a migration — don't do it in one step)
A rename is really a delete + create: the old variable disappears and a new one appears. Anything still using the old name — in Moments or in the Easol app — silently breaks. Never rename a token that's already in use in a single PR.
Safe rename (add → migrate → release → remove):
- Add the token under the new name (keep the old one for now). Point both at the same core value. Merge.
- Migrate the code from
--moments-…-oldnameto--moments-…-newname— in Moments components and in easol-app. Open a ticket for a developer if needed. - Release (VERSION bump) and make sure easol-app is on that release, so nothing live still needs the old name.
- Confirm nothing uses the old name any more (see "Before you rename or remove" above), then remove the old token in Tokens Studio and open a PR.
If a token was just added and isn't used anywhere yet, you can rename it directly — there's no contract to break.
🗑️ Deprecating / removing a token
Same principle: don't pull the rug out from under the code.
- Mark it deprecated first — prefix the description with
[DEPRECATED]and say what to use instead (e.g. "usesemantic.colour.text.base.subtle"). Do not delete it yet. - Announce it in the design system Slack channel so consumers migrate.
- Give it a grace period — until nothing in Moments or easol-app uses it and easol-app is on a release that doesn't need it.
- Only then remove it in Tokens Studio and open a PR.
Removing a token that's still referenced will break those components or pages — that's why deprecation comes first.
↩️ Rollback (if a token change breaks something)
Token changes flow through Git, so they're fully reversible.
Fastest — revert on GitHub (recommended):
- Go to the repo → Pull requests (or Commits) and find the one that introduced the bad token change.
- Click Revert (or a developer runs
git revert <commit>). This opens a revert PR — let the checks run and merge it. Storybook goes back to the previous state. - If the change was already released, bump VERSION again so the Easol app can pick up the fixed release.
Then realign the source of truth: 4. In Tokens Studio, undo the change too (revert your last edit, or pull the reverted state) so Figma and GitHub match again — otherwise your next push re-introduces it.
Tokens Studio also keeps its own history; you can restore a previous state there and re-push. Either way, make sure Tokens Studio and GitHub agree after a rollback.
Pre-flight checklist (before every PR)
- ☐ Editing in Tokens Studio, not the JSON/CSS by hand.
- ☐ New tokens follow Token framework and Standards, and reference a core token.
- ☐ Colour changes keep light + dark parity.
- ☐ Renames done as add → migrate → release → remove (not in one step).
- ☐ Removals were deprecated + announced first.
- ☐ Checked where the token is used (Tokens panel, Moments, easol-app).
- ☐ PR checks green; the visual report only shows intended changes.
- ☐ You know how to revert if it goes wrong (section above).
What NOT to do
- ❌ Don't hand-edit
tokens/*.jsonordist/— Tokens Studio / the build owns them. - ❌ Don't rename or delete a token that's in use without migrating the code (Moments and easol-app) first.
- ❌ Don't add a colour to only one theme (breaks light/dark parity).
- ❌ Don't change a token's name when you only meant to change its value — changing the value is safe and non-breaking; changing the name is the risky one.
- ❌ Don't update the visual baselines without looking at the report — that's how an unintended change gets accepted.
- ❌ Don't assume "merged" means "live in the Easol app" — it needs a release and a package bump in easol-app.