RORK LABJP
PLAY — Google Play's target API level 36 requirement took effect yesterday, August 31. From today, new apps and updates must target Android 16VISIBILITY — Apps still on API 35 stay listed but disappear for users on newer Android versions. No error is raised; new installs simply fade, which makes the change easy to missEXTENSION — If you missed the deadline, an extension through November 1, 2026 can be requested in Play Console — best filed alongside a concrete migration planAPPLE — On the Apple side, the event lands September 9 and iOS 27 is reported to ship September 14. Testing generated apps on iOS 27 hardware before release week is time well spentEXPO — Expo released expo-paste-input on August 28, a native module that brings image, GIF, and sticker paste to React Native TextInputEAS — EAS Observe reached general availability on August 20, putting crash and performance monitoring on the same EAS platform as builds and updatesPLAY — Google Play's target API level 36 requirement took effect yesterday, August 31. From today, new apps and updates must target Android 16VISIBILITY — Apps still on API 35 stay listed but disappear for users on newer Android versions. No error is raised; new installs simply fade, which makes the change easy to missEXTENSION — If you missed the deadline, an extension through November 1, 2026 can be requested in Play Console — best filed alongside a concrete migration planAPPLE — On the Apple side, the event lands September 9 and iOS 27 is reported to ship September 14. Testing generated apps on iOS 27 hardware before release week is time well spentEXPO — Expo released expo-paste-input on August 28, a native module that brings image, GIF, and sticker paste to React Native TextInputEAS — EAS Observe reached general availability on August 20, putting crash and performance monitoring on the same EAS platform as builds and updates
Articles/Dev Tools
Dev Tools/2026-03-21Intermediate

When Your Figma Comp and Your Rork Screen Don't Match — It's Almost Always These Five Properties

You hand Figma to Rork, the generated screen has every element in place, and it still looks wrong. Comparing the numbers instead of the pixels shows the gap collapses into five properties. Includes an Auto Layout translation table and a token file to ship with your prompt.

Rork548Figma8Design5React Native234Design Tokens3Auto LayoutUI/UX3

You spend an afternoon tightening a comp in Figma, hand it to Rork, open the build on a device, and think: everything is here, and it's still wrong.

That was my situation. Every element present. Colors correct. Order correct. Put it next to the Figma frame and it read as a different screen. The frustrating part wasn't the mismatch — it was that I couldn't name it. "Looks a bit clumsy" was as far as I got, which meant every Fix Now request came out vague, and every fix came back slightly off target. As an indie developer, design and implementation are the same pair of hands, so that vagueness comes back as hours you can't account for.

What broke the loop was giving up on looking. I opened Figma's Dev Mode, wrote down the values for one component, opened the generated StyleSheet beside it, and compared numbers. Tedious work, but the shape of the problem appeared quickly. The differences weren't scattered. They kept landing on the same five properties.

Below are those five, plus the Auto Layout translation table I keep on hand and the token file I now attach to every prompt.

Compare numbers, not screenshots

One process note before the list.

Putting the Figma frame and a device screenshot side by side did not work well for me. Eyes judge the overall impression, which is exactly the wrong resolution for finding a root cause. More than once I was certain the padding was too generous when the actual culprit was line height.

The approach that worked: pick one component, write down the Figma values, and read the corresponding values out of the generated code. Dev Mode gives you CSS-equivalent numbers directly if your plan includes it; if not, copying the right-panel values by hand is enough.

Do this for five or six components and the same category of difference shows up again and again. At that point you stop fixing instances and start fixing categories — diagnose the cause once, and every later component falls to the same prescription.

Translate Auto Layout into flexbox vocabulary first

Auto Layout and flexbox think alike, which tempts you to treat them as interchangeable. The names differ, though, and that difference is exactly where prompt instructions get slippery.

Figma (Auto Layout)React Native styleWhere it bites
Vertical layoutflexDirection: 'column'RN defaults to column — the opposite of the web
Horizontal layoutflexDirection: 'row'
Gap between itemsgapSubstituting margin doubles the edge spacing
Padding (per side)paddingTop, etc.Figma's grouped vertical/horizontal fields mislead here
Main-axis alignmentjustifyContent
Cross-axis alignmentalignItems
Fill container (main axis)flex: 1The single most common mismatch — see below
Fill container (cross axis)alignSelf: 'stretch'Same. width: '100%' fights the parent's padding
Hug contentsNo size specified
Fixedwidth / height
WrapflexWrap: 'wrap'

