Type-safe SwiftUI navigation built on NavigationStack.
Navi is a lightweight navigation layer for SwiftUI. It adds programmatic routing, deep linking, pop-to-destination, and destination macros to Apple’s NavigationStack — without imposing an application architecture. Pure Swift 6, iOS 16+, zero external dependencies.
Navi is a type-safe navigation library for SwiftUI that builds on NavigationStack. It gives you compile-time safe routes, a clean programmatic API, multi-step deep linking, and pop-to-destination, while staying fully compatible with the native navigation model.
It does not replace NavigationStack. It is a thin typed layer on top of it.
Who is it for?
Developers who want structured, type-safe routes without adopting coordinators, TCA, or a large routing framework. It fits both small projects needing lightweight structure and large, modular codebases wanting a modern NavigationStack-native alternative to legacy coordinators.
| Need | Native NavigationStack |
Navi |
|---|---|---|
| Type-safe routes | Easy to lose with NavigationPath |
Enum + macro, compile-time checked |
| Programmatic navigation | Pass bindings or mutate path manually | push(to:) / pop() |
| Deep linking | Manual path construction | deepLink(to:) |
| Pop to a specific screen | Manual path surgery | @OriginKey + pop(to:) |
iOS 17+ / macOS 14+ (@Observable):
@Observable
final class DemoController: NaviController {
var properties = NaviControllerProperties()
}iOS 16 / macOS 13 (ObservableObject):
@MainActor
final class DemoController: NaviController, ObservableObject {
@Published var properties = NaviControllerProperties()
}@main
struct BasicApp: App {
@State private var controller = DemoController()
var body: some Scene {
WindowGroup {
NavigationStack(path: $controller.properties.path) {
HomeView()
}
}
}
}@DestinationRepresentable
enum HomeDestinations {
case settings
case profile
}struct HomeView: View {
var body: some View {
content
.navigationDestination(
for: HomeDestinations.self,
destination: destinationView
)
}
@ViewBuilder
private func destinationView(for destination: HomeDestinations) -> some View {
switch destination {
case .settings: SettingsView()
case .profile: ProfileView()
}
}
}
// Navigate
controller.push(to: HomeDestinations.settings)
controller.pop()controller.deepLink(to: [
HomeDestinations.settings,
SettingsDestinations.notifications,
NotificationsDestinations.emailNotifications
])@DestinationRepresentable
enum HomeDestinations {
@OriginKey case settings
case profile
}
controller.pop(to: HomeDestinations.Origins.settings)| Example | Platform | Status |
|---|---|---|
Examples/Basic |
iOS 17+ / macOS 14+ | ✅ |
Examples/Basic-iOS16 |
iOS 16 / macOS 13 | ✅ |
Examples/Coordinators |
iOS 16 / macOS 13 | ✅ |
| Platform | Minimum |
|---|---|
| iOS | 16.0+ |
| macOS | 13.0+ |
| Swift | 6.0+ (tools 6.3) |
| Xcode | 16.0+ |
- iOS 17+ / macOS 14+ → prefer
@Observable(Examples/Basic) - iOS 16 / macOS 13 → use
ObservableObject(Examples/Basic-iOS16)
Xcode: File → Add Packages… → https://github.com/SwiftMates/Navi
Package.swift:
dependencies: [
.package(url: "https://github.com/SwiftMates/Navi.git", from: "1.0.0")
]What is Navi?
A type-safe navigation layer for SwiftUI built on NavigationStack. It adds programmatic navigation, deep linking, and pop-to-destination without architecture lock-in.
Does Navi replace NavigationStack?
No. It works with NavigationStack.
Is Navi a SwiftUI router?
Yes — a lightweight, type-safe one. NavigationStack remains the underlying container.
Does it require a specific architecture?
No. Works with MVVM, TCA, coordinators, or none.
Does it support deep linking and programmatic navigation?
Yes. Use deepLink(to:), push(to:), pop(), and pop(to:).
How do I pop to a specific screen?
Mark the destination with @OriginKey, then call controller.pop(to: Destination.Origins.yourCase).
Does it support iOS 16 and Swift 6?
Yes. iOS 16+ / macOS 13+, designed for Swift 6.
Contributions are welcome.
- Fork the repository
- Create a branch from
develop:git checkout develop git checkout -b feature/your-feature
- Make your changes
- Run
swift test(and example builds if relevant) - Open a Pull Request against
develop
If you find Navi helpful, please consider:
- Giving it a ⭐ on GitHub
- Sharing it with fellow developers
- Contributing to its development
MIT. See LICENSE.
Created by SwiftMates.
