Before you start
This guide assumes:
- FlowDeck is installed and the AI skill pack is loaded into your agent. If not, run through the getting-started guide and the AI agents setup guide first.
- An iOS or macOS project that builds with
flowdeck build. - A design source: a Figma file, an image mockup (PNG / JPG), or a clear verbal description.
- If you're using Figma, the Figma MCP server installed on your machine. That gives the agent exact spacing, colors, and typography tokens. Image-only sources work too; the agent estimates from the pixels.
By the end you'll have a working pattern for translating a design into SwiftUI with an agent that captures, compares, and refines until the implementation matches.
Step 01
Pick your design source and prepare it
The methodology is the same across sources; the difference is how the agent extracts specs.
- Figma link, best signal. The agent can read exact spacing, color tokens, font sizes, and effects via the Figma MCP server. Skip ahead to layered implementation.
- Image mockup, common path. The agent visually estimates measurements, colors, and typography from the pixels. Higher chance of optical drift; the validation loop catches it.
- Verbal description, last resort. Works if you can be precise ("32pt padding, system blue, headline weight"). The agent fills gaps with sensible defaults.
Drop the image or Figma link into your agent's session. For images, the agent reads them directly; for Figma, the agent fetches via the MCP server. Either way, point it at one screen at a time, agents implement individual screens cleanly but struggle with whole-app jobs in one shot.
Step 02
Tell the agent to read the design first
Before any code, the agent should establish what the design communicates. Visual hierarchy, intended action, brand tone. Ask explicitly:
Read this design and identify the visual hierarchy.
What's the primary focal point, the secondary content,
and what's the intended user action? Don't write code yet.
The agent should respond with a structured breakdown: primary focus, secondary content, tertiary/ambient elements, and the CTA. This step prevents the agent from rushing to .padding() calls before it understands what's important on the screen.
If you have an exact Figma source, this step is shorter (specs are explicit). With image sources, the read step is most of the value, it forces the agent to think before it estimates.
Step 03
Ask for layered implementation
Designers don't think in VStack { Text(); Spacer(); Button() }. They think in layers: structure → typography → color → shape → effects. Asking the agent to implement in that order produces cleaner code and easier-to-iterate output.
Implement this in layers. First the structural skeleton
(VStack/HStack/ZStack and spacing). Then typography
(font sizes and weights). Then colors. Then shapes
and corner radii. Then shadows and effects. Stop after
each layer and tell me what you did.
This gives you natural checkpoints. After the structure layer, you can correct the layout before colors and shadows are sunk costs. The agent gets feedback while it's cheap to apply.
Two specific things to require in the prompt:
- Explicit spacing values. The agent should use
.padding(.horizontal, 24)not bare.padding(). Bare padding is a guess; explicit values are auditable. - Exact colors. Hex values, named assets, or
Color(red:green:blue:), not.grayor.secondary. Generic SwiftUI colors are placeholders; the design has specific values.
Step 04
Trigger the validation loop
This is the prompt that turns the agent's implementation into something that matches the design. One sentence, two rules baked in:
Build the app and use FlowDeck UI to validate and
compare the app side by side with the design. Fix one
discrepancy at a time. Don't move on until they match.
Behind the scenes, the agent runs the FlowDeck validation loop: build the project, launch on the simulator, navigate to the screen, capture a screenshot, read it back, compare to the design source, identify the single most visible difference, fix it, and repeat. You see the comparison after each cycle; the agent does the iteration.
The "one discrepancy at a time" rule is load-bearing. Agents that batch three fixes per cycle introduce regressions; agents that fix one thing per build converge in 5-10 cycles. The prompt makes the discipline explicit so the agent doesn't try to be efficient by skipping ahead.
Your role during the loop: this is coffee time. Each cycle (build → launch → screenshot → compare → fix → rebuild) runs for a couple of minutes, and a full convergence is usually 5-10 cycles, so a single screen can take 30+ minutes end to end. Walk away. The agent keeps iterating in the background. Come back, skim the screenshots, and step in only if it's chasing the wrong discrepancy ("the title spacing is fine; the button color is the real issue"). Approve when the comparison matches.
For long iteration sessions, the agent may start a background capture session so it doesn't repeat the screenshot call every turn. Captures land in ./.flowdeck/automation/sessions/ as latest.jpg; the agent reads from disk between actions. You don't have to manage any of this; the skill handles the switch.
Step 05
Ask for the optical corrections
The literal measurements can be correct and the screen can still look wrong. After the validation loop converges, give the agent one more prompt to chase the perceptual gaps:
Now look for perceptual issues. Optical centering, color
in context, multi-layer shadows for depth, continuous corner
radii (squircles), no pure black for text. Adjust where you
see them.
This is the gap between engineer-quality and designer-quality UI. Things math gets right but eyes get wrong:
- Optical centering. Mathematically centered text in a button often looks low (descenders pull weight down). Asymmetric icons like a play triangle look off-center even when the bounding box is centered. The fix is a 1-2pt offset toward the perceived center.
- Color in context. A hex value that looks right next to white can feel heavy next to a gradient. The agent checks colors against the actual neighboring elements, not in isolation.
- Squircles, not circular corners. Apple's design language uses continuous corners (
RoundedRectangle(cornerRadius: 16, style: .continuous)). The default.cornerRadius()modifier produces circular arcs that read as "off" against Apple's standard components. - Multi-layer shadows. A single
.shadow()looks flat. Real depth stacks a tight close shadow with a wider ambient one. The agent adds both when the design has elevation. - "True black" is rarely black.
#000000reads as harsh next to Apple's UI. Production designs use#1A1A1Aor thereabouts. The agent swaps pure black if it crept in as a default.
The agent re-captures after each adjustment and continues the same compare-and-fix loop. You see one screenshot per change.
Step 06
Ask the agent to verify on a small screen and in dark mode
A design that's pixel-perfect on iPhone 16 can break on iPhone SE or in dark mode. One prompt covers both:
Now run the same loop on iPhone SE and in dark mode.
Fix anything that breaks.
Behind the scenes, the agent reboots a smaller simulator (or sets the existing one to dark mode), reruns the build-capture-compare cycle, and reports the discrepancies. Common breakages it'll catch:
- Text overflow at smaller widths (fixed-size fonts and tight layouts).
- Colors that read fine in light mode and disappear in dark.
- Gradients with the wrong direction at smaller widths.
- Shadows that vanish on dark backgrounds (need borders or lighter elevation instead).
For apps that ship on iPad too, add iPad as a third target in the same loop. Layouts that work on iPhone often break on iPad: single columns become awkward at wider widths, hardcoded paddings look lost in extra space. Same prompt, swap the simulator name.
A design isn't done until it survives every target you support: phone, smallest phone, dark mode, and iPad if it's in scope. Treating that as the implicit acceptance test stops you shipping screens that look perfect in one configuration and broken in the others.
This loop works for macOS apps too. Substitute flowdeck ui mac screen for the iOS capture command and target the running macOS app instead of a simulator. The compare-and-fix mechanics are identical.
Patterns that keep this loop fast
- Stay on one screen.
- Agents implement individual screens well. They struggle with whole-app jobs. Drive the iteration loop one screen at a time, even if you have ten mockups.
- Use a fresh build between major changes.
- SwiftUI's previews and incremental rebuilds can mask layout bugs that show up on a full rebuild. After every layer change, do
flowdeck clean+flowdeck buildif something looks off. It's a 30-second sanity check. - Keep the design source visible in the agent context.
- If you're using an image mockup, attach it to the conversation again periodically. Long agent sessions drift from the original; re-anchoring keeps the comparison honest.
- Limit the agent to SwiftUI you can read.
- Agents will sometimes reach for custom
PreferenceKeymachinery to solve a layout the design doesn't require. Constrain the prompt: "use standard SwiftUI containers; no custom layouts unless I ask." Your future self will thank you when reviewing the code. - Capture before the fix, not after.
- Ask the agent to read the captured screenshot before proposing the next change. Agents that propose fixes without first inspecting the current state are guessing.
When things go wrong
- The agent's implementation looks broadly right but never converges
- Almost always: the agent is fixing multiple things per round. Force one-at-a-time: "identify the single most visible discrepancy, fix only that, then capture and report back." Convergence happens in 5-10 cycles when constrained, never when unconstrained.
- Colors are close but not matching
- If the source is an image, sampled colors from a screenshot have JPEG / display profile drift. Ask the agent to use a color picker on the highest-quality source available, or, if you have access, pull tokens from Figma directly.
- Text breaks at smaller screen sizes
- The agent picked a fixed font size where it should have used a Dynamic Type style. Ask it to convert sizes to named styles (
.body,.headline,.subheadline,.title, etc.) wherever the original design's size matches one. Named styles scale with accessibility settings; fixed sizes don't. - The agent invents accessibility identifiers that don't match anything
- It's trying to be helpful but the result is unusable for testing. Tell it to use
.accessibilityIdentifier("loginBtn")only when you ask for it explicitly. Free-form invention pollutes the accessibility tree. - Implementation looks right in dark mode but wrong on a real device
- Simulator dark mode doesn't always match the OLED black of a physical iPhone. If the design hinges on true-black backgrounds, verify on a paired device with
flowdeck run -D "iPhone"+flowdeck ui simulator screen(which still works on the simulator host even when targeting a device).
Annex
How this compares to manual design implementation
For reference, what the engineering workflow looks like with and without the agent + FlowDeck loop.
| Task | Manual | Agent + FlowDeck |
|---|---|---|
| Read the design | Engineer eyeballs Figma / image | Agent reads file or Figma MCP, structures the response |
| Implement | Write SwiftUI, switch to Xcode preview, iterate | Agent writes SwiftUI in layers, you review at checkpoints |
| Validate the rendered output | Build in Xcode, navigate, eyeball, alt-tab back | flowdeck ui simulator screen, agent reads the PNG |
| Iterate | Tweak, rebuild, look again. Tens of rebuild cycles. | Agent runs the loop with one fix per cycle |
| Verify dark mode + small screen | Manually switch settings, rebuild, eyeball | Same loop, different simulator + appearance flag |
The methodology shifts the engineer's role from "implement the design" to "review the agent's interpretation." The agent does the iteration; you do the design judgment.
Read next
Let an AI agent test your iOS app →
Further reading
- Things to ask your AI agent, more example prompts beyond the design loop.
- iOS UI automation deep dive, the accessibility tree, gestures, and what is and is not reachable.
- Autonomous iOS UI testing with Claude Code, the agent-driven UI workflow in long form.
- Full CLI reference, in the FlowDeck docs.