gap is available from React Native 0.71 onward. On older setups you fall back to margins, which means something has to cancel the trailing child's spacing — and that cancellation is a reliable source of generated-code drift. Check your version before you start.

The five places the gap collects

1. Fill and Hug swapped

This was the most frequent by a wide margin. Something set to Fill container in Figma comes back sized to its contents, or the reverse.

It reads as "vaguely centered" or "there's leftover space on the right," which is why it rarely gets suspected as the cause.

When fixing it, separate main axis from cross axis. Inside a column container, "stretch to full width" is a cross-axis concern, so alignSelf: 'stretch'. "Absorb the remaining height" is main axis, so flex: 1. Reaching for width: '100%' instead adds to the parent's padding and pushes the element past the edge.

2. Line height

Figma text is frequently left on Auto line spacing, in which case the real value comes from the font's metrics. React Native's lineHeight is an explicit number, and if you omit it you inherit a platform default. The two diverge easily.

A 2–3px difference across a five-line paragraph is a 10px difference in block height. Nearly every time I thought "the spacing is too loose," this was it.

If Figma specifies line spacing as a percentage, convert with fontSize × percentage. If it's on Auto, read the computed value in Dev Mode and pin that number in code. Better still, switch the design side to explicit values so the next comparison is trivial.

3. Letter spacing

Less visible than line height, but it matters in headings. Figma expresses letter spacing as a percentage; React Native expects points. Convert with fontSize × percentage ÷ 100.

Two percent on a 12px font is 0.24px. That sounds negligible, but it accumulates across a heading — enough to move a line break by a character. One character is enough to change how a screen reads.

4. Stroke alignment

Figma strokes can be Inside, Center, or Outside. React Native's borderWidth is always inside.

A 100px box with a 1px Outside stroke occupies 102px in Figma and 100px in React Native, with the border eating 1px of the interior. When cards sit in a row, this is why the spacing between them looks subtly uneven.

The low-drama fix is to standardize on Inside strokes in the design file. If Outside has to stay, the code needs the box dimensions increased by twice the stroke width.

5. Shadows

This is the one where you should stop chasing an exact match.

A Figma drop shadow carries X, Y, blur, spread, and a color with opacity. Classic React Native shadows give iOS shadowColor, shadowOffset, shadowRadius, and shadowOpacity, while Android gets elevation alone — no color, no direction. There is also no classic equivalent for spread.

Blur doesn't transfer directly either. As a starting point, set shadowRadius to roughly half the Figma blur and tune on a device. Trying to derive an exact formula took longer than eyeballing from a close starting value.

Newer React Native versions support boxShadow, but availability depends on your version and architecture settings. Confirm it works in your project before designing around it.

Attach the numbers as text, not just a screenshot

All five have something in common: none of them are readable from a screenshot.

Images communicate structure and layout well. They cannot tell you whether a line height is 22 or 24. So Rork fills that in by inference, and the inference misses. Obvious in hindsight.

Now I send numbers alongside the image. Exporting Figma Variables directly would be ideal, but the Variables read API is limited to higher-tier plans. Without it, writing out only the values you actually use is plenty — about ten minutes of work.

// tokens.ts — only the values actually in use, lifted from Figma Variables
// as const keeps fontWeight from widening to string so StyleSheet accepts it directly
export const t = {
  color: {
    surface: '#171B22',
    border: '#232A34',
    text: '#E6E9EF',
    textMuted: '#9AA4B2',
    accent: '#4F8CFF',
  },
  space: { xs: 4, sm: 8, md: 12, lg: 16, xl: 24 },
  radius: { sm: 6, md: 12, pill: 999 },
  type: {
    // Pinning lineHeight and letterSpacing in points is the whole point of this file
    title: { fontSize: 20, lineHeight: 26, letterSpacing: -0.2, fontWeight: '600' },
    body: { fontSize: 15, lineHeight: 22, letterSpacing: 0, fontWeight: '400' },
    caption: { fontSize: 12, lineHeight: 16, letterSpacing: 0.2, fontWeight: '400' },
  },
} as const;

Paste that into the prompt with one instruction: reference these tokens for color, spacing, and typography, and don't write raw values into components. That alone cut down the stream of hardcoded #171B22 in generated output considerably.

Once the code comes back, leaving the Figma spec in comments makes the next comparison much faster.

