Expert navigation decisions for iOS/tvOS: when NavigationStack vs Coordinator patterns, NavigationPath state management trade-offs, deep link architecture choices, and tab+navigation coordination strategies. Use when designing app navigation, implementing deep links, or debugging navigation state issues. Trigger keywords: NavigationStack, NavigationPath, deep link, routing, tab bar, navigation, programmatic navigation, universal link, URL scheme, navigation state
View on GitHubKaakati/rails-enterprise-dev
reactree-ios-dev
January 25, 2026
Select agents to install to:
npx add-skill https://github.com/Kaakati/rails-enterprise-dev/blob/main/plugins/reactree-ios-dev/skills/navigation-patterns/SKILL.md -a claude-code --skill navigation-patternsInstallation paths:
.claude/skills/navigation-patterns/# Navigation Patterns — Expert Decisions
Expert decision frameworks for SwiftUI navigation choices. Claude knows NavigationStack syntax — this skill provides judgment calls for architecture decisions and state management trade-offs.
---
## Decision Trees
### Navigation Architecture Selection
```
How complex is your navigation?
├─ Simple (linear flows, 1-3 screens)
│ └─ NavigationStack with inline NavigationLink
│ No Router needed
│
├─ Medium (multiple flows, deep linking required)
│ └─ NavigationStack + Router (ObservableObject)
│ Centralized navigation state
│
└─ Complex (tabs with independent stacks, cross-tab navigation)
└─ Tab Coordinator + per-tab Routers
Each tab maintains own NavigationPath
```
### NavigationPath vs Typed Array
```
Do you need heterogeneous routes?
├─ YES (different types in same stack)
│ └─ NavigationPath (type-erased)
│ path.append(User(...))
│ path.append(Product(...))
│
└─ NO (single route enum)
└─ @State var path: [Route] = []
Type-safe, debuggable, serializable
```
**Rule**: Prefer typed arrays unless you genuinely need mixed types. NavigationPath's type erasure makes debugging harder.
### Deep Link Handling Strategy
```
When does deep link arrive?
├─ App already running (warm start)
│ └─ Direct navigation via Router
│
└─ App launches from deep link (cold start)
└─ Is view hierarchy ready?
├─ YES → Navigate immediately
└─ NO → Queue pending deep link
Handle in root view's .onAppear
```
### Modal vs Push Selection
```
Is the destination a self-contained flow?
├─ YES (can complete/cancel independently)
│ └─ Modal (.sheet or .fullScreenCover)
│ Examples: Settings, Compose, Login
│
└─ NO (part of current navigation hierarchy)
└─ Push (NavigationLink or path.append)
Examples: Detail views, drill-down
```
---
## NEVER Do
### NavigationPath State
**NEVER** store NavigationPath in ViewModel without careful consideration:
```swift
// ❌ ViewModel owns navi