swift-ui-architect

SwiftUI Modular MVVM-C Architecture

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "swift-ui-architect" with this command: npx skills add pproenca/dot-skills/pproenca-dot-skills-swift-ui-architect

SwiftUI Modular MVVM-C Architecture

Opinionated architecture enforcement for SwiftUI clinic-style apps. This skill aligns to the iOS 26 / 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/O layer.

Mandated Architecture Stack

┌───────────────────────────────────────────────────────────────┐ │ App target: DependencyContainer, Coordinators, Route Shells │ ├───────────────┬───────────────┬───────────────┬──────────────┤ │ Feature* SPM │ Feature* SPM │ Feature* SPM │ Feature* SPM │ │ View + VM │ View + VM │ View + VM │ View + VM │ ├───────────────────────────────────────────────────────────────┤ │ Data SPM: repository impls, remote/local, retry, sync queue │ ├───────────────────────────────────────────────────────────────┤ │ Domain SPM: models, repository protocols, coordinator protocols│ │ and ErrorRouting/AppError │ ├───────────────────────────────────────────────────────────────┤ │ Shared SPMs: DesignSystem, SharedKit │ └───────────────────────────────────────────────────────────────┘

Dependency Rule: Feature modules import Domain

  • DesignSystem only. Features never import Data or other features. App target is the only convergence point.

Clinic Architecture Contract (iOS 26 / Swift 6.2)

All guidance in this skill assumes the clinic modular MVVM-C architecture:

  • Feature modules import Domain
  • DesignSystem only (never Data , never sibling features)
  • App target is the convergence point and owns DependencyContainer , concrete coordinators, and Route Shell wiring

  • Domain stays pure Swift and defines models plus repository, *Coordinating , ErrorRouting , and AppError contracts

  • Data owns SwiftData/network/sync/retry/background I/O and implements Domain protocols

  • Read/write flow defaults to stale-while-revalidate reads and optimistic queued writes

  • ViewModels call repository protocols directly (no default use-case/interactor layer)

When to Apply

Reference these guidelines when:

  • Building or refactoring feature modules under local SPM packages

  • Wiring coordinators, route shells, and dependency container factories

  • Defining Domain protocols for repositories, coordinators, and error routing

  • Enforcing Data-only ownership of networking, persistence, and sync

  • Reviewing stale-while-revalidate reads and optimistic queued writes

Non-Negotiable Constraints (iOS 26 / Swift 6.2)

  • @Observable for ViewModels/coordinators, ObservableObject / @Published never

  • No dedicated use-case/interactor layer: ViewModels call Domain repository protocols directly

  • Coordinator protocols live in Domain; concrete coordinators own NavigationPath in App target

  • Route shells live in App target and own .navigationDestination mapping

  • AppError

  • ErrorRouting drive presentation policy; ViewModels do not hardcode global error UI
  • SwiftData / URLSession / retry / sync queue logic stays in Data package only

Rule Categories by Priority

Priority Category Impact Prefix Rules

1 View Identity & Diffing CRITICAL diff-

6

2 State Architecture CRITICAL state-

7

3 View Composition HIGH view-

6

4 Navigation & Coordination HIGH nav-

5

5 Layer Architecture HIGH layer-

6

6 Dependency Injection MEDIUM-HIGH di-

4

7 List & Collection Performance MEDIUM list-

4

8 Async & Data Flow MEDIUM data-

5

Quick Reference

  1. View Identity & Diffing (CRITICAL)
  • diff-equatable-views

  • Apply @Equatable macro to every SwiftUI view

  • diff-closure-skip

  • Use @SkipEquatable for closure/handler properties

  • diff-reference-types

  • Never store reference types without Equatable conformance

  • diff-identity-stability

  • Use stable O(1) identifiers in ForEach

  • diff-avoid-anyview

  • Never use AnyView — use @ViewBuilder or generics

  • diff-printchanges-debug

  • Use _printChanges() to diagnose unnecessary re-renders

  1. State Architecture (CRITICAL)
  • state-observable-class

  • Use @Observable classes for all ViewModels

  • state-ownership

  • @State for owned data, plain property for injected data

  • state-single-source

  • One source of truth per piece of state

  • state-scoped-observation

  • Leverage @Observable property-level tracking

  • state-binding-minimal

  • Pass @Binding only for two-way data flow

  • state-environment-global

  • Use @Environment for app-wide shared dependencies

  • state-no-published

  • Never use @Published or ObservableObject

  1. View Composition (HIGH)
  • view-body-complexity

  • Maximum 10 nodes in view body

  • view-extract-subviews

  • Extract computed properties/helpers into separate View structs

  • view-no-logic-in-body

  • Zero business logic in body

  • view-minimal-dependencies

  • Pass only needed properties, not entire models

  • view-viewbuilder-composition

  • Use @ViewBuilder for conditional composition

  • view-no-init-sideeffects

  • Never perform work in View init

  1. Navigation & Coordination (HIGH)
  • nav-coordinator-pattern

  • Every feature has a coordinator owning NavigationStack

  • nav-routes-enum

  • Define all routes as a Hashable enum

  • nav-deeplink-support

  • Coordinators must support URL-based deep linking

  • nav-modal-sheets

  • Present modals via coordinator, not inline

  • nav-no-navigationlink

  • Never use NavigationLink(destination:) — use navigationDestination(for:)

  1. Layer Architecture (HIGH)
  • layer-dependency-rule

  • Domain layer has zero framework imports

  • layer-usecase-protocol

  • Do not add a use-case layer; keep orchestration in ViewModel + repository protocols

  • layer-repository-protocol

  • Repository protocols in Domain, implementations in Data

  • layer-model-value-types

  • Domain models are structs, never classes

  • layer-no-view-repository

  • Views never access repositories directly; ViewModel calls repository protocols

  • layer-viewmodel-boundary

  • ViewModels expose display-ready state only

  1. Dependency Injection (MEDIUM-HIGH)
  • di-environment-injection

  • Inject container-managed protocol dependencies via @Environment

  • di-protocol-abstraction

  • All injected dependencies are protocol types

  • di-container-composition

  • Compose DependencyContainer in App target and expose VM factories

  • di-mock-testing

  • Every protocol dependency has a mock for testing

  1. List & Collection Performance (MEDIUM)
  • list-constant-viewcount

  • ForEach must produce constant view count per element

  • list-filter-in-model

  • Filter/sort in ViewModel, never inside ForEach

  • list-lazy-stacks

  • Use LazyVStack/LazyHStack for unbounded content

  • list-id-keypath

  • Provide explicit id keyPath — never rely on implicit identity

  1. Async & Data Flow (MEDIUM)
  • data-task-modifier

  • Use .task(id:) as the primary feature data-loading trigger

  • data-async-init

  • Never perform async work in init

  • data-error-loadable

  • Model loading states as enum, not booleans

  • data-combine-avoid

  • Prefer async/await over Combine for new code

  • data-cancellation

  • Use .task automatic cancellation — never manage Tasks manually

How to Use

Read individual reference files for detailed explanations and code examples:

  • Section definitions - Category structure and impact levels

  • Rule template - Template for adding new rules

Reference Files

File Description

references/_sections.md Category definitions and ordering

assets/templates/_template.md Template for new rules

metadata.json Version and reference information

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

zod

No summary provided by upstream source.

Repository SourceNeeds Review
General

clean-architecture

No summary provided by upstream source.

Repository SourceNeeds Review
General

emilkowal-animations

No summary provided by upstream source.

Repository SourceNeeds Review
General

nuqs

No summary provided by upstream source.

Repository SourceNeeds Review