buildanything 1.7.0 → 1.8.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 (222) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +55 -0
  4. package/README.md +71 -61
  5. package/agents/ios-app-review-guardian.md +49 -0
  6. package/agents/ios-foundation-models-specialist.md +46 -0
  7. package/agents/ios-storekit-specialist.md +52 -0
  8. package/agents/ios-swift-architect.md +102 -0
  9. package/agents/ios-swift-search.md +130 -0
  10. package/agents/ios-swift-ui-design.md +104 -0
  11. package/commands/build.md +80 -176
  12. package/commands/fix.md +65 -0
  13. package/commands/setup.md +73 -0
  14. package/commands/ux-review.md +63 -0
  15. package/commands/verify.md +72 -0
  16. package/hooks/session-start +18 -1
  17. package/package.json +5 -2
  18. package/protocols/brainstorm.md +99 -0
  19. package/protocols/build-fix.md +52 -0
  20. package/protocols/cleanup.md +54 -0
  21. package/protocols/design.md +269 -0
  22. package/protocols/eval-harness.md +61 -0
  23. package/protocols/fake-data-detector.md +64 -0
  24. package/protocols/ios-context.md +235 -0
  25. package/protocols/ios-frameworks-map.md +323 -0
  26. package/protocols/ios-phase-branches.md +162 -0
  27. package/protocols/ios-preflight.md +27 -0
  28. package/protocols/metric-loop.md +93 -0
  29. package/protocols/planning.md +87 -0
  30. package/protocols/smoke-test.md +110 -0
  31. package/protocols/verify.md +67 -0
  32. package/protocols/web-phase-branches.md +201 -0
  33. package/skills/ios/_VENDORED.md +60 -0
  34. package/skills/ios/activitykit/LICENSE +131 -0
  35. package/skills/ios/activitykit/SKILL.md +505 -0
  36. package/skills/ios/activitykit/references/activitykit-patterns.md +868 -0
  37. package/skills/ios/app-intents/LICENSE +131 -0
  38. package/skills/ios/app-intents/SKILL.md +494 -0
  39. package/skills/ios/app-intents/references/appintents-advanced.md +1076 -0
  40. package/skills/ios/apple-on-device-ai/LICENSE +131 -0
  41. package/skills/ios/apple-on-device-ai/SKILL.md +505 -0
  42. package/skills/ios/apple-on-device-ai/references/coreml-conversion.md +425 -0
  43. package/skills/ios/apple-on-device-ai/references/coreml-optimization.md +344 -0
  44. package/skills/ios/apple-on-device-ai/references/foundation-models.md +508 -0
  45. package/skills/ios/apple-on-device-ai/references/mlx-swift.md +285 -0
  46. package/skills/ios/ios-26-platform/SKILL.md +53 -0
  47. package/skills/ios/ios-26-platform/references/automatic-adoption.md +161 -0
  48. package/skills/ios/ios-26-platform/references/backward-compat.md +238 -0
  49. package/skills/ios/ios-26-platform/references/liquid-glass.md +255 -0
  50. package/skills/ios/ios-26-platform/references/swiftui-apis.md +277 -0
  51. package/skills/ios/ios-26-platform/references/toolbar-navigation.md +250 -0
  52. package/skills/ios/ios-bootstrap/SKILL.md +98 -0
  53. package/skills/ios/ios-bootstrap/references/apple-docs-mcp-config.md +28 -0
  54. package/skills/ios/ios-bootstrap/references/new-project-dialog.md +41 -0
  55. package/skills/ios/ios-bootstrap/references/xcode-mcp-config.md +29 -0
  56. package/skills/ios/ios-debugger-agent/LICENSE +21 -0
  57. package/skills/ios/ios-debugger-agent/SKILL.md +58 -0
  58. package/skills/ios/ios-debugger-agent/agents/openai.yaml +4 -0
  59. package/skills/ios/ios-entitlements-generator/SKILL.md +47 -0
  60. package/skills/ios/ios-hig/SKILL.md +41 -0
  61. package/skills/ios/ios-hig/references/accessibility.md +81 -0
  62. package/skills/ios/ios-hig/references/content.md +142 -0
  63. package/skills/ios/ios-hig/references/feedback.md +123 -0
  64. package/skills/ios/ios-hig/references/interaction.md +199 -0
  65. package/skills/ios/ios-hig/references/performance-platform.md +129 -0
  66. package/skills/ios/ios-hig/references/privacy-permissions.md +181 -0
  67. package/skills/ios/ios-hig/references/visual-design.md +84 -0
  68. package/skills/ios/ios-info-plist-hardening/SKILL.md +130 -0
  69. package/skills/ios/ios-maestro-flow-author/SKILL.md +68 -0
  70. package/skills/ios/ios-maestro-flow-author/references/input-and-scroll.yaml +17 -0
  71. package/skills/ios/ios-maestro-flow-author/references/modal-and-dismiss.yaml +14 -0
  72. package/skills/ios/ios-maestro-flow-author/references/onboarding-flow.yaml +16 -0
  73. package/skills/ios/ios-maestro-flow-author/references/tab-navigation.yaml +13 -0
  74. package/skills/ios/ios-maestro-flow-author/references/tap-and-assert.yaml +9 -0
  75. package/skills/ios/swift-accessibility/LICENSE +21 -0
  76. package/skills/ios/swift-accessibility/SKILL.md +371 -0
  77. package/skills/ios/swift-accessibility/examples/before-after-appkit.md +446 -0
  78. package/skills/ios/swift-accessibility/examples/before-after-swiftui.md +441 -0
  79. package/skills/ios/swift-accessibility/examples/before-after-uikit.md +464 -0
  80. package/skills/ios/swift-accessibility/references/assistive-access.md +441 -0
  81. package/skills/ios/swift-accessibility/references/display-settings.md +491 -0
  82. package/skills/ios/swift-accessibility/references/dynamic-type.md +420 -0
  83. package/skills/ios/swift-accessibility/references/media-accessibility.md +421 -0
  84. package/skills/ios/swift-accessibility/references/motor-input.md +393 -0
  85. package/skills/ios/swift-accessibility/references/nutrition-labels.md +362 -0
  86. package/skills/ios/swift-accessibility/references/platform-specifics.md +515 -0
  87. package/skills/ios/swift-accessibility/references/semantic-structure.md +585 -0
  88. package/skills/ios/swift-accessibility/references/testing-auditing.md +507 -0
  89. package/skills/ios/swift-accessibility/references/voice-control.md +317 -0
  90. package/skills/ios/swift-accessibility/references/voiceover-swiftui.md +584 -0
  91. package/skills/ios/swift-accessibility/references/voiceover-uikit.md +519 -0
  92. package/skills/ios/swift-accessibility/references/wcag-mapping.md +167 -0
  93. package/skills/ios/swift-accessibility/resources/audit-template.swift +128 -0
  94. package/skills/ios/swift-accessibility/resources/qa-checklist.md +258 -0
  95. package/skills/ios/swift-concurrency/LICENSE +21 -0
  96. package/skills/ios/swift-concurrency/SKILL.md +171 -0
  97. package/skills/ios/swift-concurrency/references/_index.md +50 -0
  98. package/skills/ios/swift-concurrency/references/actors.md +660 -0
  99. package/skills/ios/swift-concurrency/references/async-algorithms.md +847 -0
  100. package/skills/ios/swift-concurrency/references/async-await-basics.md +266 -0
  101. package/skills/ios/swift-concurrency/references/async-sequences.md +710 -0
  102. package/skills/ios/swift-concurrency/references/core-data.md +560 -0
  103. package/skills/ios/swift-concurrency/references/glossary.md +135 -0
  104. package/skills/ios/swift-concurrency/references/linting.md +155 -0
  105. package/skills/ios/swift-concurrency/references/memory-management.md +569 -0
  106. package/skills/ios/swift-concurrency/references/migration.md +1104 -0
  107. package/skills/ios/swift-concurrency/references/performance.md +593 -0
  108. package/skills/ios/swift-concurrency/references/sendable.md +598 -0
  109. package/skills/ios/swift-concurrency/references/tasks.md +636 -0
  110. package/skills/ios/swift-concurrency/references/testing.md +592 -0
  111. package/skills/ios/swift-concurrency/references/threading.md +495 -0
  112. package/skills/ios/swift-security-expert/LICENSE +21 -0
  113. package/skills/ios/swift-security-expert/SKILL.md +470 -0
  114. package/skills/ios/swift-security-expert/references/biometric-authentication.md +565 -0
  115. package/skills/ios/swift-security-expert/references/certificate-trust.md +592 -0
  116. package/skills/ios/swift-security-expert/references/common-anti-patterns.md +690 -0
  117. package/skills/ios/swift-security-expert/references/compliance-owasp-mapping.md +537 -0
  118. package/skills/ios/swift-security-expert/references/credential-storage-patterns.md +721 -0
  119. package/skills/ios/swift-security-expert/references/cryptokit-public-key.md +505 -0
  120. package/skills/ios/swift-security-expert/references/cryptokit-symmetric.md +497 -0
  121. package/skills/ios/swift-security-expert/references/keychain-access-control.md +508 -0
  122. package/skills/ios/swift-security-expert/references/keychain-fundamentals.md +596 -0
  123. package/skills/ios/swift-security-expert/references/keychain-item-classes.md +476 -0
  124. package/skills/ios/swift-security-expert/references/keychain-sharing.md +458 -0
  125. package/skills/ios/swift-security-expert/references/migration-legacy-stores.md +727 -0
  126. package/skills/ios/swift-security-expert/references/secure-enclave.md +539 -0
  127. package/skills/ios/swift-security-expert/references/testing-security-code.md +781 -0
  128. package/skills/ios/swift-testing-expert/LICENSE +21 -0
  129. package/skills/ios/swift-testing-expert/SKILL.md +79 -0
  130. package/skills/ios/swift-testing-expert/references/_index.md +12 -0
  131. package/skills/ios/swift-testing-expert/references/async-testing-and-waiting.md +127 -0
  132. package/skills/ios/swift-testing-expert/references/expectations.md +145 -0
  133. package/skills/ios/swift-testing-expert/references/fundamentals.md +141 -0
  134. package/skills/ios/swift-testing-expert/references/migration-from-xctest.md +127 -0
  135. package/skills/ios/swift-testing-expert/references/parallelization-and-isolation.md +95 -0
  136. package/skills/ios/swift-testing-expert/references/parameterized-testing.md +284 -0
  137. package/skills/ios/swift-testing-expert/references/performance-and-best-practices.md +187 -0
  138. package/skills/ios/swift-testing-expert/references/traits-and-tags.md +114 -0
  139. package/skills/ios/swift-testing-expert/references/xcode-workflows.md +70 -0
  140. package/skills/ios/swiftdata-pro/LICENSE +21 -0
  141. package/skills/ios/swiftdata-pro/SKILL.md +102 -0
  142. package/skills/ios/swiftdata-pro/agents/openai.yaml +10 -0
  143. package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.png +0 -0
  144. package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.svg +29 -0
  145. package/skills/ios/swiftdata-pro/references/class-inheritance.md +104 -0
  146. package/skills/ios/swiftdata-pro/references/cloudkit.md +10 -0
  147. package/skills/ios/swiftdata-pro/references/core-rules.md +20 -0
  148. package/skills/ios/swiftdata-pro/references/indexing.md +27 -0
  149. package/skills/ios/swiftdata-pro/references/predicates.md +73 -0
  150. package/skills/ios/swiftui-design-principles/AGENTS.md +21 -0
  151. package/skills/ios/swiftui-design-principles/LICENSE +21 -0
  152. package/skills/ios/swiftui-design-principles/README.md +41 -0
  153. package/skills/ios/swiftui-design-principles/SKILL.md +605 -0
  154. package/skills/ios/swiftui-design-principles/metadata.json +10 -0
  155. package/skills/ios/swiftui-liquid-glass/LICENSE +21 -0
  156. package/skills/ios/swiftui-liquid-glass/SKILL.md +95 -0
  157. package/skills/ios/swiftui-liquid-glass/agents/openai.yaml +4 -0
  158. package/skills/ios/swiftui-liquid-glass/references/liquid-glass.md +280 -0
  159. package/skills/ios/swiftui-performance-audit/LICENSE +21 -0
  160. package/skills/ios/swiftui-performance-audit/SKILL.md +111 -0
  161. package/skills/ios/swiftui-performance-audit/agents/openai.yaml +4 -0
  162. package/skills/ios/swiftui-performance-audit/references/code-smells.md +150 -0
  163. package/skills/ios/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
  164. package/skills/ios/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
  165. package/skills/ios/swiftui-performance-audit/references/profiling-intake.md +44 -0
  166. package/skills/ios/swiftui-performance-audit/references/report-template.md +47 -0
  167. package/skills/ios/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
  168. package/skills/ios/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
  169. package/skills/ios/swiftui-pro/LICENSE +21 -0
  170. package/skills/ios/swiftui-pro/SKILL.md +108 -0
  171. package/skills/ios/swiftui-pro/agents/openai.yaml +10 -0
  172. package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.png +0 -0
  173. package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.svg +29 -0
  174. package/skills/ios/swiftui-pro/references/accessibility.md +13 -0
  175. package/skills/ios/swiftui-pro/references/api.md +39 -0
  176. package/skills/ios/swiftui-pro/references/data.md +43 -0
  177. package/skills/ios/swiftui-pro/references/design.md +31 -0
  178. package/skills/ios/swiftui-pro/references/hygiene.md +9 -0
  179. package/skills/ios/swiftui-pro/references/navigation.md +14 -0
  180. package/skills/ios/swiftui-pro/references/performance.md +46 -0
  181. package/skills/ios/swiftui-pro/references/swift.md +56 -0
  182. package/skills/ios/swiftui-pro/references/views.md +35 -0
  183. package/skills/ios/swiftui-ui-patterns/LICENSE +21 -0
  184. package/skills/ios/swiftui-ui-patterns/SKILL.md +100 -0
  185. package/skills/ios/swiftui-ui-patterns/agents/openai.yaml +4 -0
  186. package/skills/ios/swiftui-ui-patterns/references/app-wiring.md +201 -0
  187. package/skills/ios/swiftui-ui-patterns/references/async-state.md +96 -0
  188. package/skills/ios/swiftui-ui-patterns/references/components-index.md +50 -0
  189. package/skills/ios/swiftui-ui-patterns/references/controls.md +57 -0
  190. package/skills/ios/swiftui-ui-patterns/references/deeplinks.md +66 -0
  191. package/skills/ios/swiftui-ui-patterns/references/focus.md +90 -0
  192. package/skills/ios/swiftui-ui-patterns/references/form.md +97 -0
  193. package/skills/ios/swiftui-ui-patterns/references/grids.md +71 -0
  194. package/skills/ios/swiftui-ui-patterns/references/haptics.md +71 -0
  195. package/skills/ios/swiftui-ui-patterns/references/input-toolbar.md +51 -0
  196. package/skills/ios/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
  197. package/skills/ios/swiftui-ui-patterns/references/list.md +86 -0
  198. package/skills/ios/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
  199. package/skills/ios/swiftui-ui-patterns/references/macos-settings.md +71 -0
  200. package/skills/ios/swiftui-ui-patterns/references/matched-transitions.md +59 -0
  201. package/skills/ios/swiftui-ui-patterns/references/media.md +73 -0
  202. package/skills/ios/swiftui-ui-patterns/references/menu-bar.md +101 -0
  203. package/skills/ios/swiftui-ui-patterns/references/navigationstack.md +159 -0
  204. package/skills/ios/swiftui-ui-patterns/references/overlay.md +45 -0
  205. package/skills/ios/swiftui-ui-patterns/references/performance.md +62 -0
  206. package/skills/ios/swiftui-ui-patterns/references/previews.md +48 -0
  207. package/skills/ios/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
  208. package/skills/ios/swiftui-ui-patterns/references/scrollview.md +87 -0
  209. package/skills/ios/swiftui-ui-patterns/references/searchable.md +71 -0
  210. package/skills/ios/swiftui-ui-patterns/references/sheets.md +155 -0
  211. package/skills/ios/swiftui-ui-patterns/references/split-views.md +72 -0
  212. package/skills/ios/swiftui-ui-patterns/references/tabview.md +114 -0
  213. package/skills/ios/swiftui-ui-patterns/references/theming.md +71 -0
  214. package/skills/ios/swiftui-ui-patterns/references/title-menus.md +93 -0
  215. package/skills/ios/swiftui-ui-patterns/references/top-bar.md +49 -0
  216. package/skills/ios/swiftui-view-refactor/LICENSE +21 -0
  217. package/skills/ios/swiftui-view-refactor/SKILL.md +207 -0
  218. package/skills/ios/swiftui-view-refactor/agents/openai.yaml +4 -0
  219. package/skills/ios/swiftui-view-refactor/references/mv-patterns.md +161 -0
  220. package/skills/ios/widgetkit/LICENSE +131 -0
  221. package/skills/ios/widgetkit/SKILL.md +502 -0
  222. package/skills/ios/widgetkit/references/widgetkit-advanced.md +871 -0
