stitch-kit 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/AGENTS.md +139 -0
  2. package/CHANGELOG.md +86 -0
  3. package/README.md +167 -0
  4. package/agents/stitch-kit.md +93 -0
  5. package/bin/stitch-kit.mjs +430 -0
  6. package/docs/architecture.md +118 -0
  7. package/docs/color-prompt-guide.md +119 -0
  8. package/docs/mcp-naming-convention.md +64 -0
  9. package/docs/mcp-schemas/README.md +130 -0
  10. package/docs/mcp-schemas/apply_design_system.json +36 -0
  11. package/docs/mcp-schemas/create_design_system.json +78 -0
  12. package/docs/mcp-schemas/create_project.json +290 -0
  13. package/docs/mcp-schemas/delete_project.json +20 -0
  14. package/docs/mcp-schemas/edit_screens.json +46 -0
  15. package/docs/mcp-schemas/generate_screen_from_text.json +242 -0
  16. package/docs/mcp-schemas/generate_variants.json +77 -0
  17. package/docs/mcp-schemas/get_project.json +137 -0
  18. package/docs/mcp-schemas/get_screen.json +92 -0
  19. package/docs/mcp-schemas/list_design_systems.json +32 -0
  20. package/docs/mcp-schemas/list_projects.json +136 -0
  21. package/docs/mcp-schemas/list_screens.json +56 -0
  22. package/docs/mcp-schemas/update_design_system.json +32 -0
  23. package/docs/mcp-schemas/upload_screens_from_images.json +52 -0
  24. package/docs/prd-to-stitch-workflow.md +137 -0
  25. package/docs/skills-index.md +108 -0
  26. package/docs/tailwind-reference.md +207 -0
  27. package/package.json +41 -0
  28. package/skills/stitch-a11y/SKILL.md +428 -0
  29. package/skills/stitch-a11y/resources/audit-checklist.md +102 -0
  30. package/skills/stitch-animate/SKILL.md +371 -0
  31. package/skills/stitch-animate/resources/animation-patterns.md +248 -0
  32. package/skills/stitch-design-md/SKILL.md +215 -0
  33. package/skills/stitch-design-md/examples/DESIGN.md +54 -0
  34. package/skills/stitch-design-md/examples/usage.md +67 -0
  35. package/skills/stitch-design-md/scripts/fetch-stitch.sh +35 -0
  36. package/skills/stitch-design-system/SKILL.md +314 -0
  37. package/skills/stitch-design-system/resources/tokens-template.css +237 -0
  38. package/skills/stitch-html-components/SKILL.md +344 -0
  39. package/skills/stitch-html-components/resources/architecture-checklist.md +74 -0
  40. package/skills/stitch-html-components/scripts/fetch-stitch.sh +45 -0
  41. package/skills/stitch-loop/SKILL.md +183 -0
  42. package/skills/stitch-loop/examples/SITE.md +39 -0
  43. package/skills/stitch-loop/examples/next-prompt.md +24 -0
  44. package/skills/stitch-loop/examples/usage.md +77 -0
  45. package/skills/stitch-mcp-apply-design-system/SKILL.md +82 -0
  46. package/skills/stitch-mcp-create-design-system/SKILL.md +117 -0
  47. package/skills/stitch-mcp-create-project/SKILL.md +77 -0
  48. package/skills/stitch-mcp-delete-project/SKILL.md +62 -0
  49. package/skills/stitch-mcp-edit-screens/SKILL.md +121 -0
  50. package/skills/stitch-mcp-generate-screen-from-text/SKILL.md +102 -0
  51. package/skills/stitch-mcp-generate-screen-from-text/examples/desktop.md +53 -0
  52. package/skills/stitch-mcp-generate-screen-from-text/examples/mobile.md +71 -0
  53. package/skills/stitch-mcp-generate-variants/SKILL.md +124 -0
  54. package/skills/stitch-mcp-get-project/SKILL.md +67 -0
  55. package/skills/stitch-mcp-get-screen/SKILL.md +117 -0
  56. package/skills/stitch-mcp-get-screen/scripts/fetch-stitch.sh +35 -0
  57. package/skills/stitch-mcp-list-design-systems/SKILL.md +84 -0
  58. package/skills/stitch-mcp-list-projects/SKILL.md +77 -0
  59. package/skills/stitch-mcp-list-screens/SKILL.md +69 -0
  60. package/skills/stitch-mcp-update-design-system/SKILL.md +82 -0
  61. package/skills/stitch-mcp-upload-screens-from-images/SKILL.md +95 -0
  62. package/skills/stitch-mcp-upload-screens-from-images/scripts/encode-image.sh +43 -0
  63. package/skills/stitch-nextjs-components/SKILL.md +181 -0
  64. package/skills/stitch-nextjs-components/resources/architecture-checklist.md +65 -0
  65. package/skills/stitch-nextjs-components/resources/component-template.tsx +101 -0
  66. package/skills/stitch-nextjs-components/scripts/fetch-stitch.sh +45 -0
  67. package/skills/stitch-orchestrator/SKILL.md +337 -0
  68. package/skills/stitch-orchestrator/examples/workflow.md +173 -0
  69. package/skills/stitch-react-components/SKILL.md +236 -0
  70. package/skills/stitch-react-components/references/tailwind-to-react.md +117 -0
  71. package/skills/stitch-react-components/resources/architecture-checklist.md +34 -0
  72. package/skills/stitch-react-components/resources/component-template.tsx +35 -0
  73. package/skills/stitch-react-components/scripts/fetch-stitch.sh +35 -0
  74. package/skills/stitch-react-native-components/SKILL.md +333 -0
  75. package/skills/stitch-react-native-components/resources/architecture-checklist.md +74 -0
  76. package/skills/stitch-react-native-components/resources/component-template.tsx +104 -0
  77. package/skills/stitch-react-native-components/scripts/fetch-stitch.sh +45 -0
  78. package/skills/stitch-remotion/SKILL.md +280 -0
  79. package/skills/stitch-setup/SKILL.md +183 -0
  80. package/skills/stitch-shadcn-ui/SKILL.md +255 -0
  81. package/skills/stitch-skill-creator/SKILL.md +257 -0
  82. package/skills/stitch-skill-creator/references/output-patterns.md +71 -0
  83. package/skills/stitch-skill-creator/scripts/init_stitch_skill.py +229 -0
  84. package/skills/stitch-svelte-components/SKILL.md +282 -0
  85. package/skills/stitch-svelte-components/resources/architecture-checklist.md +62 -0
  86. package/skills/stitch-svelte-components/resources/component-template.svelte +193 -0
  87. package/skills/stitch-svelte-components/scripts/fetch-stitch.sh +36 -0
  88. package/skills/stitch-swiftui-components/SKILL.md +424 -0
  89. package/skills/stitch-swiftui-components/resources/architecture-checklist.md +83 -0
  90. package/skills/stitch-swiftui-components/resources/component-template.swift +131 -0
  91. package/skills/stitch-swiftui-components/resources/layout-mapping.md +155 -0
  92. package/skills/stitch-swiftui-components/scripts/fetch-stitch.sh +45 -0
  93. package/skills/stitch-ued-guide/SKILL.md +124 -0
  94. package/skills/stitch-ui-design-spec-generator/SKILL.md +115 -0
  95. package/skills/stitch-ui-design-spec-generator/examples/usage.md +79 -0
  96. package/skills/stitch-ui-design-variants/SKILL.md +127 -0
  97. package/skills/stitch-ui-prompt-architect/SKILL.md +196 -0
  98. package/skills/stitch-ui-prompt-architect/references/KEYWORDS.md +170 -0
