ADR-026
Figma synchronization strategy for custom brand palettes
Context
ADR-024 introduced two custom brand palettes (rose-coral accent and bordeaux secondary) into tokens/primitives.json. Unlike the Radix UI palettes already present (Teal, Blue, Red, etc.), these palettes:
1. Are not on Figma Community — Tokens Studio cannot import them from an official shared file 2. Have no external reference documentation — users must understand each step from the JSON alone 3. Can evolve — the hex values are design decisions, not constants inherited from a third-party system
The question raised in ADR-024's debt log:
How are custom palettes synchronized with Figma reliably, in a governed way, without creating a second source of truth?
Decision
Principle: the same pipeline as the Radix palettes
The custom palettes (accent, secondary) are handled exactly like the Radix palettes in the sync pipeline. There is no special process for them.
tokens/primitives.json
↓ (Tokens Studio reads this file)
Figma Variables — "Primitives" collection
↓ (designers use it via semantic tokens)
Figma Variables — "Semantic" + "Component" collections
Tokens Studio makes no distinction between a Radix palette and a custom palette — it reads the JSON and maps tokens to Figma Variables based on the file's structure.
Tokens Studio configuration
Target Figma collection: Primitives (the same collection as primitive.color.teal, primitive.color.blue, etc.)
Automatic naming in Figma:
primitive/color/accent/1→ Figma variableaccent/1primitive/color/accent/9→ Figma variableaccent/9primitive/color/secondary/9→ Figma variablesecondary/9- etc.
_readme tokens (type other) are ignored by Tokens Studio on import — they do not generate Figma variables. They exist solely to document the JSON for agents and developers.
Import order (unchanged since ADR-011): 1. primitives.json → Primitives collection 2. semantic.json → Semantic collection 3. component.json → Component collection
When custom values change
Any modification of a custom palette's hex values follows the standard process:
1. Open a token(primitives) PR on a token/brand-palette-update branch 2. Modify the values in tokens/primitives.json 3. Mandatory approval from the Principal Designer (governance rule ADR-001, ADR-004) 4. Merge → the Tokens Studio sync pipeline detects the change on the next pull from Figma
Designers do not modify values directly in Figma. If a hue doesn't work, they open an issue / submit a PR — not a local Figma variable edit.
Documenting steps in Figma
Figma variable descriptions (the description field in Tokens Studio) are populated from each JSON token's $description field. Designers see directly in the Figma panel:
| Figma variable | Automatic description |
|---|---|
accent/9 | Solid background — brand accent / secondary CTA |
accent/11 | Accent text — 7.1:1 on white (WCAG AA+AAA) |
secondary/9 | Solid dark background — 12.2:1 with white text |
secondary/12 | High-contrast text — 13.8:1 on white (WCAG AAA) |
The per-step usage rule (inherited from the Radix convention — steps 1-2 backgrounds, 9-10 solids, 11-12 text) applies to the custom palettes as well. It is documented in the _readme field of each palette in primitives.json.
Validation after sync
After each custom palette update in Figma, the Principal Designer validates:
- [ ] All 12 steps of each palette appear in the
Primitivescollection - [ ] The
semantic/color/brand/*semantic tokens correctly resolve their aliases - [ ] No orphaned Figma variable (broken alias) in the
SemanticorComponentcollections - [ ] Variable descriptions match the JSON's
$descriptionvalues
What an agent may do
✅ Modify hex values in tokens/primitives.json via PR
✅ Add a new intermediate step (e.g. accent/9-5) if justified
✅ Update the $description fields to improve Figma documentation
❌ Modify Figma variables directly (never — the direction is JSON → Figma)
❌ Create a new palette without an ADR and Principal Designer approval
Rationale
Why not create a separate Figma collection for the custom palettes?
A Brand collection separate from Primitives:
- Introduces an asymmetry between the Figma structure and the JSON structure (where everything lives in
primitives.json) - Complicates the Tokens Studio import rules (order, alias resolution)
- Provides no benefit to agents — who work on the JSON, not on Figma
Keeping everything in the Primitives collection preserves consistency between JSON and Figma.
Why don't _readme entries create Figma variables?
Tokens Studio ignores tokens of type other when importing variables (they are not design values — no usable $value). This behavior is documented and intentional. _readme entries are a documentation pattern internal to the JSON.
Rejected alternatives
| Alternative | Reason for rejection |
|---|---|
| Create the custom palettes manually in Figma | Creates a second source of truth outside the repo. Drift is guaranteed at the next update. |
| Host the custom palettes in a separate JSON file | Fragments primitives.json with no benefit — Tokens Studio can manage a single file for all primitives. |
| Use Figma Styles (not Variables) | Figma Styles do not support aliases/references — semantic tokens could not point to the primitives. Figma Variables is the right mechanism. |
| Wait for a Radix fork | The custom colors do not correspond to any existing Radix palette. Waiting for a hypothetical similar Radix palette is not actionable. |
Consequences
Immediate:
- The
accentandsecondarypalettes are available in Figma on the next Tokens Studio pull from the repo - No additional configuration required — they appear automatically in the
Primitivescollection
For designers:
- Same workflow as for Radix palettes — nothing new to learn
- Step descriptions are visible directly in the Figma Variables panel
- Any request to change a hue goes through a PR, not a local Figma edit
For AI agents:
- Agents continue to work exclusively on the JSON files
- Figma sync is transparent to agents — it does not change token usage rules
For governance:
- A custom palette with no ADR = drift — audit-tokens.js can detect tokens with no associated documentation
- Any new custom palette triggers the creation of an ADR + Principal Designer approval
Debt resolved:
- The debt documented in ADR-024 ("a separate ADR must document the Figma sync strategy for custom palettes") is resolved by this ADR.
Contexte
ADR-024 a introduit deux palettes de marque custom (accent rose-corail et secondary bordeaux) dans tokens/primitives.json. Contrairement aux palettes Radix UI déjà présentes (Teal, Blue, Red, etc.), ces palettes :
1. Ne sont pas dans Figma Community — Tokens Studio ne peut pas les importer depuis un fichier partagé officiel 2. N'ont pas de documentation de référence externe — les utilisateurs doivent comprendre chaque step depuis le JSON seul 3. Peuvent évoluer — les valeurs hex sont décisions de design, pas des constantes issues d'un système tiers
La question soulevée dans la dette d'ADR-024 :
Comment les palettes custom sont-elles synchronisées avec Figma de manière fiable, gouvernée, et sans créer une seconde source de vérité ?
Décision
Principe : même pipeline que les palettes Radix
Les palettes custom (accent, secondary) sont traitées exactement comme les palettes Radix dans le pipeline de sync. Il n'existe pas de processus spécial pour elles.
tokens/primitives.json
↓ (Tokens Studio lit ce fichier)
Variables Figma — Collection "Primitives"
↓ (les designers utilisent via semantic tokens)
Variables Figma — Collection "Semantic" + "Component"
Tokens Studio ne fait pas de distinction entre une palette Radix et une palette custom — il lit le JSON et mappe les tokens à des Variables Figma selon la structure du fichier.
Configuration Tokens Studio
Collection Figma cible : Primitives (même collection que primitive.color.teal, primitive.color.blue, etc.)
Nommage automatique dans Figma :
primitive/color/accent/1→ variable Figmaaccent/1primitive/color/accent/9→ variable Figmaaccent/9primitive/color/secondary/9→ variable Figmasecondary/9- etc.
Les tokens _readme (type other) sont ignorés par Tokens Studio à l'import — ils ne génèrent pas de variables Figma. Ils servent exclusivement à la documentation du JSON pour les agents et développeurs.
Import order (inchangé depuis ADR-011) : 1. primitives.json → Collection Primitives 2. semantic.json → Collection Semantic 3. component.json → Collection Component
Quand les valeurs custom changent
Toute modification des valeurs hex d'une palette custom suit le processus standard :
1. Ouvrir une PR de type token(primitives) sur une branche token/brand-palette-update 2. Modifier les valeurs dans tokens/primitives.json 3. Approbation obligatoire du Principal Designer (règle gouvernance ADR-001, ADR-004) 4. Merge → le pipeline de sync Tokens Studio détecte le changement au prochain pull depuis Figma
Les designers ne modifient pas les valeurs directement dans Figma. Si une teinte ne convient pas, ils ouvrent une issue / soumettent une PR — pas une modification locale de variable Figma.
Documentation des steps dans Figma
Les descriptions des variables Figma (champ description dans Tokens Studio) sont renseignées depuis le champ $description de chaque token JSON. Les designers voient directement dans le panneau Figma :
| Variable Figma | Description automatique |
|---|---|
accent/9 | Solid background — brand accent / CTA secondaire |
accent/11 | Texte accent — 7.1:1 sur blanc (WCAG AA+AAA) |
secondary/9 | Solid dark background — 12.2:1 avec texte blanc |
secondary/12 | High-contrast text — 13.8:1 sur blanc (WCAG AAA) |
La règle d'usage par step (héritée de la convention Radix — steps 1-2 fonds, 9-10 solides, 11-12 texte) s'applique aux palettes custom. Elle est documentée dans le champ _readme de chaque palette dans primitives.json.
Validation après sync
Après chaque mise à jour de palette custom dans Figma, le Principal Designer valide :
- [ ] Les 12 steps de chaque palette apparaissent dans la collection
Primitives - [ ] Les tokens sémantiques
semantic/color/brand/*résolvent correctement les alias - [ ] Aucune variable Figma orpheline (alias cassé) dans les collections
SemanticouComponent - [ ] Les descriptions de variables correspondent aux
$descriptiondu JSON
Ce qu'un agent peut faire
✅ Modifier les valeurs hex dans tokens/primitives.json via PR
✅ Ajouter un nouveau step intermédiaire (ex: accent/9-5) si justifié
✅ Mettre à jour les $description pour améliorer la documentation Figma
❌ Modifier les variables Figma directement (jamais — direction JSON → Figma)
❌ Créer une nouvelle palette sans ADR et sans approbation Principal Designer
Argumentaire
Pourquoi ne pas créer une collection Figma séparée pour les palettes custom ?
Une collection Brand séparée des Primitives :
- Introduit une asymétrie dans la structure Figma vs la structure JSON (où tout est dans
primitives.json) - Complique les règles d'import Tokens Studio (ordre, résolution des alias)
- Ne bénéficie pas aux agents — qui travaillent sur le JSON, pas sur Figma
Garder tout dans la collection Primitives préserve la cohérence entre JSON et Figma.
Pourquoi les _readme ne créent-ils pas de variables Figma ?
Tokens Studio ignore les tokens de type other à l'import des variables (ils ne sont pas des valeurs de design — pas de $value utile). Ce comportement est documenté et intentionnel. Les _readme sont un pattern de documentation interne au JSON.
Alternatives rejetées
| Alternative | Raison du rejet |
|---|---|
| Créer les palettes custom manuellement dans Figma | Crée une seconde source de vérité hors du repo. Dérive garantie à la prochaine mise à jour. |
| Héberger les palettes custom dans un fichier JSON séparé | Fragmente primitives.json sans bénéfice — Tokens Studio peut gérer un seul fichier pour tous les primitifs. |
| Utiliser des Figma Styles (pas des Variables) | Les Figma Styles ne supportent pas les alias/références — les tokens sémantiques ne pourraient pas pointer vers les primitifs. Variables Figma est le bon mécanisme. |
| Attendre un fork Radix | Les couleurs custom ne correspondent à aucune palette Radix existante. Attendre une hypothétique palette Radix similaire n'est pas actionnable. |
Conséquences
Immédiates :
- Les palettes
accentetsecondarysont disponibles dans Figma au prochain pull Tokens Studio depuis le repo - Aucune configuration supplémentaire requise — elles apparaissent automatiquement dans la collection
Primitives
Pour les designers :
- Même workflow que pour les palettes Radix — rien à apprendre de nouveau
- Les descriptions de step sont visibles directement dans le panneau Variables Figma
- Toute demande de modification de teinte passe par une PR, pas par une modification Figma locale
Pour les agents IA :
- Les agents continuent de travailler exclusivement sur les fichiers JSON
- La sync Figma est transparente pour les agents — elle ne change pas les règles d'usage des tokens
Pour la gouvernance :
- Une palette custom sans ADR = dérive — l'audit-tokens.js peut détecter des tokens sans documentation associée
- Toute nouvelle palette custom déclenche la création d'un ADR + approbation Principal Designer
Dette soldée :
- La dette documentée dans ADR-024 ("un ADR séparé devra documenter la stratégie de sync Figma pour les palettes custom") est soldée par cet ADR.