[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FEJDBCWRNAMXD7JK3DV111":3,"skill-same:01M6FEJDBCWRNAMXD7JK3DV111":49},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":22,"linkOnly":23,"markdownContent":24,"markdownBody":24,"frontMatter":25,"refName":26,"commitSha":27,"skillDirectory":28,"forksCount":29,"repositoryHtmlUrl":30,"repositoryHomepageUrl":31,"ownerHtmlUrl":32,"ownerBlogUrl":6,"ownerDescription":33,"updatedAt":34,"install":35,"resources":48},"01M6FEJDBCWRNAMXD7JK3DV111","swift-ui-architect",null,"ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",66,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fpproenca\u002Fdot-skills\u002Fswift-ui-architect\u002FSKILL.md",[],[18,19,20,21],"swift","ui","architect","swift ui architect","2026-11-10 10:12:30",false,"# SwiftUI Modular MVVM-C Architecture\n\nOpinionated architecture enforcement for SwiftUI clinic-style apps. This skill aligns to the iOS 26 \u002F Swift 6.2 clinic architecture: modular MVVM-C in local SPM packages, concrete coordinators and route shells in the App target, pure Domain protocols, and Data as the only I\u002FO layer.\n\n## Mandated Architecture Stack\n\n```\n┌───────────────────────────────────────────────────────────────┐\n│ App target: DependencyContainer, Coordinators, Route Shells   │\n├───────────────┬───────────────┬───────────────┬──────────────┤\n│ Feature* SPM  │ Feature* SPM  │ Feature* SPM  │ Feature* SPM │\n│ View + VM     │ View + VM     │ View + VM     │ View + VM    │\n├───────────────────────────────────────────────────────────────┤\n│ Data SPM: repository impls, remote\u002Flocal, retry, sync queue   │\n├───────────────────────────────────────────────────────────────┤\n│ Domain SPM: models, repository protocols, coordinator protocols│\n│ and ErrorRouting\u002FAppError                                      │\n├───────────────────────────────────────────────────────────────┤\n│ Shared SPMs: DesignSystem, SharedKit                           │\n└───────────────────────────────────────────────────────────────┘\n```\n\n**Dependency Rule**: Feature modules import `Domain` + `DesignSystem` only. Features never import `Data` or other features. App target is the only convergence point.\n\n\n## Clinic Architecture Contract (iOS 26 \u002F Swift 6.2)\n\nAll guidance in this skill assumes the clinic modular MVVM-C architecture:\n\n- Feature modules import `Domain` + `DesignSystem` only (never `Data`, never sibling features)\n- App target is the convergence point and owns `DependencyContainer`, concrete coordinators, and Route Shell wiring\n- `Domain` stays pure Swift and defines models plus repository, `*Coordinating`, `ErrorRouting`, and `AppError` contracts\n- `Data` owns SwiftData\u002Fnetwork\u002Fsync\u002Fretry\u002Fbackground I\u002FO and implements Domain protocols\n- Read\u002Fwrite flow defaults to stale-while-revalidate reads and optimistic queued writes\n- ViewModels call repository protocols directly (no default use-case\u002Finteractor layer)\n\n## When to Apply\n\nReference these guidelines when:\n- Building or refactoring feature modules under local SPM packages\n- Wiring coordinators, route shells, and dependency container factories\n- Defining Domain protocols for repositories, coordinators, and error routing\n- Enforcing Data-only ownership of networking, persistence, and sync\n- Reviewing stale-while-revalidate reads and optimistic queued writes\n\n## Non-Negotiable Constraints (iOS 26 \u002F Swift 6.2)\n\n- `@Observable` for ViewModels\u002Fcoordinators, `ObservableObject` \u002F `@Published` never\n- No dedicated use-case\u002Finteractor layer: ViewModels call Domain repository protocols directly\n- Coordinator protocols live in Domain; concrete coordinators own `NavigationPath` in App target\n- Route shells live in App target and own `.navigationDestination` mapping\n- `AppError` + `ErrorRouting` drive presentation policy; ViewModels do not hardcode global error UI\n- SwiftData \u002F URLSession \u002F retry \u002F sync queue logic stays in Data package only\n\n## Rule Categories by Priority\n\n| Priority | Category | Impact | Prefix | Rules |\n|----------|----------|--------|--------|-------|\n| 1 | View Identity & Diffing | CRITICAL | `diff-` | 6 |\n| 2 | State Architecture | CRITICAL | `state-` | 7 |\n| 3 | View Composition | HIGH | `view-` | 6 |\n| 4 | Navigation & Coordination | HIGH | `nav-` | 5 |\n| 5 | Layer Architecture | HIGH | `layer-` | 6 |\n| 6 | Dependency Injection | MEDIUM-HIGH | `di-` | 4 |\n| 7 | List & Collection Performance | MEDIUM | `list-` | 4 |\n| 8 | Async & Data Flow | MEDIUM | `data-` | 5 |\n\n## Quick Reference\n\n### 1. View Identity & Diffing (CRITICAL)\n\n- [`diff-equatable-views`](references\u002Fdiff-equatable-views.md) - Apply @Equatable macro to every SwiftUI view\n- [`diff-closure-skip`](references\u002Fdiff-closure-skip.md) - Use @SkipEquatable for closure\u002Fhandler properties\n- [`diff-reference-types`](references\u002Fdiff-reference-types.md) - Never store reference types without Equatable conformance\n- [`diff-identity-stability`](references\u002Fdiff-identity-stability.md) - Use stable O(1) identifiers in ForEach\n- [`diff-avoid-anyview`](references\u002Fdiff-avoid-anyview.md) - Never use AnyView — use @ViewBuilder or generics\n- [`diff-printchanges-debug`](references\u002Fdiff-printchanges-debug.md) - Use _printChanges() to diagnose unnecessary re-renders\n\n### 2. State Architecture (CRITICAL)\n\n- [`state-observable-class`](references\u002Fstate-observable-class.md) - Use @Observable classes for all ViewModels\n- [`state-ownership`](references\u002Fstate-ownership.md) - @State for owned data, plain property for injected data\n- [`state-single-source`](references\u002Fstate-single-source.md) - One source of truth per piece of state\n- [`state-scoped-observation`](references\u002Fstate-scoped-observation.md) - Leverage @Observable property-level tracking\n- [`state-binding-minimal`](references\u002Fstate-binding-minimal.md) - Pass @Binding only for two-way data flow\n- [`state-environment-global`](references\u002Fstate-environment-global.md) - Use @Environment for app-wide shared dependencies\n- [`state-no-published`](references\u002Fstate-no-published.md) - Never use @Published or ObservableObject\n\n### 3. View Composition (HIGH)\n\n- [`view-body-complexity`](references\u002Fview-body-complexity.md) - Maximum 10 nodes in view body\n- [`view-extract-subviews`](references\u002Fview-extract-subviews.md) - Extract computed properties\u002Fhelpers into separate View structs\n- [`view-no-logic-in-body`](references\u002Fview-no-logic-in-body.md) - Zero business logic in body\n- [`view-minimal-dependencies`](references\u002Fview-minimal-dependencies.md) - Pass only needed properties, not entire models\n- [`view-viewbuilder-composition`](references\u002Fview-viewbuilder-composition.md) - Use @ViewBuilder for conditional composition\n- [`view-no-init-sideeffects`](references\u002Fview-no-init-sideeffects.md) - Never perform work in View init\n\n### 4. Navigation & Coordination (HIGH)\n\n- [`nav-coordinator-pattern`](references\u002Fnav-coordinator-pattern.md) - Every feature has a coordinator owning NavigationStack\n- [`nav-routes-enum`](references\u002Fnav-routes-enum.md) - Define all routes as a Hashable enum\n- [`nav-deeplink-support`](references\u002Fnav-deeplink-support.md) - Coordinators must support URL-based deep linking\n- [`nav-modal-sheets`](references\u002Fnav-modal-sheets.md) - Present modals via coordinator, not inline\n- [`nav-no-navigationlink`](references\u002Fnav-no-navigationlink.md) - Never use NavigationLink(destination:) — use navigationDestination(for:)\n\n### 5. Layer Architecture (HIGH)\n\n- [`layer-dependency-rule`](references\u002Flayer-dependency-rule.md) - Domain layer has zero framework imports\n- [`layer-usecase-protocol`](references\u002Flayer-usecase-protocol.md) - Do not add a use-case layer; keep orchestration in ViewModel + repository protocols\n- [`layer-repository-protocol`](references\u002Flayer-repository-protocol.md) - Repository protocols in Domain, implementations in Data\n- [`layer-model-value-types`](references\u002Flayer-model-value-types.md) - Domain models are structs, never classes\n- [`layer-no-view-repository`](references\u002Flayer-no-view-repository.md) - Views never access repositories directly; ViewModel calls repository protocols\n- [`layer-viewmodel-boundary`](references\u002Flayer-viewmodel-boundary.md) - ViewModels expose display-ready state only\n\n### 6. Dependency Injection (MEDIUM-HIGH)\n\n- [`di-environment-injection`](references\u002Fdi-environment-injection.md) - Inject container-managed protocol dependencies via @Environment\n- [`di-protocol-abstraction`](references\u002Fdi-protocol-abstraction.md) - All injected dependencies are protocol types\n- [`di-container-composition`](references\u002Fdi-container-composition.md) - Compose `DependencyContainer` in App target and expose VM factories\n- [`di-mock-testing`](references\u002Fdi-mock-testing.md) - Every protocol dependency has a mock for testing\n\n### 7. List & Collection Performance (MEDIUM)\n\n- [`list-constant-viewcount`](references\u002Flist-constant-viewcount.md) - ForEach must produce constant view count per element\n- [`list-filter-in-model`](references\u002Flist-filter-in-model.md) - Filter\u002Fsort in ViewModel, never inside ForEach\n- [`list-lazy-stacks`](references\u002Flist-lazy-stacks.md) - Use LazyVStack\u002FLazyHStack for unbounded content\n- [`list-id-keypath`](references\u002Flist-id-keypath.md) - Provide explicit id keyPath — never rely on implicit identity\n\n### 8. Async & Data Flow (MEDIUM)\n\n- [`data-task-modifier`](references\u002Fdata-task-modifier.md) - Use `.task(id:)` as the primary feature data-loading trigger\n- [`data-async-init`](references\u002Fdata-async-init.md) - Never perform async work in init\n- [`data-error-loadable`](references\u002Fdata-error-loadable.md) - Model loading states as enum, not booleans\n- [`data-combine-avoid`](references\u002Fdata-combine-avoid.md) - Prefer async\u002Fawait over Combine for new code\n- [`data-cancellation`](references\u002Fdata-cancellation.md) - Use .task automatic cancellation — never manage Tasks manually\n\n## How to Use\n\nRead individual reference files for detailed explanations and code examples:\n\n- [Section definitions](references\u002F_sections.md) - Category structure and impact levels\n- [Rule template](assets\u002Ftemplates\u002F_template.md) - Template for adding new rules\n\n## Reference Files\n\n| File | Description |\n|------|-------------|\n| [references\u002F_sections.md](references\u002F_sections.md) | Category definitions and ordering |\n| [assets\u002Ftemplates\u002F_template.md](assets\u002Ftemplates\u002F_template.md) | Template for new rules |\n| [metadata.json](metadata.json) | Version and reference information |\n",{},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Fpproenca\u002Fdot-skills\u002Fswift-ui-architect",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":7,"skillName":5,"commands":36,"prompt":46,"zipAvailable":47},[37,40,43],{"tool":38,"command":39},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill swift-ui-architect",{"tool":41,"command":42},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill swift-ui-architect",{"tool":44,"command":45},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill swift-ui-architect","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fpproenca\u002Fdot-skills\u002Fswift-ui-architect\u002FSKILL.md",true,[],[50,64,74,83,89,96],{"skillNo":51,"name":52,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":53,"categories":54,"keywords":60,"publishedAt":22},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[55],{"categoryNo":56,"categoryName":57,"taxonomyType":58,"taxonomyTypeDesc":59},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[61,62,63],"model","model hierarchy","model hierarchy skill",{"skillNo":65,"name":66,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":67,"categories":68,"keywords":70,"publishedAt":22},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[69],{"categoryNo":56,"categoryName":57,"taxonomyType":58,"taxonomyTypeDesc":59},[71,72,73],"MCP","zoom","zoom mcp",{"skillNo":75,"name":76,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":79,"publishedAt":22},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[80,81,82,72],"sdk","zoom apps sdk","apps",{"skillNo":84,"name":85,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":22},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[85],{"skillNo":90,"name":91,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":92,"categories":93,"keywords":95,"publishedAt":22},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[94],{"categoryNo":56,"categoryName":57,"taxonomyType":58,"taxonomyTypeDesc":59},[91],{"skillNo":97,"name":98,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":99,"categories":100,"keywords":101,"publishedAt":22},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[98]]