@@ -0,0 +1,83 @@
1
+ # SwiftUI Components — Architecture Checklist
2
+
3
+ Run through this checklist before marking the task complete.
4
+
5
+ ## Xcode project structure
6
+
7
+ - [ ] Views are in `Views/` — one file per view
8
+ - [ ] Reusable components are in `Views/Components/`
9
+ - [ ] Theme tokens are in `Theme/ThemeTokens.swift`
10
+ - [ ] Color extension is in `Theme/Color+App.swift`
11
+ - [ ] Static preview data is in `Models/MockData.swift` — not hardcoded in views
12
+ - [ ] `@main` entry point is in `[AppName].swift`
13
+
14
+ ## SwiftUI correctness
15
+
16
+ - [ ] `@State` is used for local UI state (not business logic)
17
+ - [ ] `@StateObject` / `@ObservedObject` for view models (if MVVM)
18
+ - [ ] `@Environment` used for system values (colorScheme, dismiss, reducedMotion)
19
+ - [ ] No logic in `var body: some View` — extract to computed properties or helper views
20
+ - [ ] Views are small and composable — extract when `body` exceeds ~50 lines
21
+ - [ ] Previews have mock data — no force-unwraps in `#Preview`
22
+
23
+ ## Layout
24
+
25
+ - [ ] `VStack`, `HStack`, `ZStack` used instead of `Group` for layout intent
26
+ - [ ] `Spacer()` used for `justify-content: space-between` patterns
27
+ - [ ] `LazyVStack` / `LazyVGrid` used inside `ScrollView` for long lists
28
+ - [ ] `List` used for data-driven lists (virtualized automatically)
29
+ - [ ] `.frame(maxWidth: .infinity)` replaces `w-full` / `width: 100%`
30
+ - [ ] No hardcoded pixel values where semantic sizing (`font(.headline)`) is available
31
+
32
+ ## Touch targets and interaction
33
+
34
+ - [ ] All interactive views have `.frame(minHeight: 44)` — Apple HIG minimum
35
+ - [ ] Buttons use SwiftUI `Button` (not `.onTapGesture` on arbitrary views)
36
+ - [ ] Icon-only buttons have `.accessibilityLabel("Action name")`
37
+ - [ ] Press animation: `.scaleEffect(isPressed ? 0.96 : 1.0)` with `.spring()`
38
+ - [ ] Reduced motion respected: `@Environment(\.accessibilityReduceMotion)` gates animations
39
+
40
+ ## Colors and dark mode
41
+
42
+ - [ ] `@Environment(\.colorScheme) private var colorScheme` in every themed view
43
+ - [ ] `private var theme: ThemeTokens { colorScheme == .dark ? .dark : .light }` pattern used
44
+ - [ ] No hardcoded `Color(hex:)` values in views — always via `theme.*`
45
+ - [ ] Tested in both light and dark mode (⌃⌘A in Simulator)
46
+ - [ ] `#Preview("Dark Mode")` block exists for every component
47
+
48
+ ## Typography
49
+
50
+ - [ ] Semantic fonts used: `.font(.headline)`, `.font(.body)` — NOT `.font(.system(size: 17))`
51
+ - [ ] Dynamic Type works: increase text size in Simulator and verify layout holds
52
+ - [ ] Text doesn't truncate unexpectedly — `.lineLimit(nil)` or `.fixedSize` where needed
53
+
54
+ ## Images
55
+
56
+ - [ ] Remote images use `AsyncImage` — no sync image loading
57
+ - [ ] Local images are in `Assets.xcassets` and loaded with `Image("name")`
58
+ - [ ] Aspect ratios are explicit: `.aspectRatio(16/9, contentMode: .fill)`
59
+ - [ ] Decorative images use `Image(decorative: "name")` — screen reader skips them
60
+ - [ ] Content images have `.accessibilityLabel("Description")`
61
+
62
+ ## Accessibility
63
+
64
+ - [ ] Buttons are labeled by their `Text` child automatically — verify with VoiceOver
65
+ - [ ] Icon-only buttons have `.accessibilityLabel("Action name")`
66
+ - [ ] Related text groups combined: `.accessibilityElement(children: .combine)`
67
+ - [ ] Custom accessibility actions for swipe gestures if applicable
68
+ - [ ] App tested with VoiceOver enabled — no silent tappable areas
69
+
70
+ ## Navigation
71
+
72
+ - [ ] `NavigationStack` used (not deprecated `NavigationView`)
73
+ - [ ] Tab bar uses `TabView` with `.tabItem { Label("Name", systemImage: "icon") }`
74
+ - [ ] Sheets dismissed via `@Environment(\.dismiss) var dismiss`
75
+ - [ ] Back navigation is automatic — no custom back buttons unless design requires
76
+ - [ ] Deep links handled if the app supports URL schemes
77
+
78
+ ## Performance
79
+
80
+ - [ ] No `print()` statements in production code
81
+ - [ ] `LazyVStack` / `LazyVGrid` for lists of 20+ items
82
+ - [ ] `AsyncImage` for remote images — no manual URLSession in views
83
+ - [ ] `@StateObject` used when the view owns the model (not `@ObservedObject`)
@@ -0,0 +1,131 @@
1
+ // StitchComponentView.swift
2
+ // Generated from Stitch design via stitch-swiftui-components skill.
3
+ // Replace "StitchComponent" with the actual view name throughout.
4
+
5
+ import SwiftUI
6
+
7
+ // MARK: - View
8
+
9
+ /// StitchComponent — [describe purpose in one sentence]
10
+ ///
11
+ /// Usage:
12
+ /// ```swift
13
+ /// StitchComponentView(title: "Hello", description: "World")
14
+ /// ```
15
+ struct StitchComponentView: View {
16
+
17
+ // MARK: - Properties (props equivalent)
18
+
19
+ /// Primary heading text
20
+ let title: String
21
+
22
+ /// Supporting description — optional
23
+ var description: String = ""
24
+
25
+ /// Callback for primary action — nil hides the action button
26
+ var onAction: (() -> Void)? = nil
27
+
28
+ // MARK: - Environment
29
+
30
+ /// Automatically switches between light and dark theme tokens
31
+ @Environment(\.colorScheme) private var colorScheme
32
+
33
+ /// Resolved theme tokens for current color scheme
34
+ private var theme: ThemeTokens {
35
+ colorScheme == .dark ? .dark : .light
36
+ }
37
+
38
+ /// Respects user's Reduce Motion accessibility setting
39
+ @Environment(\.accessibilityReduceMotion) private var reduceMotion
40
+
41
+ // MARK: - State
42
+
43
+ @State private var isPressed = false
44
+
45
+ // MARK: - Body
46
+
47
+ var body: some View {
48
+ VStack(alignment: .leading, spacing: 8) {
49
+
50
+ // Title
51
+ Text(title)
52
+ .font(.headline)
53
+ .foregroundStyle(theme.text)
54
+ .lineLimit(nil) // Allow multiline
55
+
56
+ // Description — only render when non-empty
57
+ if !description.isEmpty {
58
+ Text(description)
59
+ .font(.subheadline)
60
+ .foregroundStyle(theme.textMuted)
61
+ .lineLimit(3)
62
+ }
63
+
64
+ // Action button — only render when provided
65
+ if let action = onAction {
66
+ Button(action: action) {
67
+ Text("Action")
68
+ .font(.subheadline)
69
+ .fontWeight(.semibold)
70
+ .padding(.horizontal, 16)
71
+ .padding(.vertical, 8)
72
+ .background(theme.primary)
73
+ .foregroundStyle(theme.primaryFg)
74
+ .clipShape(Capsule())
75
+ // Press feedback (respects reduced motion)
76
+ .scaleEffect(isPressed ? 0.96 : 1.0)
77
+ .animation(
78
+ reduceMotion ? .none : .spring(response: 0.2, dampingFraction: 0.6),
79
+ value: isPressed
80
+ )
81
+ }
82
+ .simultaneousGesture(
83
+ DragGesture(minimumDistance: 0)
84
+ .onChanged { _ in isPressed = true }
85
+ .onEnded { _ in isPressed = false }
86
+ )
87
+ // Accessibility — button is labeled by its Text child automatically
88
+ .accessibilityHint("Activates the primary action")
89
+ }
90
+ }
91
+ .padding(16)
92
+ .frame(maxWidth: .infinity, alignment: .leading)
93
+ .frame(minHeight: 44) // Apple HIG minimum touch target
94
+ .background(theme.surface)
95
+ .clipShape(RoundedRectangle(cornerRadius: 12))
96
+ .overlay(
97
+ RoundedRectangle(cornerRadius: 12)
98
+ .stroke(theme.border, lineWidth: 1)
99
+ )
100
+ }
101
+ }
102
+
103
+ // MARK: - Preview
104
+
105
+ #Preview("Light Mode") {
106
+ VStack(spacing: 16) {
107
+ StitchComponentView(
108
+ title: "Card Title",
109
+ description: "Supporting description text that can span multiple lines."
110
+ )
111
+ StitchComponentView(
112
+ title: "With Action",
113
+ description: "This card has a primary action.",
114
+ onAction: { print("Action tapped") }
115
+ )
116
+ StitchComponentView(title: "Title Only")
117
+ }
118
+ .padding()
119
+ }
120
+
121
+ #Preview("Dark Mode") {
122
+ VStack(spacing: 16) {
123
+ StitchComponentView(
124
+ title: "Dark Card",
125
+ description: "Preview in dark mode.",
126
+ onAction: { }
127
+ )
128
+ }
129
+ .padding()
130
+ .preferredColorScheme(.dark)
131
+ }
@@ -0,0 +1,155 @@
1
+ # HTML/CSS → SwiftUI Layout Mapping Reference
2
+
3
+ Quick lookup when converting Stitch HTML to SwiftUI.
4
+
5
+ ---
6
+
7
+ ## Flex containers
8
+
9
+ | CSS | SwiftUI |
10
+ |-----|---------|
11
+ | `flex-col` (default) | `VStack(alignment: .leading, spacing: 16) { }` |
12
+ | `flex-col items-center` | `VStack(alignment: .center, spacing: 16) { }` |
13
+ | `flex-col items-end` | `VStack(alignment: .trailing, spacing: 16) { }` |
14
+ | `flex-row` | `HStack(alignment: .center, spacing: 12) { }` |
15
+ | `flex-row items-start` | `HStack(alignment: .top, spacing: 12) { }` |
16
+ | `flex-row justify-between` | `HStack { content; Spacer(); content }` |
17
+ | `flex-row justify-around` | `HStack { Spacer(); content; Spacer(); content; Spacer() }` |
18
+ | Absolute overlay | `ZStack(alignment: .topLeading) { base; overlay }` |
19
+
20
+ ---
21
+
22
+ ## Spacing
23
+
24
+ | CSS | SwiftUI |
25
+ |-----|---------|
26
+ | `gap-1` (4px) | `spacing: 4` in VStack/HStack |
27
+ | `gap-2` (8px) | `spacing: 8` |
28
+ | `gap-3` (12px) | `spacing: 12` |
29
+ | `gap-4` (16px) | `spacing: 16` |
30
+ | `gap-6` (24px) | `spacing: 24` |
31
+ | `p-4` (16px all) | `.padding(16)` |
32
+ | `px-4 py-2` | `.padding(.horizontal, 16).padding(.vertical, 8)` |
33
+ | `pt-4` | `.padding(.top, 16)` |
34
+ | `mx-auto` (center) | `.frame(maxWidth: .infinity)` + center alignment |
35
+ | `mb-4` | use `spacing` in parent VStack instead |
36
+
37
+ ---
38
+
39
+ ## Sizing
40
+
41
+ | CSS | SwiftUI |
42
+ |-----|---------|
43
+ | `w-full` | `.frame(maxWidth: .infinity)` |
44
+ | `h-full` | `.frame(maxHeight: .infinity)` |
45
+ | `w-12` (48px) | `.frame(width: 48)` |
46
+ | `h-12` (48px) | `.frame(height: 48)` |
47
+ | `w-1/2` | `.frame(maxWidth: .infinity)` on each child in HStack |
48
+ | `min-h-[44px]` (touch target) | `.frame(minHeight: 44)` |
49
+
50
+ ---
51
+
52
+ ## Typography
53
+
54
+ | CSS | SwiftUI |
55
+ |-----|---------|
56
+ | `text-xs` (12px) | `.font(.caption2)` |
57
+ | `text-sm` (14px) | `.font(.caption)` or `.font(.subheadline)` |
58
+ | `text-base` (16px) | `.font(.body)` |
59
+ | `text-lg` (18px) | `.font(.callout)` |
60
+ | `text-xl` (20px) | `.font(.title3)` |
61
+ | `text-2xl` (24px) | `.font(.title2)` |
62
+ | `text-3xl` (30px) | `.font(.title)` |
63
+ | `text-4xl` (36px) | `.font(.largeTitle)` |
64
+ | `font-medium` | `.fontWeight(.medium)` |
65
+ | `font-semibold` | `.fontWeight(.semibold)` |
66
+ | `font-bold` | `.fontWeight(.bold)` |
67
+ | `text-muted` | `.foregroundStyle(.secondary)` |
68
+ | `truncate` | `.lineLimit(1)` |
69
+ | `line-clamp-2` | `.lineLimit(2)` |
70
+ | No clamp | `.lineLimit(nil)` |
71
+
72
+ ---
73
+
74
+ ## Colors & backgrounds
75
+
76
+ | CSS | SwiftUI |
77
+ |-----|---------|
78
+ | `bg-[var(--color-surface)]` | `.background(theme.surface)` |
79
+ | `bg-primary` | `.background(theme.primary)` |
80
+ | `text-muted` | `.foregroundStyle(theme.textMuted)` |
81
+ | `border border-[var(--color-border)]` | `.overlay(RoundedRectangle(...).stroke(theme.border))` |
82
+ | `opacity-50` | `.opacity(0.5)` |
83
+ | `shadow-md` | `.shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 4)` |
84
+
85
+ ---
86
+
87
+ ## Border radius
88
+
89
+ | CSS | SwiftUI |
90
+ |-----|---------|
91
+ | `rounded-sm` (4px) | `.clipShape(RoundedRectangle(cornerRadius: 4))` |
92
+ | `rounded-md` (8px) | `.clipShape(RoundedRectangle(cornerRadius: 8))` |
93
+ | `rounded-lg` (12px) | `.clipShape(RoundedRectangle(cornerRadius: 12))` |
94
+ | `rounded-xl` (16px) | `.clipShape(RoundedRectangle(cornerRadius: 16))` |
95
+ | `rounded-full` | `.clipShape(Capsule())` or `.clipShape(Circle())` |
96
+
97
+ > **Note:** Use `.clipShape` over deprecated `.cornerRadius` modifier in iOS 17+.
98
+
99
+ ---
100
+
101
+ ## Images
102
+
103
+ | CSS | SwiftUI |
104
+ |-----|---------|
105
+ | `<img src="https://...">` | `AsyncImage(url: URL(string: "https://..."))` |
106
+ | `<img src="./local.png">` | `Image("local")` (add to Assets.xcassets) |
107
+ | `object-fit: cover` | `.scaledToFill()` + `.clipped()` |
108
+ | `object-fit: contain` | `.scaledToFit()` |
109
+ | `aspect-ratio: 16/9` | `.aspectRatio(16/9, contentMode: .fill)` |
110
+ | Circle avatar | `AsyncImage(...).clipShape(Circle())` |
111
+
112
+ ---
113
+
114
+ ## Interactive elements
115
+
116
+ | CSS | SwiftUI |
117
+ |-----|---------|
118
+ | Primary `<button>` | `Button("Label") { }.buttonStyle(.borderedProminent).tint(theme.primary)` |
119
+ | Secondary button | `Button("Label") { }.buttonStyle(.bordered)` |
120
+ | Ghost/text button | `Button("Label") { }.buttonStyle(.plain)` |
121
+ | Destructive button | `Button("Delete") { }.tint(.red)` |
122
+ | Icon-only button | `Button { action() } label: { Image(systemName: "star") }` |
123
+ | `<input type="text">` | `TextField("Placeholder", text: $text)` |
124
+ | `<input type="password">` | `SecureField("Password", text: $password)` |
125
+ | `<input type="search">` | `TextField("Search", text: $query).searchable(text: $query)` |
126
+ | Toggle/checkbox | `Toggle("Label", isOn: $isOn)` |
127
+ | Slider | `Slider(value: $value, in: 0...100)` |
128
+ | Stepper | `Stepper("Count: \(count)", value: $count, in: 0...10)` |
129
+
130
+ ---
131
+
132
+ ## Scroll and lists
133
+
134
+ | CSS | SwiftUI |
135
+ |-----|---------|
136
+ | `overflow-y: scroll` | `ScrollView { VStack { ... } }` |
137
+ | `overflow-x: scroll` (horizontal) | `ScrollView(.horizontal) { HStack { ... } }` |
138
+ | `overflow: hidden` | `.clipped()` |
139
+ | Long list (performance) | `List { ForEach(items) { ... } }` or `LazyVStack` inside `ScrollView` |
140
+ | Grid | `LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())]) { ... }` |
141
+ | Horizontal card scroll | `ScrollView(.horizontal, showsIndicators: false) { HStack(spacing: 16) { ... } }` |
142
+
143
+ ---
144
+
145
+ ## Navigation patterns
146
+
147
+ | Pattern | SwiftUI |
148
+ |---------|---------|
149
+ | Bottom tab bar | `TabView { View1().tabItem { Label("Home", systemImage: "house") } }` |
150
+ | Push navigation | `NavigationStack { ... NavigationLink("Go", destination: DetailView()) }` |
151
+ | Modal sheet | `.sheet(isPresented: $show) { ModalView() }` |
152
+ | Full screen | `.fullScreenCover(isPresented: $show) { FullView() }` |
153
+ | Dismiss sheet/nav | `@Environment(\.dismiss) var dismiss; dismiss()` |
154
+ | Alert | `.alert("Title", isPresented: $show) { Button("OK") { } }` |
155
+ | Action sheet | `.confirmationDialog("Choose", isPresented: $show) { ... }` |
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env bash
2
+ # fetch-stitch.sh
3
+ # Reliably downloads Stitch HTML from Google Cloud Storage URLs.
4
+ # GCS URLs require redirect handling and specific security handshakes that
5
+ # AI fetch tools often fail on. This script handles both.
6
+ #
7
+ # Usage:
8
+ # bash scripts/fetch-stitch.sh "<url>" "<output-path>"
9
+ #
10
+ # Example:
11
+ # bash scripts/fetch-stitch.sh "$htmlCode_downloadUrl" "temp/source.html"
12
+
13
+ set -euo pipefail
14
+
15
+ URL="${1:?Usage: fetch-stitch.sh <url> <output-path>}"
16
+ OUTPUT="${2:?Usage: fetch-stitch.sh <url> <output-path>}"
17
+
18
+ # Create output directory if it doesn't exist
19
+ mkdir -p "$(dirname "$OUTPUT")"
20
+
21
+ # Use curl with:
22
+ # -L : follow redirects (GCS uses multiple redirect hops)
23
+ # -A : set User-Agent to avoid bot blocking
24
+ # --compressed : handle gzip responses
25
+ # --retry 3 : retry on transient failures
26
+ # --retry-delay 1 : wait 1s between retries
27
+ # --max-time 30 : don't hang forever
28
+ curl -L \
29
+ -A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" \
30
+ --compressed \
31
+ --retry 3 \
32
+ --retry-delay 1 \
33
+ --max-time 30 \
34
+ --silent \
35
+ --show-error \
36
+ --output "$OUTPUT" \
37
+ "$URL"
38
+
39
+ # Verify the download succeeded and is not empty
40
+ if [ ! -s "$OUTPUT" ]; then
41
+ echo "Error: Downloaded file is empty. URL may be expired or invalid." >&2
42
+ exit 1
43
+ fi
44
+
45
+ echo "Downloaded to: $OUTPUT ($(wc -c < "$OUTPUT") bytes)"
@@ -0,0 +1,124 @@
1
+ ---
2
+ name: stitch-ued-guide
3
+ description: Visual vocabulary, design terminology, and prompt engineering strategy for Stitch. Reference this when you need layout pattern names, aesthetic style terms, color structure formulas, or device guidelines.
4
+ allowed-tools: []
5
+ ---
6
+
7
+ # Stitch UED Guide
8
+
9
+ This is a reference guide, not an action skill. Use it when:
10
+ - You need specific design terminology for a Stitch prompt (masonry, glassmorphism, split-screen)
11
+ - You're unsure how to describe a layout pattern or visual style
12
+ - You want to apply color + theme structure consistently
13
+ - You need to know device-specific constraints for prompt writing
14
+
15
+ ## Prompt engineering strategy
16
+
17
+ The most effective Stitch prompts follow this 4-part structure:
18
+
19
+ ```
20
+ [Context & Style] + [Layout Structure] + [Component Details] + [Content & Data]
21
+ ```
22
+
23
+ **Context & Style:**
24
+ > "Mobile fitness app for gym-goers. Dark mode with neon green accents. Cyberpunk aesthetic. Rounded corners."
25
+
26
+ **Layout Structure:**
27
+ > "Bottom navigation bar (Home, Workout, Progress, Profile). Scrollable main feed. Sticky top bar with greeting."
28
+
29
+ **Component Details:**
30
+ > "Workout cards with gradient border, thumbnail, title, duration badge, and 'Start' pill button."
31
+
32
+ **Content & Data:**
33
+ > "Sample data: 'Upper Body Blast' (45 min), 'Core Destroyer' (20 min), 'Morning Run' (30 min, completed today)."
34
+
35
+ ## Stitch model selection
36
+
37
+ | Model | When to use |
38
+ |-------|-------------|
39
+ | `GEMINI_3_PRO` | High-fidelity designs, complex layouts, when quality matters — **recommended default** |
40
+ | `GEMINI_3_FLASH` | Fast iteration, wireframes, rapid exploration, when speed matters |
41
+
42
+ ## Layout patterns
43
+
44
+ ### Mobile patterns
45
+ - **Vertical scroll feed** — infinite scroll of content cards, sticky header, bottom nav
46
+ - **Tab navigation** — segmented control or tab bar, content switches inline
47
+ - **Bottom sheet** — slide-up panel for secondary content or actions
48
+ - **Full-screen form** — single-column, large touch targets, sticky submit
49
+ - **Detail → action** — hero content at top, description below, sticky CTA at bottom
50
+
51
+ ### Desktop patterns
52
+ - **Left sidebar + main** — persistent side nav (200-280px), main content area, top bar
53
+ - **Top nav + content** — horizontal navigation bar, sectioned main content below
54
+ - **Split screen** — two equal halves (form/preview, signup/product screenshot)
55
+ - **Dashboard grid** — KPI strip, charts, tables, widgets in responsive grid
56
+ - **Landing page** — full-width hero, feature sections, pricing, footer CTA
57
+
58
+ ### Universal patterns
59
+ - **Masonry grid** — variable-height cards, Pinterest-style layout
60
+ - **Bento grid** — asymmetric boxes of varying sizes, each containing different content
61
+ - **Hero section** — full-width/height with background image, headline, CTA
62
+ - **Card grid** — uniform cards in responsive column grid
63
+
64
+ ## Visual styles
65
+
66
+ | Style | Description | Use for |
67
+ |-------|-------------|---------|
68
+ | **Flat** | No shadows, bold colors, simple shapes | Mobile apps, illustrations |
69
+ | **Material** | Cards with elevation, clear hierarchy, ripple effects | Android-style apps |
70
+ | **Neumorphism** | Extruded elements on same-color bg, soft shadows | Luxury, subtle UIs |
71
+ | **Glassmorphism** | Frosted glass effect, blur + transparency + border | Modern SaaS, overlays |
72
+ | **Brutalism** | Raw, high-contrast, purposefully rough, grid-breaking | Editorial, bold brands |
73
+ | **Minimalism** | Maximum whitespace, single accent color, typographic focus | Portfolios, landing pages |
74
+ | **Cyberpunk** | Dark bg, neon accents, glitch elements, monospace fonts | Gaming, tech, dark mode |
75
+
76
+ ## Color structure formula
77
+
78
+ For consistent, professional palettes in prompts:
79
+
80
+ ```
81
+ [Domain/mood description] + [Background hex] + [Primary hex] + [Secondary hex] + [Text hex] + [Aesthetic mood]
82
+ ```
83
+
84
+ **Example:**
85
+ > "Modern SaaS productivity app. Slate-50 (#F8FAFC) background. Indigo (#6366F1) primary. Violet (#8B5CF6) secondary. Zinc-900 (#18181B) text. Clean, structured, professional."
86
+
87
+ **Dark mode example:**
88
+ > "Premium dark dashboard. Zinc-900 (#18181B) background. Indigo-400 (#818CF8) primary on dark. Zinc-800 (#27272A) card surface. Zinc-100 (#F4F4F5) text. Focused, high-contrast, developer-friendly."
89
+
90
+ ## Device guidelines
91
+
92
+ | Device | Dimensions | Key constraints |
93
+ |--------|-----------|-----------------|
94
+ | **MOBILE** | ~375px wide | Bottom navigation, thumb-friendly tap targets (44px min), single-column layouts, larger type |
95
+ | **DESKTOP** | ~1440px wide | Multi-column layouts, sidebar navigation, dense data tables, hover interactions |
96
+ | **TABLET** | ~768-1024px | Hybrid: 2-column grids, collapsible sidebar, touch-friendly but more space |
97
+ | **AGNOSTIC** | Fluid | Responsive/fluid layout — not tied to a specific device, adapts to viewport |
98
+
99
+ ## Accessibility in prompts
100
+
101
+ Include these phrases in prompts to guide Stitch toward accessible output:
102
+ - "High contrast text, WCAG AA compliant colors"
103
+ - "Touch-friendly tap targets, minimum 44px height"
104
+ - "Clear visual hierarchy, strong heading sizes"
105
+ - "Sufficient color contrast between text and background"
106
+
107
+ ## Quick reference — UI component names for Stitch prompts
108
+
109
+ Use these precise names (vague descriptions produce worse results):
110
+
111
+ - "Floating action button (FAB)" not "button in corner"
112
+ - "Segmented control" not "toggle group"
113
+ - "Bottom sheet" not "popup from bottom"
114
+ - "Skeleton loader" not "loading placeholder"
115
+ - "Snackbar" not "notification at bottom"
116
+ - "Breadcrumb trail" not "navigation path"
117
+ - "Stepper / wizard" not "multi-step form indicator"
118
+ - "Data table with sortable columns" not "list of data"
119
+ - "Autocomplete input" not "search with suggestions"
120
+
121
+ ## Related skills
122
+
123
+ - `stitch-ui-design-spec-generator` — produces the structured JSON this guide helps you describe
124
+ - `stitch-ui-prompt-architect` — applies this vocabulary to build final Stitch prompts
@@ -0,0 +1,115 @@
1
+ ---
2
+ name: stitch-ui-design-spec-generator
3
+ description: Translates a user request or PRD document into a structured Design Spec JSON — theme, color, typography, density, and device type. Call this before building Stitch generation prompts.
4
+ allowed-tools: []
5
+ ---
6
+
7
+ # Stitch Design Spec Generator
8
+
9
+ You are a Creative Director. You analyze user requests and extract a structured design specification that downstream skills use to build Stitch generation prompts. Your output is a JSON object — never freeform text.
10
+
11
+ ## When to use this skill
12
+
13
+ Call this skill internally (no user-facing output needed) before:
14
+ - Building a Stitch generation prompt via `stitch-ui-prompt-architect`
15
+ - Starting a new Stitch project
16
+ - The orchestrator passes control to you
17
+
18
+ You can also use it directly when a user asks: "What design spec would work for X?" or "Help me define the visual style."
19
+
20
+ ## Input types
21
+
22
+ **Type A — One-shot natural language request:**
23
+ > "A cyberpunk login page for a gaming platform"
24
+
25
+ **Type B — PRD document or summary:**
26
+ > Provide a file path or paste PRD content. Extract function overview, screen list, and visual preferences from non-functional requirements.
27
+
28
+ ## Logic rules — apply in order
29
+
30
+ ### 1. Analyze tone → derive style keywords and colors
31
+
32
+ | Domain / Tone | Primary Color range | Style Keywords |
33
+ |---------------|--------------------|-|
34
+ | Corporate / Medical / Finance | Blues, greys (#2563EB, #475569) | Clean, Professional, Data-dense, Trustworthy |
35
+ | Creative / Gaming / Cyberpunk | Neons, deep darks (#00FF88, #1a1a1a) | Dynamic, High-contrast, Edgy, Immersive |
36
+ | Lifestyle / Food / Social | Warm oranges, pinks (#E85D04, #EC4899) | Friendly, Warm, Playful, Inviting |
37
+ | Productivity / SaaS / Dashboard | Neutral blues, purples (#6366F1, #0EA5E9) | Focused, Structured, Efficient, Minimal |
38
+ | Luxury / Fashion | Blacks, golds (#18181B, #D4AF37) | Elegant, Exclusive, Premium, Refined |
39
+ | Health / Wellness | Soft greens, teals (#10B981, #0D9488) | Calm, Natural, Clean, Reassuring |
40
+
41
+ ### 2. Determine device type
42
+
43
+ | Signal in request | → deviceType |
44
+ |---|---|
45
+ | "dashboard", "admin", "web app", "landing page", "desktop" | DESKTOP |
46
+ | "mobile app", "iOS", "Android", "phone", "app" | MOBILE |
47
+ | "tablet", "iPad" | TABLET |
48
+ | "responsive", "fluid", "any device" | AGNOSTIC |
49
+ | No clear signal → default | MOBILE |
50
+
51
+ ### 3. Determine design mode
52
+
53
+ | Signal | → designMode |
54
+ |---|---|
55
+ | "wireframe", "sketch", "low-fi", "draft" | WIREFRAME |
56
+ | All other cases | HIGH_FIDELITY |
57
+
58
+ ### 4. Determine roundness
59
+
60
+ | Style keywords contain | → roundness |
61
+ |---|---|
62
+ | "sharp", "brutalist", "corporate", "enterprise" | Low |
63
+ | "modern", "clean", "professional" | Medium |
64
+ | "friendly", "playful", "card", "soft", "rounded" | High |
65
+
66
+ ### 5. Determine density
67
+
68
+ | Context | → density |
69
+ |---|---|
70
+ | Data tables, dashboards, admin panels | COMPACT |
71
+ | Mobile apps, social, consumer | COMFORTABLE |
72
+ | Marketing pages, landing pages, portfolios | SPACIOUS |
73
+
74
+ ## Output format
75
+
76
+ Always output **exactly this JSON structure** — no extra fields, no explanations:
77
+
78
+ ```json
79
+ {
80
+ "theme": "DARK" | "LIGHT",
81
+ "primaryColor": "#HEXCODE",
82
+ "font": "Font Name",
83
+ "roundness": "High" | "Medium" | "Low",
84
+ "density": "COMPACT" | "COMFORTABLE" | "SPACIOUS",
85
+ "designMode": "WIREFRAME" | "HIGH_FIDELITY",
86
+ "styleKeywords": ["Keyword1", "Keyword2", "Keyword3"],
87
+ "deviceType": "MOBILE" | "TABLET" | "DESKTOP" | "AGNOSTIC"
88
+ }
89
+ ```
90
+
91
+ **Font selection guide — use Stitch enum names exactly:**
92
+
93
+ | Use case | Font (Stitch enum) |
94
+ |----------|--------------------|
95
+ | Corporate / SaaS / Dashboard | `INTER`, `DM_SANS`, `IBM_PLEX_SANS` |
96
+ | Clean modern / startup | `GEIST`, `MANROPE`, `PLUS_JAKARTA_SANS`, `WORK_SANS` |
97
+ | Editorial / expressive | `SPACE_GROTESK`, `EPILOGUE`, `SORA`, `RUBIK` |
98
+ | Friendly / consumer app | `NUNITO_SANS`, `LEXEND`, `BE_VIETNAM_PRO` |
99
+ | Luxury / serif | `EB_GARAMOND`, `LITERATA`, `SOURCE_SERIF_FOUR`, `LIBRE_CASLON_TEXT` |
100
+ | Dense data / admin | `SOURCE_SANS_THREE`, `PUBLIC_SANS`, `ARIMO` |
101
+ | News / reading | `NEWSREADER`, `DOMINE`, `NOTO_SERIF` |
102
+
103
+ Full font list: `BE_VIETNAM_PRO`, `EPILOGUE`, `INTER`, `LEXEND`, `MANROPE`, `NEWSREADER`,
104
+ `NOTO_SERIF`, `PLUS_JAKARTA_SANS`, `PUBLIC_SANS`, `SPACE_GROTESK`, `SPLINE_SANS`,
105
+ `WORK_SANS`, `DOMINE`, `LIBRE_CASLON_TEXT`, `EB_GARAMOND`, `LITERATA`, `SOURCE_SERIF_FOUR`,
106
+ `MONTSERRAT`, `METROPOLIS`, `SOURCE_SANS_THREE`, `NUNITO_SANS`, `ARIMO`, `HANKEN_GROTESK`,
107
+ `RUBIK`, `GEIST`, `DM_SANS`, `IBM_PLEX_SANS`, `SORA`
108
+
109
+ ## Integration
110
+
111
+ After generating the spec JSON, the next step is always `stitch-ui-prompt-architect`, which merges the spec with the user's request to produce a `[Context] [Layout] [Components]` Stitch generation prompt.
112
+
113
+ ## References
114
+
115
+ - `examples/usage.md` — Three worked examples (cyberpunk login, medical dashboard, food app)