Generate a per-screen SwiftUI mockup from design tokens, temporarily host it as the app entry point, build and screenshot on simulator via XcodeBuildMCP, then revert and register the baseline in screens.json for /design-verify-ios.
Install
npx skillscat add jthorare/agentic-workflow/design-mockup-ios Install via the SkillsCat registry.
Before anything else: read $HOME/.agentic-workflow/toolkit/skills/_preamble.md and follow it (skill index, provider capability map, bootstrap check, session context). Run its Session Close section when this skill finishes.
Design context: read $HOME/.agentic-workflow/toolkit/skills/_design-preamble.md and follow it before continuing.
Design Mockup iOS — SwiftUI Mockup Baseline Generator
Generates a per-screen SwiftUI mockup from design tokens, temporarily makes it the app's entry point, builds and screenshots it on the simulator, reverts the swap, and registers the baseline in screens.json.
Simulator sequence, capability probe, and lock recipe come from _shared/sim-bootstrap.md; artifact names and the screens.json schema from _shared/design-artifact-paths.md.
Step 1: Validate Arguments & Prerequisites
The user must provide a screen name. If missing, stop:
"Usage:
/design-mockup-ios <screen-name>
Example:/design-mockup-ios settings"
design-tokens.json must exist. If missing:
"No design tokens found. Run
/design-analyze-iosfirst to extract tokens from your Xcode assets."
The working tree for the entry-point file must be clean enough to verify the revert later — run git status --short now and record the output as the pre-run baseline.
Step 2: Read Design Context
Read design-tokens.json and (if present) .impeccable.md — palette, typography scale, spacing system, brand personality.
Step 3: Acquire Simulator Lock
Acquire the lock before writing any files (so a lock failure orphans nothing), in a single bash invocation per _shared/sim-bootstrap.md — shell state does not persist between Bash calls:
SHARED_DIR="$HOME/.agentic-workflow/toolkit/skills/_shared"
LOCK_NAME=ios-sim source "$SHARED_DIR/skill-lock.sh"; acquire_lockEvery failure branch in later steps must re-source and release in that same invocation:
SHARED_DIR="$HOME/.agentic-workflow/toolkit/skills/_shared"
LOCK_NAME=ios-sim source "$SHARED_DIR/skill-lock.sh"; release_lockUse return, not exit, in sourced context — skill-lock.sh enables set -euo pipefail in the caller's shell.
Step 4: Generate Mockup.swift
Write Mockup.swift into the main app target folder (temporary — for the build only):
// Mockup.swift — generated by /design-mockup-ios <screen-name>
// Temporary design mockup host — reverted after baseline capture.
import SwiftUI
// MARK: - Color(hex:) helper (defined here so the file is self-contained)
extension Color {
init(hex: String) { /* standard hex → RGB parsing */ }
}
// MARK: - Design Tokens (inline for isolation)
private enum MockupTokens {
enum Colors { /* one static let per color token from design-tokens.json */ }
enum Spacing { /* one static let per spacing token */ }
enum Typography { /* one static let per typography token */ }
}
// MARK: - Mockup View for <screen-name>
struct MockupView: View {
var body: some View {
// Representative <screen-name> screen using the design tokens.
// Realistic placeholder content (not "Lorem ipsum").
// iOS HIG: safe areas, standard navigation, system fonts as fallback.
}
}
#Preview { MockupView() }The mockup should use ALL color, spacing, and typography tokens to demonstrate the full design language (Step 9 reports the coverage %).
Persist a durable copy for /design-implement-ios — this copy is kept, not deleted:
SHARED_DIR="$HOME/.agentic-workflow/toolkit/skills/_shared"
source "$SHARED_DIR/repo-slug.sh"
mkdir -p "$AW_DIR/design"
cp "<path-to>/Mockup.swift" "$AW_DIR/design/Mockup-<screen-name>.swift"Step 5: Entry-Point Swap
A #Preview block never renders in the built app — to earn "app running with mockup visible", temporarily make MockupView the entry point:
- Search the app target's
**/*.swiftfiles for@main. Record and echo the original entry point:original @main: <File.swift>:<StructName>. - Edit that file:
@main→// @main // temporarily disabled by /design-mockup-ios — MUST be reverted. - Append a temporary host to
Mockup.swift:@main struct MockupHostApp: App { var body: some Scene { WindowGroup { MockupView() } } }
Step 6: Build, Launch, Screenshot
Follow the canonical sequence from _shared/sim-bootstrap.md (mcp: xcodebuildmcp/session_show_defaults → discover/schemes if missing → mcp: xcodebuildmcp/list_sims/mcp: xcodebuildmcp/boot_sim → mcp: xcodebuildmcp/build_run_sim or the split build/install/launch path). With the mockup visible: mcp: xcodebuildmcp/screenshot.
If the build fails: report the error, then go directly to Step 7 (revert) and Step 10 (release lock) — never write a baseline from a broken build.
Baseline path (overwrite requires an Ask the user "Baseline exists for <screen-name>. Overwrite? (yes/no)" first):
~/.agentic-workflow/<repo-slug>/design/mockup-ios-<screen-name>.pngOptionally capture a dark-mode variant as mockup-ios-<screen-name>-dark.png.
Step 7: Revert Entry-Point Swap (MANDATORY)
This step runs on every path — success, build failure, or capture failure:
- Edit the original entry-point file: restore
@main(remove the comment marker). - Delete the temporary
Mockup.swiftfrom the app target (the persisted$AW_DIR/design/Mockup-<screen-name>.swiftcopy stays). - Verify with git: run
git status --shortandgit diff -- <original-entry-point-file>— output must match the Step 1 pre-run baseline, and the diff must be empty. If any residue remains, fix it before reporting. Echo:revert verified: git diff clean.
Step 8: Approval & screens.json
Read the captured baseline PNG and present it. Ask the user: Approve / Revise (Revise = adjust MockupView, re-run Steps 5–7; cap 5 rounds — on exceed, stop and report unapproved with no screens.json entry). On Approve, record the UTC timestamp as approved_at.
Determine the nav recipe — how /design-verify-ios reaches this screen in the real app: infer from the app's navigation or Ask the user (e.g., "Settings tab → Profile row"). Express as [{"action":"tap","target":"<label or x,y from mcp: xcodebuildmcp/snapshot_ui>"}], or null for the launch screen.
Read → mutate → Write ~/.agentic-workflow/<repo-slug>/design/screens.json (never clobber other screens), per the CD4 schema in _shared/design-artifact-paths.md:
{ "schema": "screens/v1",
"viewports": {"mobile":"375x812","tablet":"768x1024","desktop":"1440x900"},
"screens": { "<screen-name>": {
"route": null,
"nav": [ {"action":"tap","target":"<label or x,y>"} ],
"baselines": { "ios": "mockup-ios-<screen-name>.png" },
"approved_at": "<ISO timestamp>",
"baseline_stale": null,
"source": "design-mockup-ios" } } }Add "ios-dark": "mockup-ios-<screen-name>-dark.png" to baselines if captured.
Step 9: Token Coverage
Count distinct tokens in design-tokens.json (colors + spacing + typography) and search $AW_DIR/design/Mockup-<screen-name>.swift for how many are actually referenced. Report:
token coverage: <used>/<total> (<pct>%)If below 100%, list the unused tokens so the next revision can incorporate them.
Step 10: Release Simulator Lock
Final step, success or failure — single invocation:
SHARED_DIR="$HOME/.agentic-workflow/toolkit/skills/_shared"
LOCK_NAME=ios-sim source "$SHARED_DIR/skill-lock.sh"; release_lockStep 11: Report
iOS Mockup Baseline Created
============================
Screen: <screen-name>
Mockup source: ~/.agentic-workflow/<repo-slug>/design/Mockup-<screen-name>.swift (persisted)
Baseline: ~/.agentic-workflow/<repo-slug>/design/mockup-ios-<screen-name>.png
screens.json: entry written (nav: <recipe|null>, approved_at: <ISO>)
Token coverage: <used>/<total> (<pct>%)
Entry point: swap reverted, git diff cleanRules
- The mockup is a design artifact, not production code — optimize for visual completeness, not code quality
- Inline all design tokens and the
Color(hex:)extension so the file is self-contained - Never write a baseline from a broken build
- The entry-point revert (Step 7) is mandatory on every path and must be verified with
git diffbefore reporting - Keep
design/Mockup-<screen-name>.swift—/design-implement-iosreads it as the primary reference; only the temporary in-targetMockup.swiftis deleted - Lock ordering: acquire before any file is written; release as the final step, success or failure
Next steps
/design-implement-ios— generate production Theme.swift and SwiftUI components from the persisted mockup/design-verify-ios <screen-name>— compare the implementation against this baseline/design-refine— iterate the SwiftUI mockup before implementation