Every deep link owns special-case code.
Every URL, notification and tap produces the same plan.
Navigation infrastructure for SwiftUI
Ship complex SwiftUI journeys as one typed, restorable and dynamically composed graph - across features, entry points and Apple devices.
The difference is not another coordinator. It is one contract that turns every product intent into a valid journey.
Every deep link owns special-case code.
Every URL, notification and tap produces the same plan.
Features import coordinators and destinations.
Routes cross features through stable contracts.
Tabs, sheets and full-screen flows drift apart.
One graph drives every SwiftUI surface.
401 challenges and 403 failures restart or strand the flow.
Authentication resumes. Authorization recovers safely.
Tabs, stacks, sheets, full-screen flows and restoration share the same deterministic model.
Navigation becomes inspectable application state instead of hidden view-local behavior.
URLs, notifications and in-app actions produce the same NavigationPlan.
Keep the original destination, complete login, then resume exactly where the user intended.
Plans mutate the active graph directly, removing presenter lookup, timing guesses and dispatch delays.
Keep product intent consistent while each SwiftUI shell renders the right experience for its device.
Dynamic navigation architecture
Stop hard-coding the app shell. NavCorePro lets runtime policy compose tabs, entry points and feature placement from user needs, entitlements, experiments or incoming context.
Reduce viewport pressure without forking the app. The same Settings route can live under Home for one audience and under a sub-account menu for another.
Age, accessibility needs, account type, permissions or product maturity.
Deep link, notification, campaign, advertising banner or partner journey.
Market, entitlements, feature flags and architecture-level experiments.
Let future models select the most useful route, tab set or feature placement.
Dynamic routing turns navigation from implementation detail into a product and growth capability.
Personalize without duplicating features Experiment beyond individual screens Keep every outcome deterministic and testableNavCorePro keeps the difficult moments inside the same route-driven system, from a forbidden destination to a restored cold start.
Small, codable values describe complete journeys. The same APIs drive taps, deep links, authentication, recovery and experiments.
Select a tab and rebuild its route stack as one deterministic intent.
let order = RouteDescriptor(
routeId: "orders.detail",
featureId: "orders",
payload: ["orderId": .string("123")]
)
navigator.apply(NavigationPlan(actions: [
.selectTab("orders"),
.replaceTabStack(
tabId: "orders",
routes: [order]
)
]))
Replace the active destination with a feature-owned recovery route without starting a login loop.
let forbidden = OrdersRoutes.forbiddenRoute(
orderId: route.string("orderId") ?? "unknown",
reason: "Another account owns this order."
)
navigator.failCurrentRoute(with: forbidden)
Persist the variant and let the plan choose presentation and layout.
let offer = RouteDescriptor(
routeId: "offers.detail",
featureId: "offers",
metadata: ["experiment.offer": variant]
)
navigator.apply(NavigationPlan(
actions: [.present(
kind: variant == "d" ? .fullScreen : .sheet,
rootRoute: offer,
stack: []
)],
layoutHint: .preferThreeColumnSplit
))
Built for real app architecture
Each feature owns its routes, validation and destinations. The app shell renders one shared graph, so cross-feature flows no longer leak coordination code into views.
Start with one route, flow or tab. NavCorePro is designed to coexist with existing navigation while the architecture moves forward.
Map one existing product flow to route descriptors and a navigation plan.
Let the shared store drive the selected tab, stacks and presented surfaces.
Move feature by feature, keeping delivery risk and migration scope controlled.
Explore the complete NavCore and NavCorePro feature set. Each capability includes its product value, architecture detail and the Swift that makes it real.
Tabs, independent stacks, sheets and full-screen journeys become codable application state. Cross-tab changes and nested modal stacks are applied as one ordered intent instead of a chain of presenters.
let order = OrdersRoutes.detailRoute(
orderId: "123"
)
navigator.apply(NavigationPlan(actions: [
.selectTab("orders"),
.replaceTabStack(
tabId: "orders",
routes: [order]
)
]))
URLs, notifications, widgets and in-app actions all resolve to the same NavigationPlan. Authentication, validation, presentation and analytics stay on one route pipeline.
// navcore://orders/123
let order = OrdersRoutes.detailRoute(
orderId: "123"
)
func parse(_ url: URL) -> NavigationPlan? {
NavigationPlan(actions: [
.selectTab("orders"),
.replaceTabStack(
tabId: "orders",
routes: [order]
)
])
}
A protected plan pauses while authentication is presented. After login, the user lands on the requested order, checkout or campaign destination instead of being dropped at Home.
navigator.apply(protectedOrderPlan)
// The configured auth route is presented.
// After successful authentication:
navigator.logInAndContinue()
// The original plan now resumes.
The graph survives relaunches and cold starts, but each feature controls what may return. Unsafe checkout, payment or one-time authorization routes can be discarded, migrated or replaced before rendering.
func restorationPolicy(
for route: RouteDescriptor
) -> RouteRestorationPolicy {
let isCheckout =
route.routeId == OrdersRoutes.checkout
guard isCheckout else {
return .restore
}
let orderId =
route.string("orderId") ?? "unknown"
let detail = OrdersRoutes.detailRoute(
orderId: orderId
)
return .replaceWith(detail)
}
NavigationStack, NavigationSplitView, sheets and full-screen covers render the graph directly. Shared routes and plans can drive device-native shells for iPhone, iPad, Mac, Apple Watch, Apple Vision Pro and Apple TV.
let path = store.bindingForTabStack("orders")
let root = store.rootRoute(for: "orders")
NavigationStack(path: path) {
destination(for: root)
.navigationDestination(
for: RouteDescriptor.self
) {
destination(for: $0)
}
}
Graph mutations stay ordered on MainActor. Routes, plans and persistence are Sendable values, so asynchronous entry points can produce navigation without racing the UI.
let order = OrdersRoutes.detailRoute(
orderId: "123"
)
let plan = NavigationPlan(actions: [
.selectTab("orders"),
.push(order)
])
await MainActor.run {
navigator.apply(plan)
}
XCTAssertEqual(
store.state.selectedTabId,
"orders"
)
A product does not need to stop shipping while navigation changes underneath it. Wrap one screen, flow or tab, bridge it into the existing shell and retire coordination code in controlled steps.
let registry = RouteRegistry()
registry.register(HomeRouteProvider())
registry.register(OrdersRouteProvider())
// Register the next migrated feature.
registry.register(SettingsRouteProvider())
Every package owns its route IDs, validation, migration, authentication policy and destinations. Cross-feature journeys use stable route contracts instead of importing coordinators or feature views.
struct OrdersRouteProvider:
FeatureRouteProvider {
let featureId = "orders"
func canHandle(routeId: String) -> Bool {
[
OrdersRoutes.list,
OrdersRoutes.detail,
OrdersRoutes.checkout
].contains(routeId)
}
}
Authentication and authorization are different flows. When an authenticated user cannot access a resource, replace the blocked screen with a relevant feature-owned route instead of reopening login.
let orderId =
route.string("orderId") ?? "unknown"
let forbidden = OrdersRoutes.forbiddenRoute(
orderId: orderId,
reason: "Another account owns this order."
)
navigator.failCurrentRoute(with: forbidden)
Associated values such as IDs, source components, campaign attribution and experiment assignments remain codable. They survive tab changes, authentication, persistence and restoration without transporting complete models.
let checkout = OrdersRoutes
.attributedCheckoutRoute(
orderId: "CAB-481",
attribution: [
"source": .string(
"customersAlsoBought"
),
"campaign": .string("summer_bundle")
]
)
navigator.push(checkout)
A/B/C/D tests can change presentation, entry point, stack shape or feature placement. Persist the chosen variant on the route so analytics, debugging and restored sessions agree on what the user saw.
let presentation: PresentationKind =
variant == "d" ? .fullScreen : .sheet
let offer = RouteDescriptor(
routeId: "offers.detail",
featureId: "offers",
metadata: ["experiment.offer": variant]
)
navigator.apply(NavigationPlan(actions: [
.present(
kind: presentation,
rootRoute: offer,
stack: []
)
]))
Stop hard-coding five tabs for every user. Runtime policy can select tabs, entry points and feature placement from role, age, accessibility needs, entitlement, market, campaign, deep link or future ML decisions.
let tabs = user.needsFocusedNavigation
? [home, orders, account, help]
: [home, search, orders, account, settings]
let configuration = NavigationConfiguration(
defaultSelectedTabId: tabs[0].tabId,
defaultTabs: tabs,
authenticationRoute: RouteDescriptor(
routeId: AuthRoutes.login,
featureId: AuthRoutes.featureId
)
)
The route graph stays independent from the renderer. A plan can prefer a three-column NavigationSplitView on iPad while compact widths present the same logical journey through a native detail-first stack.
navigator.apply(NavigationPlan(
actions: [
.selectTab("catalog"),
.replaceTabStack(
tabId: "catalog",
routes: [category, product]
)
],
layoutHint: .preferThreeColumnSplit
))
NavCore establishes a deterministic SwiftUI foundation. NavCorePro adds the routing capabilities needed for modular products, experiments and adaptive app architectures.
| Capability | NavCore Essential | NavCorePro Advanced |
|---|---|---|
| Navigation foundation | ||
| SwiftUI route graph for tabs, stacks, sheets and full-screen flows | Included | Included |
| Deep links and atomic NavigationPlans | Included | Included |
| 401 authentication continuation | Included | Included |
| Restorable navigation state and deterministic route tests | Included | Included |
| Product architecture | ||
| Feature-owned route providers and cross-feature contracts | Not included | Included |
| Controlled 403 authorization recovery | Not included | Included |
| Associated-value route payloads with codable context | Not included | Included |
| A/B/C/D routing with persisted experiment variants | Not included | Included |
| Dynamic tabs, entry points and feature placement | Not included | Included |
| Adaptive three-column iPad SplitView architecture | Not included | Included |
| Shared architecture across Apple platform shells | Included | Included |
One-time commercial licenses for the delivered source snapshot, with no recurring runtime fee.
For teams replacing fragmented SwiftUI navigation with one deterministic core.
For modular products that need experiments, rich payloads and adaptive navigation architecture.
Prices are net, plus applicable VAT, and apply per legal entity to the delivered version. Updates, support and custom integration are available separately.
Read commercial and license termsBring a deep link, authentication path or cross-feature journey. We will show how NavCorePro models it.
info@neelixx.comNative Apple platform architecture, shaped by real product work.