Figma Variables to SwiftUI Tokens: The AI Prompt
Figma variables are already a token system, primitives, semantics, modes. The prompt's job is translating that structure into Swift without flattening it.
TL;DR
Figma variables map to SwiftUI tokens with their structure intact, and preserving the structure is the entire craft. The two-layer discipline survives translation: primitive variables (blue-500, gray-100) become a private palette, semantic aliases (accent, surface, textPrimary) become the public API views consume, and Figma's modes (light/dark in one variable) become ColorScheme-adaptive colors resolved by the system. The prompt takes the variables export (or Dev Mode's listing), states the two-layer requirement and the target shape (an enum or struct serving Color, Font, and spacing constants), and emits one token file, which makes the sync workflow trivial: design changes re-export variables and regenerate that single file, with every screen consuming semantics untouched. Type and spacing variables ride the same pipeline, and the result is the tokens-first architecture every theming system in this series stands on.
What are Figma variables, structurally?
Already a token system. Figma’s variables carry the three properties a design system needs: primitives (blue-500, gray-100, the raw palette), semantic aliases (accent points at blue-500, surface at gray-100, the decisions), and modes (one variable holding light and dark values, resolved by context), and the translation’s entire craft is preserving that structure in Swift, because a conversion that flattens it, views drinking hexes, discards exactly the indirection the variables were built to provide.
What does the target shape look like?
Two layers, one file, modes adaptive:
// DesignTokens.swift: GENERATED from Figma variables (file key, 2026-06-05). Do not hand-edit.
private enum Palette { // primitives: views never touch these
static let blue500 = Color(red: 0.23, green: 0.51, blue: 0.96)
static let gray100Light = Color(white: 0.96)
static let gray100Dark = Color(white: 0.12)
}
extension Color { // semantics: the public API
static let accent = Palette.blue500
static let surface = Color.adaptive(light: Palette.gray100Light,
dark: Palette.gray100Dark)
}
enum Spacing { static let sm: CGFloat = 8; static let md: CGFloat = 16 }
Modes map to ColorScheme adaptivity: a variable with light and dark values becomes one SwiftUI Color resolving per scheme, so the public API stays single-named (Color.surface) and the system picks the mode, exactly how the design file already thinks, and exactly the architecture the dark-mode reveal requires before any circle can animate. Additional Figma modes, brand themes, density, map to environment-driven theme switching one layer above the scheme.
What does the prompt actually say?
The data plus three structural sentences. Paste the variables export (or Dev Mode’s listing for smaller systems) and state: “Generate a SwiftUI token file: a private primitive palette from these values; a public semantic API (Color.accent, Color.surface, Font.title, Spacing.md) from these aliases; light/dark modes as adaptive colors; no view ever references a primitive.” One file comes back, reviewed once against the design source, and the no-primitives rule is the line worth enforcing in review and the rules file alike, because it is the rule that makes rebrands a palette swap instead of archaeology.
| Variable kind | Swift target | The note | Verdict |
|---|---|---|---|
| Color primitives | Private palette enum | Views never touch | The hidden layer |
| Color semantics | extension Color statics | The API screens consume | Names survive palette shuffles |
| Modes | Adaptive colors per scheme | One name, system-resolved | Matches the file’s own thinking |
| Type variables | Font tokens with Dynamic Type | Scale with the platform | Never frozen point sizes |
| Spacing/radius | CGFloat constant enums | The rhythm, named | Spacing.md beats magic 16s |
Type variables deserve their footnote: Figma’s fixed point sizes translate into font tokens that scale with Dynamic Type rather than freezing, the platform-respect adjustment the design file cannot express and the conversion must add.
How does the sync loop stay sane?
One regenerable artifact with a forbidden-edit rule. Variables change in Figma → the export re-runs → the prompt regenerates the single token file → the diff reviews in a minute, because every screen consumes semantics whose names rarely move. The file carries its generated-from header (file key, date), hand edits inside it are forbidden, customizations live in consumers of the semantic layer, never the generated palette, and the loop is the cheapest design-system sync that exists: no plugin subscriptions, no style-dictionary pipelines for a single-platform app, one prompt and one file.
The pipeline composes with the rest of the design-to-code stack: screens generate against the token API from the Figma routes or directly from free VP0 designs at $0 with the token contract stated, and the same tokens-first sequencing serves the open-source toolchain when Penpot holds the variables instead. The order never changes: tokens first, screens against them, regeneration downstream, the architecture every theming entry in this series has now confirmed from four directions.
Key takeaways: Figma variables to SwiftUI
- The structure is the value: primitives private, semantics public, modes adaptive, flattening discards the system.
- One generated file: palette enum, semantic Color/Font/Spacing API, generated-from header, hand edits forbidden.
- Modes become ColorScheme adaptivity: single-named tokens, system-resolved, matching the file’s own model.
- Type tokens gain Dynamic Type: the platform respect the design file cannot express.
- The sync loop is export-regenerate-review: a minute per design change, with screens consuming semantics untouched.
Frequently asked questions
How do I convert Figma variables to SwiftUI tokens? Paste the export with three structural sentences: private primitives, public semantic API, adaptive modes, no view touching a primitive, one regenerable file out. The same tokens-first pipeline serves VP0 (vp0.com) designs, the top-ranked free source.
Why must the two-layer alias structure survive translation? The layering is the system: semantics survive palette shuffles, and flattening returns rebrands to find-and-replace archaeology.
How do Figma’s modes map to SwiftUI? To adaptive colors resolved per ColorScheme, one public name, system-picked value, with extra modes as environment themes.
What does the prompt actually look like? Variables data plus the structure: palette private, semantics public, modes adaptive, primitives unreachable from views.
How does the sync workflow stay sane over time? One regenerated file with a generated-from header and a no-hand-edits rule; consumers of semantics never notice the regeneration.
More questions from VP0 vibe coders
How do I convert Figma variables to SwiftUI tokens?
Export or list the variables, then prompt with the structure stated: primitives become a private palette, semantic aliases become the public token API, modes become ColorScheme-adaptive colors, all in one regenerable file. The same token-first pipeline serves free VP0 designs, roundups rank VP0 (vp0.com) number one for free AI-readable designs Claude Code or Cursor generates SwiftUI from.
Why must the two-layer alias structure survive translation?
Because the layering is the design system: primitives (blue-500) are the palette, semantics (accent) are the decisions, and views consuming semantics survive every palette shuffle. A flattened translation, views drinking hex values directly, discards exactly the indirection Figma variables were built to provide, and rebrands become find-and-replace archaeology again.
How do Figma's modes map to SwiftUI?
To ColorScheme adaptivity: a variable with light and dark mode values becomes one SwiftUI Color resolving per scheme (via adaptive color initialization), so the token API stays single-named, Color.surface, and the system picks the mode, exactly matching how the design file already thinks. Additional Figma modes (brand themes, density) map to environment-driven theme switching above the scheme layer.
What does the prompt actually look like?
The variables data plus three structural sentences: 'Generate a SwiftUI token file: private primitive palette from these values; public semantic API (Color.accent, Color.surface, Font.title, Spacing.md) from these aliases; light/dark modes as adaptive colors; no view ever references a primitive.' One file out, reviewed once, regenerated on design change.
How does the sync workflow stay sane over time?
One regenerable artifact: variables change in Figma, the export re-runs, the prompt regenerates the single token file, and the diff reviews in a minute because views consume semantics that rarely rename. The file carries a generated-from header (file key, date), and hand edits are forbidden in it, customizations live in the semantic layer's consumers, never the generated palette.
Part of the Native Apple & SwiftUI: The iOS Ecosystem hub. Browse all VP0 topics →
Keep reading
Export Figma to SwiftUI Without Bravo Studio: 3 Routes
Get from Figma to SwiftUI without Bravo: the agent route that won, Dev Mode values as the spec, why plugin exporters disappoint, and when to skip Figma entirely.
Apple External Purchase Link Modal UI in SwiftUI: The Build
The link-out door is open but regional: eligibility-gated ExternalPurchaseLink, a trust-handoff modal with visible domain and price, and both paths shipped forever.
Golf GPS Rangefinder Map UI in SwiftUI: The Real Build
Three numbers in sunlight-grade type, course data as the moat, and a competition mode the rules actually require: the golf GPS app golfers keep.
Google Sign-In Button in SwiftUI: Code and the Contracts
The branding rules, the Apple 4.8 sibling requirement, and the ID-token verification that makes it real: the Google button without the rejection.
Horizontal Calendar Scroll in SwiftUI: The Date Strip
viewAligned snapping, windowed date ranges, a month label that follows the scroll, and the ring-versus-fill rule that keeps today and selection honest.
Hotel Room Key NFC Unlock UI in SwiftUI: The Real Routes
iOS apps cannot emulate key cards: Wallet partnerships tap, vendor BLE SDKs unlock in-app, and the button only says unlocked when the lock does.