@@ -0,0 +1,71 @@
1
+ # macOS Settings
2
+
3
+ ## Intent
4
+
5
+ Use this when building a macOS Settings window backed by SwiftUI's `Settings` scene.
6
+
7
+ ## Core patterns
8
+
9
+ - Declare the Settings scene in the `App` and compile it only for macOS.
10
+ - Keep settings content in a dedicated root view (`SettingsView`) and drive values with `@AppStorage`.
11
+ - Use `TabView` to group settings sections when you have more than one category.
12
+ - Use `Form` inside each tab to keep controls aligned and accessible.
13
+ - Use `OpenSettingsAction` or `SettingsLink` for in-app entry points to the Settings window.
14
+
15
+ ## Example: settings scene
16
+
17
+ ```swift
18
+ @main
19
+ struct MyApp: App {
20
+ var body: some Scene {
21
+ WindowGroup {
22
+ ContentView()
23
+ }
24
+ #if os(macOS)
25
+ Settings {
26
+ SettingsView()
27
+ }
28
+ #endif
29
+ }
30
+ }
31
+ ```
32
+
33
+ ## Example: tabbed settings view
34
+
35
+ ```swift
36
+ @MainActor
37
+ struct SettingsView: View {
38
+ @AppStorage("showPreviews") private var showPreviews = true
39
+ @AppStorage("fontSize") private var fontSize = 12.0
40
+
41
+ var body: some View {
42
+ TabView {
43
+ Form {
44
+ Toggle("Show Previews", isOn: $showPreviews)
45
+ Slider(value: $fontSize, in: 9...96) {
46
+ Text("Font Size (\(fontSize, specifier: "%.0f") pts)")
47
+ }
48
+ }
49
+ .tabItem { Label("General", systemImage: "gear") }
50
+
51
+ Form {
52
+ Toggle("Enable Advanced Mode", isOn: .constant(false))
53
+ }
54
+ .tabItem { Label("Advanced", systemImage: "star") }
55
+ }
56
+ .scenePadding()
57
+ .frame(maxWidth: 420, minHeight: 240)
58
+ }
59
+ }
60
+ ```
61
+
62
+ ## Skip navigation
63
+
64
+ - Avoid wrapping `SettingsView` in a `NavigationStack` unless you truly need deep push navigation.
65
+ - Prefer tabs or sections; Settings is already presented as a separate window and should feel flat.
66
+ - If you must show hierarchical settings, use a single `NavigationSplitView` with a sidebar list of categories.
67
+
68
+ ## Pitfalls
69
+
70
+ - Don’t reuse iOS-only settings layouts (full-screen stacks, toolbar-heavy flows).
71
+ - Avoid large custom view hierarchies inside `Form`; keep rows focused and accessible.
@@ -0,0 +1,59 @@
1
+ # Matched transitions
2
+
3
+ ## Intent
4
+
5
+ Use matched transitions to create smooth continuity between a source view (thumbnail, avatar) and a destination view (sheet, detail, viewer).
6
+
7
+ ## Core patterns
8
+
9
+ - Use a shared `Namespace` and a stable ID for the source.
10
+ - Use `matchedTransitionSource` + `navigationTransition(.zoom(...))` on iOS 26+.
11
+ - Use `matchedGeometryEffect` for in-place transitions within a view hierarchy.
12
+ - Keep IDs stable across view updates (avoid random UUIDs).
13
+
14
+ ## Example: media preview to full-screen viewer (iOS 26+)
15
+
16
+ ```swift
17
+ struct MediaPreview: View {
18
+ @Namespace private var namespace
19
+ @State private var selected: MediaAttachment?
20
+
21
+ var body: some View {
22
+ ThumbnailView()
23
+ .matchedTransitionSource(id: selected?.id ?? "", in: namespace)
24
+ .sheet(item: $selected) { item in
25
+ MediaViewer(item: item)
26
+ .navigationTransition(.zoom(sourceID: item.id, in: namespace))
27
+ }
28
+ }
29
+ }
30
+ ```
31
+
32
+ ## Example: matched geometry within a view
33
+
34
+ ```swift
35
+ struct ToggleBadge: View {
36
+ @Namespace private var space
37
+ @State private var isOn = false
38
+
39
+ var body: some View {
40
+ Button {
41
+ withAnimation(.spring) { isOn.toggle() }
42
+ } label: {
43
+ Image(systemName: isOn ? "eye" : "eye.slash")
44
+ .matchedGeometryEffect(id: "icon", in: space)
45
+ }
46
+ }
47
+ }
48
+ ```
49
+
50
+ ## Design choices to keep
51
+
52
+ - Prefer `matchedTransitionSource` for cross-screen transitions.
53
+ - Keep source and destination sizes reasonable to avoid jarring scale changes.
54
+ - Use `withAnimation` for state-driven transitions.
55
+
56
+ ## Pitfalls
57
+
58
+ - Don’t use unstable IDs; it breaks the transition.
59
+ - Avoid mismatched shapes (e.g., square to circle) unless the design expects it.
@@ -0,0 +1,73 @@
1
+ # Media (images, video, viewer)
2
+
3
+ ## Intent
4
+
5
+ Use consistent patterns for loading images, previewing media, and presenting a full-screen viewer.
6
+
7
+ ## Core patterns
8
+
9
+ - Use `LazyImage` (or `AsyncImage`) for remote images with loading states.
10
+ - Prefer a lightweight preview component for inline media.
11
+ - Use a shared viewer state (e.g., `QuickLook`) to present a full-screen media viewer.
12
+ - Use `openWindow` for desktop/visionOS and a sheet for iOS.
13
+
14
+ ## Example: inline media preview
15
+
16
+ ```swift
17
+ struct MediaPreviewRow: View {
18
+ @Environment(QuickLook.self) private var quickLook
19
+
20
+ let attachments: [MediaAttachment]
21
+
22
+ var body: some View {
23
+ ScrollView(.horizontal, showsIndicators: false) {
24
+ HStack {
25
+ ForEach(attachments) { attachment in
26
+ LazyImage(url: attachment.previewURL) { state in
27
+ if let image = state.image {
28
+ image.resizable().aspectRatio(contentMode: .fill)
29
+ } else {
30
+ ProgressView()
31
+ }
32
+ }
33
+ .frame(width: 120, height: 120)
34
+ .clipped()
35
+ .onTapGesture {
36
+ quickLook.prepareFor(
37
+ selectedMediaAttachment: attachment,
38
+ mediaAttachments: attachments
39
+ )
40
+ }
41
+ }
42
+ }
43
+ }
44
+ }
45
+ }
46
+ ```
47
+
48
+ ## Example: global media viewer sheet
49
+
50
+ ```swift
51
+ struct AppRoot: View {
52
+ @State private var quickLook = QuickLook.shared
53
+
54
+ var body: some View {
55
+ content
56
+ .environment(quickLook)
57
+ .sheet(item: $quickLook.selectedMediaAttachment) { selected in
58
+ MediaUIView(selectedAttachment: selected, attachments: quickLook.mediaAttachments)
59
+ }
60
+ }
61
+ }
62
+ ```
63
+
64
+ ## Design choices to keep
65
+
66
+ - Keep previews lightweight; load full media in the viewer.
67
+ - Use shared viewer state so any view can open media without prop-drilling.
68
+ - Use a single entry point for the viewer (sheet/window) to avoid duplicates.
69
+
70
+ ## Pitfalls
71
+
72
+ - Avoid loading full-size images in list rows; use resized previews.
73
+ - Don’t present multiple viewer sheets at once; keep a single source of truth.
@@ -0,0 +1,101 @@
1
+ # Menu Bar
2
+
3
+ ## Intent
4
+
5
+ Use this when adding or customizing the macOS/iPadOS menu bar with SwiftUI commands.
6
+
7
+ ## Core patterns
8
+
9
+ - Add commands at the `Scene` level with `.commands { ... }`.
10
+ - Use `SidebarCommands()` when your UI includes a navigation sidebar.
11
+ - Use `CommandMenu` for app-specific menus and group related actions.
12
+ - Use `CommandGroup` to insert items before/after system groups or replace them.
13
+ - Use `FocusedValue` for context-sensitive menu items that depend on the active scene.
14
+
15
+ ## Example: basic command menu
16
+
17
+ ```swift
18
+ @main
19
+ struct MyApp: App {
20
+ var body: some Scene {
21
+ WindowGroup {
22
+ ContentView()
23
+ }
24
+ .commands {
25
+ CommandMenu("Actions") {
26
+ Button("Run", action: run)
27
+ .keyboardShortcut("R")
28
+ Button("Stop", action: stop)
29
+ .keyboardShortcut(".")
30
+ }
31
+ }
32
+ }
33
+
34
+ private func run() {}
35
+ private func stop() {}
36
+ }
37
+ ```
38
+
39
+ ## Example: insert and replace groups
40
+
41
+ ```swift
42
+ WindowGroup {
43
+ ContentView()
44
+ }
45
+ .commands {
46
+ CommandGroup(before: .systemServices) {
47
+ Button("Check for Updates") { /* open updater */ }
48
+ }
49
+
50
+ CommandGroup(after: .newItem) {
51
+ Button("New from Clipboard") { /* create item */ }
52
+ }
53
+
54
+ CommandGroup(replacing: .help) {
55
+ Button("User Manual") { /* open docs */ }
56
+ }
57
+ }
58
+ ```
59
+
60
+ ## Example: focused menu state
61
+
62
+ ```swift
63
+ @Observable
64
+ final class DataModel {
65
+ var items: [String] = []
66
+ }
67
+
68
+ struct ContentView: View {
69
+ @State private var model = DataModel()
70
+
71
+ var body: some View {
72
+ List(model.items, id: \.self) { item in
73
+ Text(item)
74
+ }
75
+ .focusedSceneValue(model)
76
+ }
77
+ }
78
+
79
+ struct ItemCommands: Commands {
80
+ @FocusedValue(DataModel.self) private var model: DataModel?
81
+
82
+ var body: some Commands {
83
+ CommandGroup(after: .newItem) {
84
+ Button("New Item") {
85
+ model?.items.append("Untitled")
86
+ }
87
+ .disabled(model == nil)
88
+ }
89
+ }
90
+ }
91
+ ```
92
+
93
+ ## Menu bar and Settings
94
+
95
+ - Defining a `Settings` scene adds the Settings menu item on macOS automatically.
96
+ - If you need a custom entry point inside the app, use `OpenSettingsAction` or `SettingsLink`.
97
+
98
+ ## Pitfalls
99
+
100
+ - Avoid registering the same keyboard shortcut in multiple command groups.
101
+ - Don’t use menu items as the only discoverable entry point for critical features.
@@ -0,0 +1,159 @@
1
+ # NavigationStack
2
+
3
+ ## Intent
4
+
5
+ Use this pattern for programmatic navigation and deep links, especially when each tab needs an independent navigation history. The key idea is one `NavigationStack` per tab, each with its own path binding and router object.
6
+
7
+ ## Core architecture
8
+
9
+ - Define a route enum that is `Hashable` and represents all destinations.
10
+ - Create a lightweight router (or use a library such as `https://github.com/Dimillian/AppRouter`) that owns the `path` and any sheet state.
11
+ - Each tab owns its own router instance and binds `NavigationStack(path:)` to it.
12
+ - Inject the router into the environment so child views can navigate programmatically.
13
+ - Centralize destination mapping with a single `navigationDestination(for:)` block (or a `withAppRouter()` modifier).
14
+
15
+ ## Example: custom router with per-tab stack
16
+
17
+ ```swift
18
+ @MainActor
19
+ @Observable
20
+ final class RouterPath {
21
+ var path: [Route] = []
22
+ var presentedSheet: SheetDestination?
23
+
24
+ func navigate(to route: Route) {
25
+ path.append(route)
26
+ }
27
+
28
+ func reset() {
29
+ path = []
30
+ }
31
+ }
32
+
33
+ enum Route: Hashable {
34
+ case account(id: String)
35
+ case status(id: String)
36
+ }
37
+
38
+ @MainActor
39
+ struct TimelineTab: View {
40
+ @State private var routerPath = RouterPath()
41
+
42
+ var body: some View {
43
+ NavigationStack(path: $routerPath.path) {
44
+ TimelineView()
45
+ .navigationDestination(for: Route.self) { route in
46
+ switch route {
47
+ case .account(let id): AccountView(id: id)
48
+ case .status(let id): StatusView(id: id)
49
+ }
50
+ }
51
+ }
52
+ .environment(routerPath)
53
+ }
54
+ }
55
+ ```
56
+
57
+ ## Example: centralized destination mapping
58
+
59
+ Use a shared view modifier to avoid duplicating route switches across screens.
60
+
61
+ ```swift
62
+ extension View {
63
+ func withAppRouter() -> some View {
64
+ navigationDestination(for: Route.self) { route in
65
+ switch route {
66
+ case .account(let id):
67
+ AccountView(id: id)
68
+ case .status(let id):
69
+ StatusView(id: id)
70
+ }
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ Then apply it once per stack:
77
+
78
+ ```swift
79
+ NavigationStack(path: $routerPath.path) {
80
+ TimelineView()
81
+ .withAppRouter()
82
+ }
83
+ ```
84
+
85
+ ## Example: binding per tab (tabs with independent history)
86
+
87
+ ```swift
88
+ @MainActor
89
+ struct TabsView: View {
90
+ @State private var timelineRouter = RouterPath()
91
+ @State private var notificationsRouter = RouterPath()
92
+
93
+ var body: some View {
94
+ TabView {
95
+ TimelineTab(router: timelineRouter)
96
+ NotificationsTab(router: notificationsRouter)
97
+ }
98
+ }
99
+ }
100
+ ```
101
+
102
+ ## Example: generic tabs with per-tab NavigationStack
103
+
104
+ Use this when tabs are built from data and each needs its own path without hard-coded names.
105
+
106
+ ```swift
107
+ @MainActor
108
+ struct TabsView: View {
109
+ @State private var selectedTab: AppTab = .timeline
110
+ @State private var tabRouter = TabRouter()
111
+
112
+ var body: some View {
113
+ TabView(selection: $selectedTab) {
114
+ ForEach(AppTab.allCases) { tab in
115
+ NavigationStack(path: tabRouter.binding(for: tab)) {
116
+ tab.makeContentView()
117
+ }
118
+ .environment(tabRouter.router(for: tab))
119
+ .tabItem { tab.label }
120
+ .tag(tab)
121
+ }
122
+ }
123
+ }
124
+ }
125
+ ```
126
+
127
+ @MainActor
128
+ @Observable
129
+ final class TabRouter {
130
+ private var routers: [AppTab: RouterPath] = [:]
131
+
132
+ func router(for tab: AppTab) -> RouterPath {
133
+ if let router = routers[tab] { return router }
134
+ let router = RouterPath()
135
+ routers[tab] = router
136
+ return router
137
+ }
138
+
139
+ func binding(for tab: AppTab) -> Binding<[Route]> {
140
+ let router = router(for: tab)
141
+ return Binding(get: { router.path }, set: { router.path = $0 })
142
+ }
143
+ }
144
+
145
+ ## Design choices to keep
146
+
147
+ - One `NavigationStack` per tab to preserve independent history.
148
+ - A single source of truth for navigation state (`RouterPath` or library router).
149
+ - Use `navigationDestination(for:)` to map routes to views.
150
+ - Reset the path when app context changes (account switch, logout, etc.).
151
+ - Inject the router into the environment so child views can navigate and present sheets without prop-drilling.
152
+ - Keep sheet presentation state on the router if you want a single place to manage modals.
153
+
154
+ ## Pitfalls
155
+
156
+ - Do not share one path across all tabs unless you want global history.
157
+ - Ensure route identifiers are stable and `Hashable`.
158
+ - Avoid storing view instances in the path; store lightweight route data instead.
159
+ - If using a router object, keep it outside other `@Observable` objects to avoid nested observation.
@@ -0,0 +1,45 @@
1
+ # Overlay and toasts
2
+
3
+ ## Intent
4
+
5
+ Use overlays for transient UI (toasts, banners, loaders) without affecting layout.
6
+
7
+ ## Core patterns
8
+
9
+ - Use `.overlay(alignment:)` to place global UI without changing the underlying layout.
10
+ - Keep overlays lightweight and dismissible.
11
+ - Use a dedicated `ToastCenter` (or similar) for global state if multiple features trigger toasts.
12
+
13
+ ## Example: toast overlay
14
+
15
+ ```swift
16
+ struct AppRootView: View {
17
+ @State private var toast: Toast?
18
+
19
+ var body: some View {
20
+ content
21
+ .overlay(alignment: .top) {
22
+ if let toast {
23
+ ToastView(toast: toast)
24
+ .transition(.move(edge: .top).combined(with: .opacity))
25
+ .onAppear {
26
+ DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
27
+ withAnimation { self.toast = nil }
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
33
+ }
34
+ ```
35
+
36
+ ## Design choices to keep
37
+
38
+ - Prefer overlays for transient UI rather than embedding in layout stacks.
39
+ - Use transitions and short auto-dismiss timers.
40
+ - Keep the overlay aligned to a clear edge (`.top` or `.bottom`).
41
+
42
+ ## Pitfalls
43
+
44
+ - Avoid overlays that block all interaction unless explicitly needed.
45
+ - Don’t stack many overlays; use a queue or replace the current toast.
@@ -0,0 +1,62 @@
1
+ # Performance guardrails
2
+
3
+ ## Intent
4
+
5
+ Use these rules when a SwiftUI screen is large, scroll-heavy, frequently updated, or at risk of unnecessary recomputation.
6
+
7
+ ## Core rules
8
+
9
+ - Give `ForEach` and list content stable identity. Do not use unstable indices as identity when the collection can reorder or mutate.
10
+ - Keep expensive filtering, sorting, and formatting out of `body`; precompute or move it into a model/helper when it is not trivial.
11
+ - Narrow observation scope so only the views that read changing state need to update.
12
+ - Prefer lazy containers for larger scrolling content and extract subviews when only part of a screen changes frequently.
13
+ - Avoid swapping entire top-level view trees for small state changes; keep a stable root view and vary localized sections or modifiers.
14
+
15
+ ## Example: stable identity
16
+
17
+ ```swift
18
+ ForEach(items) { item in
19
+ Row(item: item)
20
+ }
21
+ ```
22
+
23
+ Prefer that over index-based identity when the collection can change order:
24
+
25
+ ```swift
26
+ ForEach(Array(items.enumerated()), id: \.offset) { _, item in
27
+ Row(item: item)
28
+ }
29
+ ```
30
+
31
+ ## Example: move expensive work out of body
32
+
33
+ ```swift
34
+ struct FeedView: View {
35
+ let items: [FeedItem]
36
+
37
+ private var sortedItems: [FeedItem] {
38
+ items.sorted(using: KeyPathComparator(\.createdAt, order: .reverse))
39
+ }
40
+
41
+ var body: some View {
42
+ List(sortedItems) { item in
43
+ FeedRow(item: item)
44
+ }
45
+ }
46
+ }
47
+ ```
48
+
49
+ If the work is more expensive than a small derived property, move it into a model, store, or helper that updates less often.
50
+
51
+ ## When to investigate further
52
+
53
+ - Janky scrolling in long feeds or grids
54
+ - Typing lag from search or form validation
55
+ - Overly broad view updates when one small piece of state changes
56
+ - Large screens with many conditionals or repeated formatting work
57
+
58
+ ## Pitfalls
59
+
60
+ - Recomputing heavy transforms every render
61
+ - Observing a large object from many descendants when only one field matters
62
+ - Building custom scroll containers when `List`, `LazyVStack`, or `LazyHGrid` would already solve the problem
@@ -0,0 +1,48 @@
1
+ # Previews
2
+
3
+ ## Intent
4
+
5
+ Use previews to validate layout, state wiring, and injected dependencies without relying on a running app or live services.
6
+
7
+ ## Core rules
8
+
9
+ - Add `#Preview` coverage for the primary state plus important secondary states such as loading, empty, and error.
10
+ - Use deterministic fixtures, mocks, and sample data. Do not make previews depend on live network calls, real databases, or global singletons.
11
+ - Install required environment dependencies directly in the preview so the view can render in isolation.
12
+ - Keep preview setup close to the view until it becomes noisy; then extract lightweight preview helpers or fixtures.
13
+ - If a preview crashes, fix the state initialization or dependency wiring before expanding the feature further.
14
+
15
+ ## Example: simple preview states
16
+
17
+ ```swift
18
+ #Preview("Loaded") {
19
+ ProfileView(profile: .fixture)
20
+ }
21
+
22
+ #Preview("Empty") {
23
+ ProfileView(profile: nil)
24
+ }
25
+ ```
26
+
27
+ ## Example: preview with injected dependencies
28
+
29
+ ```swift
30
+ #Preview("Search results") {
31
+ SearchView()
32
+ .environment(SearchClient.preview(results: [.fixture, .fixture2]))
33
+ .environment(Theme.preview)
34
+ }
35
+ ```
36
+
37
+ ## Preview checklist
38
+
39
+ - Does the preview install every required environment dependency?
40
+ - Does it cover at least one success path and one non-happy path?
41
+ - Are fixtures stable and small enough to be read quickly?
42
+ - Can the preview render without network, auth, or app-global initialization?
43
+
44
+ ## Pitfalls
45
+
46
+ - Do not hide preview crashes by making dependencies optional if the production view requires them.
47
+ - Avoid huge inline fixtures when a named sample is easier to read.
48
+ - Do not couple previews to global shared singletons unless the project has no alternative.