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.
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.
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:
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.
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.
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.
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:
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.
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:
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.
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:
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 build if 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 PreferenceKey machinery 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.
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 |
|
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.
When things go wrong
The agent’s implementation looks broadly right but never converges
Colors are close but not matching
Text breaks at smaller screen sizes
The agent invents accessibility identifiers that don’t match anything
Implementation looks right in dark mode but wrong on a real device