import { Platform, StyleSheet } from 'react-native';
import { t } from './tokens';
 
export const card = StyleSheet.create({
  root: {
    // Figma: Vertical / gap 12 / padding 16 / Fill container horizontally
    flexDirection: 'column',
    gap: t.space.md,
    padding: t.space.lg,
    alignSelf: 'stretch', // width: '100%' would fight the parent's padding
    backgroundColor: t.color.surface,
    borderRadius: t.radius.md,
 
    // Figma: Stroke 1px / Inside (Outside would make the outer box 2px larger)
    borderWidth: 1,
    borderColor: t.color.border,
 
    // Figma: Drop shadow Y=4 / blur 16 / spread 0 / #000 24%
    ...Platform.select({
      ios: {
        shadowColor: '#000',
        shadowOffset: { width: 0, height: 4 },
        shadowRadius: 8, // start at half the blur, then tune on device
        shadowOpacity: 0.24,
      },
      // Android only has elevation — no color, no direction. Approximate and move on.
      android: { elevation: 4 },
    }),
  },
  title: { ...t.type.title, color: t.color.text },
  body: { ...t.type.body, color: t.color.textMuted },
});

The broader idea of treating tokens as a single source of truth gets fuller treatment in stopping color and spacing drift across regenerations with design tokens. If you'd rather express the same vocabulary in Tailwind, setting up NativeWind in a Rork app covers that path.

Fix in a fixed order

When several differences surface at once, fixing whatever catches your eye creates rework, because changing an upstream property moves everything downstream.

The order I settled on:

  1. Structure — nesting and flexDirection. Get this wrong and every later adjustment is thrown away
  2. Dimensions — Fill/Hug, gap, padding. One and two account for most of the visual gap
  3. TypelineHeight, letterSpacing, fontWeight
  4. Decoration — corner radius, borders, shadows

Do three and four first and any layout shift from step two forces you to redo them. Lock down one and two, and the rest can be tuned independently.

The same granularity works for Fix Now requests. Not "make it match the design," but "set this component's gap to 12 and padding to 16" — name the layer and the number.

Deciding what you won't match

Matching Figma and a real device exactly isn't a realistic goal, and I've stopped treating it as one.

Shadows will only ever approximate on Android. Font rendering differs between Figma and each platform. And if you honor the user's Dynamic Type setting — which you should — the text will not be the comp's size anyway. It's also something App Store reviewers look at, and pinning it would make the app worse, not better.

So I decide up front what's in scope. Structure, dimensions, and typographic hierarchy get matched. Shadow minutiae and anything driven by user settings do not. Agreeing on that line with the design side ahead of time keeps review from turning into an argument about a single pixel.

Generation tools like Rork genuinely reduce implementation time. What I also noticed is that some of the reclaimed time moved straight into closing the gap with the design. Getting through that work quickly means talking in numbers rather than impressions.

What to try next

Pick your most reused component — a card, a list row, whatever appears most often.

Put its Figma values next to the generated StyleSheet and check only the five properties above: Fill/Hug, line height, letter spacing, stroke alignment, shadow. Two or three will almost certainly apply. Write those values into tokens.ts and attach it to your next prompt. That's one full pass.

After the first pass, later components fall to the same prescription. By my third component, the side-by-side comparison had become unnecessary.

If this shortens the detour for someone stuck at the same spot, that's a good outcome.

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.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Dev Tools2026-07-14
Designing Seams That Survive AI Regeneration in Rork
Every follow-up prompt to Rork can quietly wipe out logic you wrote by hand. Protecting it with prompts is a patch, not a fix. Here is how to separate generated code from code you own, and draw a boundary that regeneration cannot reach, with working Zustand and service-layer examples.
Dev Tools2026-04-25
Skeleton Screens in Rork Apps — Practical Patterns for Better Perceived Performance
If your Rork app still shows a spinner on a blank screen during load, you are leaving a lot of perceived performance on the table. Here is how I drop skeleton screens and shimmer effects into Rork-generated React Native code without over-engineering it.
Dev Tools2026-03-30
Rork × React Native Reanimated & Gesture Handler — Building 60fps Animations and Advanced Gesture Interactions
Keeping Reanimated 3 and Gesture Handler at 60fps, told through the production pitfalls I hit running wallpaper and calming-tone apps: delayed runOnJS, useDerivedValue caching, FlashList pairing, and missing cancelAnimation — each with real measurements.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →