●TOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13●OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude Code●SIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App Store●MAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessage●NATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core ML●SEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the round●TOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13●OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude Code●SIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App Store●MAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessage●NATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core ML●SEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the round
Rork × Figma Integration — Design-to-App Workflow for Code Automation
Production lessons from rebranding wallpaper, calming-tone, and intention-style utility apps I have run as an indie developer since 2013 — how to name design tokens, cap Auto Layout depth, design Variants, normalize icons, and use Boolean Properties so that Rork generates clean SwiftUI / React Native code.
I'm Hirokawa, an artist and indie developer running iOS and Android apps since 2013. I currently maintain about six quiet utility apps — wallpaper, calming-tone, and intention-style — with around 50 million cumulative downloads and AdMob revenue hovering near USD 7K/month. At Dolice Labs I also handle the design for four sibling blog sites.
Polishing the UI in Figma, then handing it to Rork to generate production app code — this loop works particularly well at the indie scale, where one person owns both the design and the implementation. But Figma-side habits leak directly into Rork's generated code, so a lot of decisions need to be made up front. What follows are the rules I've actually been forced to adopt after running the loop on real apps.
Setup and context
A designer perfects a UI in Figma. A developer rewrites the code from scratch. Information is lost. Implementation costs explode. The original vision fades.
Rork Max × Figma integration addresses this. It generates production-quality app code directly from Figma files in seconds, narrowing the gap between design and implementation — provided the Figma file is shaped to make that possible. Below I walk through how I set things up, then collect the six production lessons that took me the longest to learn.
Understanding Rork Max × Figma Integration
What Rork Max Extracts From Figma
When Rork Max reads a Figma file, it automatically detects and converts four critical design elements:
Design Tokens
Color palettes (global color variables)
Typography (font name, size, weight, line height)
Spacing and layout scales
Shadows, corner radius, borders
Component Structure
Figma components → Structured SwiftUI/React Views
Component variants → Conditional logic and state management
What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.
WHAT YOU'LL LEARN
✦Design token naming, Auto Layout depth, and Variants axis rules proven across 6 indie apps with 50M+ cumulative downloads
✦Production incidents from rebrands (19 stuck colors, APK 8.4MB→4.1MB, Hot Reload 8.2s→1.4s) and the working code that prevents them
✦How to shape a Figma file so Rork emits clean SwiftUI / React Native — every rule shown as Before / After
Secure payment via Stripe · Cancel anytime
✦
Unlock This Article
Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.
When colors or fonts change, re-export from Figma and all UI updates automatically:
// BeforeColorPalette.Primary.c600 = #2563EB// Figma color changed to: #3B82F6// ↓ Rork Max regeneratesColorPalette.Primary.c600 = #3B82F6 // Auto-updated// All Buttons, Cards, Badges reflect change ✓
Six things the docs won't tell you — lessons from production
What follows are incidents I actually had to recover from in my own apps, plus the rules I now operate under. None of these appear in the Figma docs or the Rork tutorials, but each one materially affects the quality of generated code.
1. Number-based color token names break on the first rebrand
primary-600 and friends feel clean for the first six months. The moment you refresh the brand color, though, Figma updates primary-600 to a new value — but any place in Rork's generated code where the literal hex slipped through stays put. On a wallpaper-app rebrand in 2024, 19 out of 132 components still carried #2563EB after the supposed migration, and I burned three days on the review thread.
Rork writes these out as SwiftUI / React Native color extensions, so calls like Button(intent: .cta) read naturally. Migrating off the numbered names took me four focused days across the six apps. Every rebrand since has wrapped in half a day.
2. Don't let Auto Layout nest past four levels
Figma is happy to nest Auto Layout indefinitely. Rork mirrors that depth as VStack > HStack > VStack > ZStack > VStack in the output. On SwiftUI it makes the update scope hard to reason about; on React Native it slows Hot Reload.
The "today's quiet line" screen in a calming-tone app sat at seven levels of nesting. Rork generated 412 lines of SwiftUI and Hot Reload took 8.2 seconds. After I flattened to three levels, it dropped to 189 lines and 1.4 seconds.
Rules I now follow
The root is always a single VStack (or ScrollView + VStack)
One level down, group by sections — one HStack/VStack per section
Use Spacer and frame padding to handle fine positioning instead of more frames
If a section genuinely needs deeper structure, extract it into a Component
Rork optimizes each component in isolation, so the visible "total nesting depth" stays at three.
3. Cap Variants at three axes; push the rest into Booleans
A Button with color × size × state × icon × loading Variants ends up as 27+ cells in Figma. Rork dutifully expands that into a switch with nearly 60 lines of branches.
The Premium button in an intention-style app started life with five axes. The resulting switch was so dense that every new developer asked me which combination ran in which case. After collapsing to three axes — color × size × state — and moving icon and loading to Boolean Properties, the generated branching shrank to about 18 lines.
The rule
Variants only for things that are visually independent and recognizable: color / size / state cover almost everything
Icon presence, loading, disabled — all Boolean Properties
Text content is, of course, a Text Property
4. Boolean Properties match Rork's code generation; Text Properties don't
Rork compiles a Boolean Property cleanly into if isLoading { ... }. Text Properties stay as strings, so you can't expect Rork to branch on label content. Anything you want to gate on belongs in a Boolean from the start.
Across my apps, isPremium / isLoading / hasIcon — three Booleans — covers eight permutations without bloating Variants.
5. Normalize icons to a 24×24 viewBox before they enter Figma
Mixed SVG viewBoxes (0 0 16 16, 0 0 20 20, 0 0 24 24, 0 0 32 32) push Rork off the Image(systemName:)-style lightweight path and into rasterizing the SVG at build time. On Android, that means four density buckets of PNG land in the APK.
The intention-style app shipped 312 icons and the APK sat at 8.4 MB. After I normalized every viewBox to 24×24 — SF Symbols-style — Rork chose the lightweight path and the APK dropped to 4.1 MB.
Normalization script (Bash + svgo)
#!/usr/bin/env bash# normalize_icons.sh — normalize SVGs before importing into Figmaset -euo pipefailINPUT_DIR="$1"OUTPUT_DIR="${2:-./icons-normalized}"mkdir -p "$OUTPUT_DIR"for svg in "$INPUT_DIR"/*.svg; do name=$(basename "$svg") # 1. Clean and unify npx svgo "$svg" \ --multipass \ --plugins='preset-default,prefixIds' \ -o /tmp/cleaned.svg # 2. Strip width / height so Figma controls size sed -i -E 's/(width|height)="[^"]*"//g' /tmp/cleaned.svg # 3. Force viewBox to 24x24 sed -i -E 's/viewBox="[^"]*"/viewBox="0 0 24 24"/' /tmp/cleaned.svg cp /tmp/cleaned.svg "$OUTPUT_DIR/$name" echo "✓ normalized $name"doneecho "done: $(ls -1 "$OUTPUT_DIR" | wc -l) icons"
I run this in CI now. Whenever a designer adds a new icon, the APK doesn't quietly inflate.
6. Restrict Auto Layout Gap to multiples of four
Allowing 5px / 7px / 13px Gaps creates .padding(5) / .padding(7) calls in Rork's output, and every review thread ends with someone asking whether those numbers are intentional. I now allow only 4 / 8 / 12 / 16 / 24 / 32 / 48 and ship a Figma Plugin that flags anything else.
Linter core (TypeScript)
// figma-plugin/gap-lint.ts// Run inside Figma: check itemSpacing on every Auto Layout frame.const ALLOWED_GAPS = [4, 8, 12, 16, 24, 32, 48];function lintGaps(node: SceneNode): void { if ( node.type === "FRAME" && node.layoutMode !== "NONE" && node.itemSpacing !== figma.mixed ) { const gap = node.itemSpacing; if (!ALLOWED_GAPS.includes(gap)) { figma.notify(`❌ ${node.name}: gap=${gap}px (not allowed)`, { error: true, }); figma.currentPage.selection = [node]; figma.viewport.scrollAndZoomIntoView([node]); } } if ("children" in node) { for (const child of node.children) { lintGaps(child); } }}figma.currentPage.findAll().forEach(lintGaps);figma.notify("✓ gap lint complete", { timeout: 1500 });
Since this rule went in, design-review time across the six apps dropped from an average of 28 minutes to 9. The vague "are these aligned?" conversations vanished — the Figma plugin catches the offenders before they reach a human.
A single next step
If you read this far and want exactly one thing to try first, rename your Figma Variables along the intent.* axis. Number-based names will eventually bite you on a rebrand, but renaming is a half-day of work and the difference shows immediately in Rork's generated code.
For my own apps, I introduced the six rules above one at a time, lined up with rebrands or new-screen work. Trying to land everything in a single sprint never worked. Folding each rule in at a moment when the cost is already paid — that's what eventually made the loop sustainable at the scale of six indie apps.
If you run something at a similar scale, I hope a few of these are useful. Thank you for reading.
Share
Thank You for Reading
Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.