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,46 @@
1
+ # Demystify SwiftUI Performance (WWDC23) (Summary)
2
+
3
+ Context: WWDC23 session on building a mental model for SwiftUI performance and triaging hangs/hitches.
4
+
5
+ ## Performance loop
6
+
7
+ - Measure -> Identify -> Optimize -> Re-measure.
8
+ - Focus on concrete symptoms (slow navigation, broken animations, spinning cursor).
9
+
10
+ ## Dependencies and updates
11
+
12
+ - Views form a dependency graph; dynamic properties are a frequent source of updates.
13
+ - Use `Self._printChanges()` in debug only to inspect extra dependencies.
14
+ - Eliminate unnecessary dependencies by extracting views or narrowing state.
15
+ - Consider `@Observable` for more granular property tracking.
16
+
17
+ ## Common causes of slow updates
18
+
19
+ - Expensive view bodies (string interpolation, filtering, formatting).
20
+ - Dynamic property instantiation and state initialization in `body`.
21
+ - Slow identity resolution in lists/tables.
22
+ - Hidden work: bundle lookups, heap allocations, repeated string construction.
23
+
24
+ ## Avoid slow initialization in view bodies
25
+
26
+ - Don’t create heavy models synchronously in view bodies.
27
+ - Use `.task` to fetch async data and keep `init` lightweight.
28
+
29
+ ## Lists and tables identity rules
30
+
31
+ - Stable identity is critical for performance and animation.
32
+ - Ensure a constant number of views per element in `ForEach`.
33
+ - Avoid inline filtering in `ForEach`; pre-filter and cache collections.
34
+ - Avoid `AnyView` in list rows; it hides identity and increases cost.
35
+ - Flatten nested `ForEach` when possible to reduce overhead.
36
+
37
+ ## Table specifics
38
+
39
+ - `TableRow` resolves to a single row; row count must be constant.
40
+ - Prefer the streamlined `Table` initializer to enforce constant rows.
41
+ - Use explicit IDs for back deployment when needed.
42
+
43
+ ## Debugging aids
44
+
45
+ - Use Instruments for hangs and hitches.
46
+ - Use `_printChanges` to validate dependency assumptions during debug.
@@ -0,0 +1,29 @@
1
+ # Optimizing SwiftUI Performance with Instruments (Summary)
2
+
3
+ Context: WWDC session introducing the next-generation SwiftUI Instrument in Instruments 26 and how to diagnose SwiftUI-specific bottlenecks.
4
+
5
+ ## Key takeaways
6
+
7
+ - Profile SwiftUI issues with the SwiftUI template (SwiftUI instrument + Time Profiler + Hangs/Hitches).
8
+ - Long view body updates are a common bottleneck; use "Long View Body Updates" to identify slow bodies.
9
+ - Set inspection range on a long update and correlate with Time Profiler to find expensive frames.
10
+ - Keep work out of `body`: move formatting, sorting, image decoding, and other expensive work into cached or precomputed paths.
11
+ - Use Cause & Effect Graph to diagnose *why* updates occur; SwiftUI is declarative, so backtraces are often unhelpful.
12
+ - Avoid broad dependencies that trigger many updates (e.g., `@Observable` arrays or global environment reads).
13
+ - Prefer granular view models and scoped state so only the affected view updates.
14
+ - Environment values update checks still cost time; avoid placing fast-changing values (timers, geometry) in environment.
15
+ - Profile early and often during feature development to catch regressions.
16
+
17
+ ## Suggested workflow (condensed)
18
+
19
+ 1. Record a trace in Release mode using the SwiftUI template.
20
+ 2. Inspect "Long View Body Updates" and "Other Long Updates."
21
+ 3. Zoom into a long update, then inspect Time Profiler for hot frames.
22
+ 4. Fix slow body work by moving heavy logic into precomputed/cache paths.
23
+ 5. Use Cause & Effect Graph to identify unintended update fan-out.
24
+ 6. Re-record and compare the update counts and hitch frequency.
25
+
26
+ ## Example patterns from the session
27
+
28
+ - Caching formatted distance strings in a location manager instead of computing in `body`.
29
+ - Replacing a dependency on a global favorites array with per-item view models to reduce update fan-out.
@@ -0,0 +1,44 @@
1
+ # Profiling intake and collection checklist
2
+
3
+ ## Intent
4
+
5
+ Use this checklist when code review alone cannot explain the SwiftUI performance issue and you need runtime evidence from the user.
6
+
7
+ ## Ask for first
8
+
9
+ - Exact symptom: CPU spike, dropped frames, memory growth, hangs, or excessive view updates.
10
+ - Exact interaction: scrolling, typing, initial load, navigation push/pop, animation, sheet presentation, or background refresh.
11
+ - Target device and OS version.
12
+ - Whether the issue was reproduced on a real device or only in Simulator.
13
+ - Build configuration: Debug or Release.
14
+ - Whether the user already has a baseline or before/after comparison.
15
+
16
+ ## Default profiling request
17
+
18
+ Ask the user to:
19
+ - Run the app in a Release build when possible.
20
+ - Use the SwiftUI Instruments template.
21
+ - Reproduce the exact problematic interaction only long enough to capture the issue.
22
+ - Capture the SwiftUI timeline and Time Profiler together.
23
+ - Export the trace or provide screenshots of the key SwiftUI lanes and the Time Profiler call tree.
24
+
25
+ ## Ask for these artifacts
26
+
27
+ - Trace export or screenshots of the relevant SwiftUI lanes
28
+ - Time Profiler call tree screenshot or export
29
+ - Device/OS/build configuration
30
+ - A short note describing what action was happening at the time of the capture
31
+ - If memory is involved, the memory graph or Allocations data if available
32
+
33
+ ## When to ask for more
34
+
35
+ - Ask for a second capture if the first run mixes multiple interactions.
36
+ - Ask for a before/after pair if the user has already tried a fix.
37
+ - Ask for a device capture if the issue only appears in Simulator or if scrolling smoothness matters.
38
+
39
+ ## Common traps
40
+
41
+ - Debug builds can distort SwiftUI timing and allocation behavior.
42
+ - Simulator traces can miss device-only rendering or memory issues.
43
+ - Mixed interactions in one capture make attribution harder.
44
+ - Screenshots without the reproduction note are much harder to interpret.
@@ -0,0 +1,47 @@
1
+ # Audit output template
2
+
3
+ ## Intent
4
+
5
+ Use this structure when reporting SwiftUI performance findings so the user can quickly see the symptom, evidence, likely cause, and next validation step.
6
+
7
+ ## Template
8
+
9
+ ```markdown
10
+ ## Summary
11
+
12
+ [One short paragraph on the most likely bottleneck and whether the conclusion is code-backed or trace-backed.]
13
+
14
+ ## Findings
15
+
16
+ 1. [Issue title]
17
+ - Symptom: [what the user sees]
18
+ - Likely cause: [root cause]
19
+ - Evidence: [code reference or profiling evidence]
20
+ - Fix: [specific change]
21
+ - Validation: [what to measure after the fix]
22
+
23
+ 2. [Issue title]
24
+ - Symptom: ...
25
+ - Likely cause: ...
26
+ - Evidence: ...
27
+ - Fix: ...
28
+ - Validation: ...
29
+
30
+ ## Metrics
31
+
32
+ | Metric | Before | After | Notes |
33
+ | --- | --- | --- | --- |
34
+ | CPU | [value] | [value] | [note] |
35
+ | Frame drops / hitching | [value] | [value] | [note] |
36
+ | Memory peak | [value] | [value] | [note] |
37
+
38
+ ## Next step
39
+
40
+ [One concrete next action: apply a fix, capture a better trace, or validate on device.]
41
+ ```
42
+
43
+ ## Notes
44
+
45
+ - Order findings by impact, not by file order.
46
+ - Say explicitly when a conclusion is still a hypothesis.
47
+ - If no metrics are available, omit the table and say what should be measured next.
@@ -0,0 +1,33 @@
1
+ # Understanding Hangs in Your App (Summary)
2
+
3
+ Context: Apple guidance on identifying hangs caused by long-running main-thread work and understanding the main run loop.
4
+
5
+ ## Key concepts
6
+
7
+ - A hang is a noticeable delay in a discrete interaction (typically >100 ms).
8
+ - Hangs almost always come from long-running work on the main thread.
9
+ - The main run loop processes UI events, timers, and main-queue work sequentially.
10
+
11
+ ## Main-thread work stages
12
+
13
+ - Event delivery to the correct view/handler.
14
+ - Your code: state updates, data fetch, UI changes.
15
+ - Core Animation commit to the render server.
16
+
17
+ ## Why the main run loop matters
18
+
19
+ - Only the main thread can update UI safely.
20
+ - The run loop is the foundation that executes main-queue work.
21
+ - If the run loop is busy, it can’t handle new events; this causes hangs.
22
+
23
+ ## Diagnosing hangs
24
+
25
+ - Observe the main run loop’s busy periods: healthy loops sleep most of the time.
26
+ - Hang detection typically flags busy periods >250 ms.
27
+ - The Hangs instrument can be configured to lower thresholds.
28
+
29
+ ## Practical takeaways
30
+
31
+ - Keep main-thread work short; offload heavy work from event handlers.
32
+ - Avoid long-running tasks on the main dispatch queue or main actor.
33
+ - Use run loop behavior as a proxy for user-perceived responsiveness.
@@ -0,0 +1,52 @@
1
+ # Understanding and Improving SwiftUI Performance (Summary)
2
+
3
+ Context: Apple guidance on diagnosing SwiftUI performance with Instruments and applying design patterns to reduce long or frequent updates.
4
+
5
+ ## Core concepts
6
+
7
+ - SwiftUI is declarative; view updates are driven by state, environment, and observable data dependencies.
8
+ - View bodies must compute quickly to meet frame deadlines; slow or frequent updates lead to hitches.
9
+ - Instruments is the primary tool to find long-running updates and excessive update frequency.
10
+
11
+ ## Instruments workflow
12
+
13
+ 1. Profile via Product > Profile.
14
+ 2. Choose the SwiftUI template and record.
15
+ 3. Exercise the target interaction.
16
+ 4. Stop recording and inspect the SwiftUI track + Time Profiler.
17
+
18
+ ## SwiftUI timeline lanes
19
+
20
+ - Update Groups: overview of time SwiftUI spends calculating updates.
21
+ - Long View Body Updates: orange >500us, red >1000us.
22
+ - Long Platform View Updates: AppKit/UIKit hosting in SwiftUI.
23
+ - Other Long Updates: geometry/text/layout and other SwiftUI work.
24
+ - Hitches: frame misses where UI wasn’t ready in time.
25
+
26
+ ## Diagnose long view body updates
27
+
28
+ - Expand the SwiftUI track; inspect module-specific subtracks.
29
+ - Set Inspection Range and correlate with Time Profiler.
30
+ - Use call tree or flame graph to identify expensive frames.
31
+ - Repeat the update to gather enough samples for analysis.
32
+ - Filter to a specific update (Show Calls Made by `MySwiftUIView.body`).
33
+
34
+ ## Diagnose frequent updates
35
+
36
+ - Use Update Groups to find long active groups without long updates.
37
+ - Set inspection range on the group and analyze update counts.
38
+ - Use Cause graph ("Show Causes") to see what triggers updates.
39
+ - Compare causes with expected data flow; prioritize the highest-frequency causes.
40
+
41
+ ## Remediation patterns
42
+
43
+ - Move expensive work out of `body` and cache results.
44
+ - Use `Observable()` macro to scope dependencies to properties actually read.
45
+ - Avoid broad dependencies that fan out updates to many views.
46
+ - Reduce layout churn; isolate state-dependent subtrees from layout readers.
47
+ - Avoid storing closures that capture parent state; precompute child views.
48
+ - Gate frequent updates (e.g., geometry changes) by thresholds.
49
+
50
+ ## Verification
51
+
52
+ - Re-record after changes to confirm reduced update counts and fewer hitches.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Paul Hudson.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: swiftui-pro
3
+ description: Comprehensively reviews SwiftUI code for best practices on modern APIs, maintainability, and performance. Use when reading, writing, or reviewing SwiftUI projects.
4
+ license: MIT
5
+ metadata:
6
+ author: Paul Hudson
7
+ version: "1.0"
8
+ ---
9
+
10
+ Review Swift and SwiftUI code for correctness, modern API usage, and adherence to project conventions. Report only genuine problems - do not nitpick or invent issues.
11
+
12
+ Review process:
13
+
14
+ 1. Check for deprecated API using `references/api.md`.
15
+ 1. Check that views, modifiers, and animations have been written optimally using `references/views.md`.
16
+ 1. Validate that data flow is configured correctly using `references/data.md`.
17
+ 1. Ensure navigation is updated and performant using `references/navigation.md`.
18
+ 1. Ensure the code uses designs that are accessible and compliant with Apple’s Human Interface Guidelines using `references/design.md`.
19
+ 1. Validate accessibility compliance including Dynamic Type, VoiceOver, and Reduce Motion using `references/accessibility.md`.
20
+ 1. Ensure the code is able to run efficiently using `references/performance.md`.
21
+ 1. Quick validation of Swift code using `references/swift.md`.
22
+ 1. Final code hygiene check using `references/hygiene.md`.
23
+
24
+ If doing a partial review, load only the relevant reference files.
25
+
26
+
27
+ ## Core Instructions
28
+
29
+ - iOS 26 exists, and is the default deployment target for new apps.
30
+ - Target Swift 6.2 or later, using modern Swift concurrency.
31
+ - As a SwiftUI developer, the user will want to avoid UIKit unless requested.
32
+ - Do not introduce third-party frameworks without asking first.
33
+ - Break different types up into different Swift files rather than placing multiple structs, classes, or enums into a single file.
34
+ - Use a consistent project structure, with folder layout determined by app features.
35
+
36
+
37
+ ## Output Format
38
+
39
+ Organize findings by file. For each issue:
40
+
41
+ 1. State the file and relevant line(s).
42
+ 2. Name the rule being violated (e.g., "Use `foregroundStyle()` instead of `foregroundColor()`").
43
+ 3. Show a brief before/after code fix.
44
+
45
+ Skip files with no issues. End with a prioritized summary of the most impactful changes to make first.
46
+
47
+ Example output:
48
+
49
+ ### ContentView.swift
50
+
51
+ **Line 12: Use `foregroundStyle()` instead of `foregroundColor()`.**
52
+
53
+ ```swift
54
+ // Before
55
+ Text("Hello").foregroundColor(.red)
56
+
57
+ // After
58
+ Text("Hello").foregroundStyle(.red)
59
+ ```
60
+
61
+ **Line 24: Icon-only button is bad for VoiceOver - add a text label.**
62
+
63
+ ```swift
64
+ // Before
65
+ Button(action: addUser) {
66
+ Image(systemName: "plus")
67
+ }
68
+
69
+ // After
70
+ Button("Add User", systemImage: "plus", action: addUser)
71
+ ```
72
+
73
+ **Line 31: Avoid `Binding(get:set:)` in view body - use `@State` with `onChange()` instead.**
74
+
75
+ ```swift
76
+ // Before
77
+ TextField("Username", text: Binding(
78
+ get: { model.username },
79
+ set: { model.username = $0; model.save() }
80
+ ))
81
+
82
+ // After
83
+ TextField("Username", text: $model.username)
84
+ .onChange(of: model.username) {
85
+ model.save()
86
+ }
87
+ ```
88
+
89
+ ### Summary
90
+
91
+ 1. **Accessibility (high):** The add button on line 24 is invisible to VoiceOver.
92
+ 2. **Deprecated API (medium):** `foregroundColor()` on line 12 should be `foregroundStyle()`.
93
+ 3. **Data flow (medium):** The manual binding on line 31 is fragile and harder to maintain.
94
+
95
+ End of example.
96
+
97
+
98
+ ## References
99
+
100
+ - `references/accessibility.md` - Dynamic Type, VoiceOver, Reduce Motion, and other accessibility requirements.
101
+ - `references/api.md` - updating code for modern API, and the deprecated code it replaces.
102
+ - `references/design.md` - guidance for building accessible apps that meet Apple’s Human Interface Guidelines.
103
+ - `references/hygiene.md` - making code compile cleanly and be maintainable in the long term.
104
+ - `references/navigation.md` - navigation using `NavigationStack`/`NavigationSplitView`, plus alerts, confirmation dialogs, and sheets.
105
+ - `references/performance.md` - optimizing SwiftUI code for maximum performance.
106
+ - `references/data.md` - data flow, shared state, and property wrappers.
107
+ - `references/swift.md` - tips on writing modern Swift code, including using Swift Concurrency effectively.
108
+ - `references/views.md` - view structure, composition, and animation.
@@ -0,0 +1,10 @@
1
+ interface:
2
+ display_name: "SwiftUI Pro"
3
+ short_description: "Reviews SwiftUI code for modern best practices."
4
+ icon_small: "./assets/swiftui-pro-icon.svg"
5
+ icon_large: "./assets/swiftui-pro-icon.png"
6
+ brand_color: "#006AFD"
7
+ default_prompt: "Use $swiftui-pro to review my project."
8
+
9
+ policy:
10
+ allow_implicit_invocation: true
@@ -0,0 +1,29 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="227.72" height="227.72" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 227.72 227.72">
3
+ <defs>
4
+ <style>
5
+ .st0 {
6
+ fill: none;
7
+ stroke: url(#linear-gradient1);
8
+ stroke-miterlimit: 10;
9
+ stroke-width: 6px;
10
+ }
11
+
12
+ .st1 {
13
+ fill: url(#linear-gradient);
14
+ fill-rule: evenodd;
15
+ }
16
+ </style>
17
+ <linearGradient id="linear-gradient" x1="58.405" y1="206.955" x2="178.785" y2="86.575" gradientTransform="translate(0 260) scale(1 -1)" gradientUnits="userSpaceOnUse">
18
+ <stop offset="0" stop-color="#00d9ff"/>
19
+ <stop offset="1" stop-color="#006efd"/>
20
+ </linearGradient>
21
+ <linearGradient id="linear-gradient1" x1="33.349" y1="218.651" x2="194.371" y2="57.629" gradientTransform="translate(0 252) scale(1 -1)" gradientUnits="userSpaceOnUse">
22
+ <stop offset="0" stop-color="#00eeaf"/>
23
+ <stop offset="0" stop-color="#00d8ff"/>
24
+ <stop offset="1" stop-color="#006ffd"/>
25
+ </linearGradient>
26
+ </defs>
27
+ <path class="st1" d="M165.43,131.08c3.87-8.17,16.03-46.62-38.6-85.38,7.61,7.03,40.19,39.2,26.05,75.5-34.2-25.27-87.91-66.75-87.91-66.75,0,0,63.69,60.57,83.58,79.15,19.9,18.59,26.97,27.71,26.47,43.59,0,.01,14.58-23.23-9.59-46.11ZM130.89,145.79c-39.35,18.56-78.42-20.82-78.42-20.82,0,0,21.12,26.7,45.19,35.06,33.72,11.71,54.61-9.64,54.61-9.64L52.42,59.03s56.43,62.62,78.47,86.76Z"/>
28
+ <circle class="st0" cx="113.86" cy="113.86" r="110.86"/>
29
+ </svg>
@@ -0,0 +1,13 @@
1
+ # Accessibility
2
+
3
+ - Respect the user’s accessibility settings for fonts, colors, animations, and more.
4
+ - Do not force specific font sizes. Prefer Dynamic Type (`.font(.body)`, `.font(.headline)`, etc.).
5
+ - If you *need* a custom font size, use `@ScaledMetric` when targeting iOS 18 and earlier. When targeting iOS 26 or later, `.font(.body.scaled(by:))` is also available to get font size adjustment.
6
+ - Flag instances where images have unclear or unhelpful VoiceOver readings, e.g. `Image(.newBanner2026)`. If they are decorative, suggest using `Image(decorative:)` or `accessibilityHidden()`, otherwise attach an `accessibilityLabel()`.
7
+ - If the user has “Reduce Motion” enabled, replace large, motion-based animations with opacity instead.
8
+ - If buttons have complex or frequently changing labels, recommend using `accessibilityInputLabels()` to provide better Voice Control commands. For example, if a button had a live-updating share price for Apple such as “AAPL $271.68”, adding an input label for “Apple” would be a big improvement.
9
+ - Buttons with image labels must always include text, even if the text is invisible: `Button("Label", systemImage: "plus", action: myAction)`. Flag icon-only buttons that lack a text label as being bad for VoiceOver.
10
+ - If color is an important differentiator in the user interface, make sure to respect the environment’s `.accessibilityDifferentiateWithoutColor` setting by showing some kind of variation beyond just color – icons, patterns, strokes, etc.
11
+ - The same is true of `Menu`: using `Menu("Options", systemImage: "ellipsis.circle") { }` is much better than just using an image.
12
+ - Never use `onTapGesture()` unless you specifically need tap location or tap count. All other tappable elements should be a `Button`.
13
+ - If `onTapGesture()` must be used, make sure to add `.accessibilityAddTraits(.isButton)` or similar so it can be read by VoiceOver correctly.
@@ -0,0 +1,39 @@
1
+ # Using modern SwiftUI API
2
+
3
+ - Always use `foregroundStyle()` instead of `foregroundColor()`.
4
+ - Always use `clipShape(.rect(cornerRadius:))` instead of `cornerRadius()`.
5
+ - Always use the `Tab` API instead of `tabItem()`.
6
+ - Never use the `onChange()` modifier in its 1-parameter variant; either use the variant that accepts two parameters or accepts none.
7
+ - Do not use `GeometryReader` if a newer alternative works: `containerRelativeFrame()`, `visualEffect()`, or the `Layout` protocol. Flag `GeometryReader` usage and suggest the modern alternative.
8
+ - When designing haptic effects, prefer using `sensoryFeedback()` over older UIKit APIs such as `UIImpactFeedbackGenerator`.
9
+ - Use the `@Entry` macro to define custom `EnvironmentValues`, `FocusValues`, `Transaction`, and `ContainerValues` keys. This replaces the legacy pattern of manually creating a type conforming to (for example) `EnvironmentKey` with a `defaultValue`, then extending `EnvironmentValues` with a computed property.
10
+ - Strongly prefer `overlay(alignment:content:)` over the deprecated `overlay(_:alignment:)`. For example, use `.overlay { Text("Hello, world!") }` rather than `.overlay(Text("Hello, world!"))`.
11
+ - Never use `.navigationBarLeading` and `.navigationBarTrailing` for toolbar item placement; they are deprecated. The correct, modern placements are `.topBarLeading` and `.topBarTrailing`.
12
+ - Prefer to rely on automatic grammar agreement when dealing with English, French, German, Portuguese, Spanish, and Italian. For example, use `Text("^[\(people) person](inflect: true)")` to show a number of people.
13
+ - You can fill and stroke a shape with two chained modifiers; you do *not* need an overlay for the stroke. The overlay was required previously, but this is fixed in iOS 17 and later.
14
+ - When referencing images from an asset catalog, prefer the generated symbol asset API when the project is configured to use them: `Image(.avatar)` rather than `Image("avatar")`.
15
+ - When targeting iOS 26 and later, SwiftUI has a native `WebView` view type that replaces almost all uses of hand-wrapped `WKWebView` inside `UIViewRepresentable`. To use it, make sure to include `import WebKit`.
16
+ - `ForEach` over an `enumerated()` sequence should not convert to an array first. Use `ForEach(items.enumerated(), id: \.element.id)` directly.
17
+ - When hiding scroll indicators, use `.scrollIndicators(.hidden)` rather than `showsIndicators: false` in the initializer.
18
+ - Never use `Text` concatenation with `+`.
19
+
20
+ For example, the usage of `+` here is bad and deprecated:
21
+
22
+ ```swift
23
+ Text("Hello").foregroundStyle(.red)
24
+ +
25
+ Text("World").foregroundStyle(.blue)
26
+ ```
27
+
28
+ Instead, use text interpolation like this:
29
+
30
+ ```swift
31
+ let red = Text("Hello").foregroundStyle(.red)
32
+ let blue = Text("World").foregroundStyle(.blue)
33
+ Text("\(red)\(blue)")
34
+ ```
35
+
36
+
37
+ ## Using ObservableObject
38
+
39
+ If using `ObservableObject` is absolutely required – for example if you are trying to create a debouncer using a Combine publisher – you should always make sure `import Combine` is added. This was previously provided through SwiftUI, but that is no longer the case.
@@ -0,0 +1,43 @@
1
+ # Data flow, shared state, and property wrappers
2
+
3
+ It is important that SwiftUI body code and logic code be kept separate in order to make code easier to read, write, and maintain. That usually means placing code into methods rather than inline in the `body` property, but often also means carving functionality out into separate `@Observable` classes.
4
+
5
+ These rules help ensure code is efficient and works well in the long term.
6
+
7
+
8
+ ## Shared state
9
+
10
+ - `@Observable` classes must be marked `@MainActor` unless the project has Main Actor default actor isolation. Flag any `@Observable` class missing this annotation.
11
+ - All shared data should use `@Observable` classes with `@State` (for ownership) and `@Bindable` / `@Environment` (for passing).
12
+ - Strongly prefer not to use `ObservableObject`, `@Published`, `@StateObject`, `@ObservedObject`, or `@EnvironmentObject` unless they are unavoidable, or if they exist in legacy/integration contexts when changing architecture would be complicated.
13
+
14
+
15
+ ## Local state
16
+
17
+ - `@State` should be marked `private` and only owned by the view that created it.
18
+ - If a view stores a class instance that contains expensive-to-recompute data, e.g. `CIContext`, it can be stored using `@State` even though it is not an observable object. This effectively uses `@State` as a cache – storing something persistently, but not doing any change tracking on it since it's not an observable object.
19
+
20
+
21
+ ## Bindings
22
+
23
+ - Strongly prefer to avoid creating bindings using `Binding(get:set:)` in view body code. It is much cleaner and simpler to use a binding provided by `@State`, `@Binding` or similar, then use `onChange()` to trigger any effects.
24
+ - If the user needs to enter a number into a `TextField`, bind the `TextField` to a numeric value such as `Int` or `Double`, then use its `format` initializer like this: `TextField("Enter your score", value: $score, format: .number)`. Apply either `.keyboardType(.numberPad)` (for integers) or `.keyboardType(.decimalPad)` (for floating-point numbers) as appropriate. Using the modifier alone is *not* sufficient.
25
+
26
+
27
+ ## Working with data
28
+
29
+ - Prefer to make structs conform to `Identifiable` rather than using `id: \.someProperty` in SwiftUI code.
30
+ - Never attempt to use `@AppStorage` inside an `@Observable` class, even if marked `@ObservationIgnored` – it will *not* trigger view updates when a change happens.
31
+
32
+
33
+ ## SwiftData
34
+
35
+ - If you only need the number of items matching a query, consider `ModelContext.fetchCount()` with a fetch descriptor. This will *not* live update if the data changes unless something else triggers the update, such as `@Query`, so it should be used carefully.
36
+
37
+ For more help with SwiftData, suggest the [SwiftData Pro agent skill](https://github.com/twostraws/swiftdata-agent-skill).
38
+
39
+ ## If the project uses SwiftData with CloudKit
40
+
41
+ - Never use `@Attribute(.unique)`.
42
+ - Model properties must always either have default values or be marked as optional.
43
+ - All relationships must be marked optional.
@@ -0,0 +1,31 @@
1
+ # Design
2
+
3
+ ## Creating a uniform design in this app
4
+
5
+ Prefer to place standard fonts, sizes, colors, stack spacing, padding, rounding, animation timings, and more into a shared enum of constants, so they can be used by all views. This allows the app’s design to feel uniform and consistent, and be adjusted easily.
6
+
7
+
8
+ ## Requirements for flexible, accessible design
9
+
10
+ - Never use `UIScreen.main.bounds` to read available space; prefer alternatives such as `containerRelativeFrame()`, or `visualEffect()` as appropriate, or (if there is no alternative) `GeometryReader`.
11
+ - Prefer to avoid fixed frames for views unless content can fit neatly inside; this can cause problems across different device sizes, different Dynamic Type settings, and more. Giving frames some flexibility is usually preferred.
12
+ - Apple’s minimum acceptable tap area for interactions on iOS is 44x44. Ensure this is strictly enforced.
13
+
14
+
15
+ ## Standard system styling
16
+
17
+ - Strongly prefer to use `ContentUnavailableView` when data is missing or empty, rather than designing something custom.
18
+ - When using `searchable()`, you can show empty results using `ContentUnavailableView.search` and it will include the search term they used automatically – there’s no need to use `ContentUnavailableView.search(text: searchText)` or similar.
19
+ - If you need an icon and some text placed horizontally side by side, prefer `Label` over `HStack`.
20
+ - Prefer system hierarchical styles (e.g. secondary/tertiary) over manual opacity when possible, so the system can adapt to the correct context automatically.
21
+ - When using `Form`, wrap controls such as `Slider` in `LabeledContent` so the title and control are laid out correctly.
22
+ - When using `RoundedRectangle`, the default rounding style is `.continuous` – there is no need to specify it explicitly.
23
+
24
+
25
+ ## Ensuring designs work for everyone
26
+
27
+ - Use `bold()` instead of `fontWeight(.bold)`, because using `bold()` allows the system to choose the correct weight for the current context.
28
+ - Only use `fontWeight()` for weights other than bold when there's an important reason - scattering around `fontWeight(.medium)` or `fontWeight(.semibold)` is counterproductive.
29
+ - Avoid hard-coded values for padding and stack spacing unless specifically requested.
30
+ - Avoid UIKit colors (`UIColor`) in SwiftUI code; use SwiftUI `Color` or asset catalog colors.
31
+ - The font size `.caption2` is extremely small, and is generally best avoided. Even the font size `.caption` is on the small side, and should be used carefully.
@@ -0,0 +1,9 @@
1
+ # Hygiene
2
+
3
+ - If the project requires secrets such as API keys, never include them in the repository.
4
+ - Code comments and documentation comments should be present where the logic isn't self-evident.
5
+ - Unit tests should exist for core application logic. UI tests only where unit tests are not possible.
6
+ - `@AppStorage` must never be used to store usernames, passwords, or other sensitive data. Use the keychain for that.
7
+ - If SwiftLint is configured, it should return no warnings or errors.
8
+ - If the project uses Localizable.xcstrings, prefer to add user-facing strings using symbol keys (e.g. “helloWorld”) in the string catalog with `extractionState` set to "manual", accessing them via generated symbols such as `Text(.helloWorld)`. Offer to translate new keys into all languages supported by the project.
9
+ - If the Xcode MCP is configured, prefer its tools over generic alternatives. For example, `RenderPreview` is able to capture images of rendered SwiftUI previews for examination, and `DocumentationSearch` can search Apple’s documentation for latest usage instructions.
@@ -0,0 +1,14 @@
1
+ # Navigation and presentation
2
+
3
+ - Use `NavigationStack` or `NavigationSplitView` as appropriate; flag all use of the deprecated `NavigationView`.
4
+ - Strongly prefer to use `navigationDestination(for:)` to specify destinations; flag all use of the old `NavigationLink(destination:)` pattern where it should be replaced.
5
+ - Never mix `navigationDestination(for:)` and `NavigationLink(destination:)` in the same navigation hierarchy; it causes significant problems.
6
+ - `navigationDestination(for:)` must be registered once per data type; flag duplicates.
7
+
8
+
9
+ ## Alerts, confirmation dialogs, and sheets
10
+
11
+ - Always attach `confirmationDialog()` to the user interface that triggers the dialog. This allows Liquid Glass animations to move from the correct source.
12
+ - If an alert has only a single “OK” button that does nothing but dismiss the alert, it can be omitted entirely: `.alert("Dismiss Me", isPresented: $isShowingAlert) { }`.
13
+ - If a sheet is designed to present an optional piece of data, prefer `sheet(item:)` over `sheet(isPresented:)` so the optional is safely unwrapped.
14
+ - When using `sheet(item:)` with a view that accepts the item as its only initializer parameter, prefer `sheet(item: $someItem, content: SomeView.init)` over `sheet(item: $someItem) { someItem in SomeView(item: someItem) }`.
@@ -0,0 +1,46 @@
1
+ # Performance
2
+
3
+ - When toggling modifier values, prefer ternary expressions over if/else view branching to avoid `_ConditionalContent`, preserve structural identity, and avoid repeatedly recreating underlying platform views.
4
+ - Avoid `AnyView` unless absolutely required. Use `@ViewBuilder`, `Group`, or generics instead.
5
+ - If a `ScrollView` has an opaque, static, and solid background, prefer to use `scrollContentBackground(.visible)` to improve scroll-edge rendering efficiency.
6
+ - It is more efficient to break views up by making dedicated SwiftUI views rather than place them into computed properties or methods. Using `@ViewBuilder` on a property or method does not solve this; breaking views up is strongly preferred.
7
+ - Always ensure view initializers are kept as small and simple as possible, avoiding any non-trivial work. Flag any work that can be moved into a `task()` modifier to be run when the view is shown.
8
+ - Similarly, assume each view’s `body` property is called frequently – if logic such as sorting or filtering can be moved out of there easily, it should be.
9
+ - Avoid creating properties to store formatters such as `DateFormatter` unless they are required. A more natural approach is to use `Text` with a format, like this: `Text(Date.now, format: .dateTime.day().month().year())` or `Text(100, format: .currency(code: "USD"))`.
10
+ - Avoid expensive inline transforms in `List`/`ForEach` initializers (e.g. `items.filter { ... }`) when they are repeated often.
11
+ - Prefer deriving transformed data from the source-of-truth using `let`, or caching in `@State`. However, do not cache derived collections in `@State` unless you also own explicit invalidation logic to avoid stale UI.
12
+ - For large data sets in `ScrollView`, use `LazyVStack`/`LazyHStack`; flag eager stacks with many children.
13
+ - Prefer using `task()` over `onAppear()` when doing async work, because it will be cancelled automatically when the view disappears.
14
+ - Avoid storing escaping `@ViewBuilder` closures on views when possible; store built view results instead.
15
+
16
+ Example:
17
+
18
+ ```swift
19
+ // Anti-pattern: stores an escaping closure on the view.
20
+ struct CardView<Content: View>: View {
21
+ let content: () -> Content
22
+
23
+ var body: some View {
24
+ VStack(alignment: .leading) {
25
+ content()
26
+ }
27
+ .padding()
28
+ .background(.ultraThinMaterial)
29
+ .clipShape(.rect(cornerRadius: 8))
30
+ }
31
+ }
32
+
33
+ // Preferred: store the built view value; the synthesized init handles calling the builder.
34
+ struct CardView<Content: View>: View {
35
+ @ViewBuilder let content: Content
36
+
37
+ var body: some View {
38
+ VStack(alignment: .leading) {
39
+ content
40
+ }
41
+ .padding()
42
+ .background(.ultraThinMaterial)
43
+ .clipShape(.rect(cornerRadius: 8))
44
+ }
45
+ }
46
+ ```