Navigation infrastructure for SwiftUI

Build journeys. Not workarounds.

Ship complex SwiftUI journeys as one typed, restorable and dynamically composed graph - across features, entry points and Apple devices.

No UIKit coordinator MainActor + Sendable Adopt flow by flow
Three glass navigation paths passing through one precise routing core

From navigation debt to one coherent system.

The difference is not another coordinator. It is one contract that turns every product intent into a valid journey.

Without a navigation core
With NavCorePro
01

Every deep link owns special-case code.

Entry points

Every URL, notification and tap produces the same plan.

02

Features import coordinators and destinations.

Module boundaries

Routes cross features through stable contracts.

03

Tabs, sheets and full-screen flows drift apart.

Presentation

One graph drives every SwiftUI surface.

04

401 challenges and 403 failures restart or strand the flow.

Access control

Authentication resumes. Authorization recovers safely.

Every capability. One navigation system.

Explore the complete NavCore and NavCorePro feature set. Each capability includes its product value, architecture detail and the Swift that makes it real.

Independent navigation paths joining one precise route graph
NavCore

One graph for every surface.

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.

  • Independent history for every tab and presented surface
  • Push, replace, dismiss and rebuild actions in one atomic plan
let order = OrdersRoutes.detailRoute(
    orderId: "123"
)

navigator.apply(NavigationPlan(actions: [
    .selectTab("orders"),
    .replaceTabStack(
        tabId: "orders",
        routes: [order]
    )
]))
A protected route passing through authentication and continuing to its destination
NavCore

Login continues the original intent.

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.

  • The pending NavigationPlan remains part of codable graph state
  • Cancel, register and login outcomes stay explicit
navigator.apply(protectedOrderPlan)

// The configured auth route is presented.
// After successful authentication:
navigator.logInAndContinue()

// The original plan now resumes.
Persisted route panels being restored into a validated safe destination
NavCore

Restore only safe navigation state.

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.

  • Feature-specific restore, discard, migrate and replace policies
  • Unknown or obsolete routes are repaired at the boundary
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)
}
One shared route architecture connected to Apple platform device shells
NavCore

SwiftUI from route to shell.

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.

  • No UIKit navigation coordinator or AnyView route registry
  • Product intent stays shared while every shell remains native
let path = store.bindingForTabStack("orders")
let root = store.rootRoute(for: "orders")

NavigationStack(path: path) {
    destination(for: root)
        .navigationDestination(
            for: RouteDescriptor.self
        ) {
            destination(for: $0)
        }
}
Concurrent route streams passing through a protected deterministic navigation core
NavCore

Safe to call. Easy to test.

Graph mutations stay ordered on MainActor. Routes, plans and persistence are Sendable values, so asynchronous entry points can produce navigation without racing the UI.

  • Test plans and graph mutations without rendering views
  • Small Codable and Hashable values keep the core lightweight
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 legacy navigation structure being replaced module by module with route-driven components
NavCore

Adopt one journey at a time.

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.

  • Start at the highest-cost journey instead of rewriting the app
  • Existing features keep working while route coverage grows
let registry = RouteRegistry()

registry.register(HomeRouteProvider())
registry.register(OrdersRouteProvider())

// Register the next migrated feature.
registry.register(SettingsRouteProvider())
Four feature-owned route rails connecting through one stable navigation contract
NavCorePro

Features own their route boundaries.

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.

  • No global AppRoute enum that grows with the entire product
  • Module boundaries remain intact as journeys cross teams
struct OrdersRouteProvider:
    FeatureRouteProvider {
    let featureId = "orders"

    func canHandle(routeId: String) -> Bool {
        [
            OrdersRoutes.list,
            OrdersRoutes.detail,
            OrdersRoutes.checkout
        ].contains(routeId)
    }
}
A forbidden route being replaced by a feature-owned recovery destination
NavCorePro

403 is a product decision.

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.

  • Recovery happens in the currently active tab or modal stack
  • The reason and affected entity can travel with the route
let orderId =
    route.string("orderId") ?? "unknown"

let forbidden = OrdersRoutes.forbiddenRoute(
    orderId: orderId,
    reason: "Another account owns this order."
)

navigator.failCurrentRoute(with: forbidden)
Codable contextual values travelling inside a route to its destination
NavCorePro

Context travels with the route.

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.

  • Stable JSONValue payloads support nested structured context
  • Metadata remains available for analytics and debugging
let checkout = OrdersRoutes
    .attributedCheckoutRoute(
    orderId: "CAB-481",
    attribution: [
        "source": .string(
            "customersAlsoBought"
        ),
        "campaign": .string("summer_bundle")
    ]
    )

navigator.push(checkout)
One route branching deterministically into four persisted experiment variants
NavCorePro

Experiment with complete journeys.

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.

  • Test sheets against full-screen flows or different tab destinations
  • Keep assignment deterministic across relaunch and restoration
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: []
    )
]))
Runtime policy composing two different tab and feature architectures from one route system
NavCorePro

Compose navigation at runtime.

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.

  • Offer a focused four-tab experience without forking the app
  • Place Settings under Home or a sub-account based on context
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 same route graph adapting from a compact phone layout to a multi-column tablet layout
NavCorePro

One intent, up to three columns.

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.

  • Sidebar, content and detail placement remain shell policy
  • Deep links, auth and restoration use the same state on every width
navigator.apply(NavigationPlan(
    actions: [
        .selectTab("catalog"),
        .replaceTabStack(
            tabId: "catalog",
            routes: [category, product]
        )
    ],
    layoutHint: .preferThreeColumnSplit
))

Choose the navigation layer your product needs.

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

Own the navigation foundation.

One-time commercial licenses for the delivered source snapshot, with no recurring runtime fee.

NavCore

For teams replacing fragmented SwiftUI navigation with one deterministic core.

Essential architecture
12.480 € one-time license
  • Route-driven SwiftUI navigation
  • Deep links and atomic plans
  • 401 authentication continuation
  • Restoration and route tests
  • Shared Apple-platform shell architecture
Request a license

NavCorePro

For modular products that need experiments, rich payloads and adaptive navigation architecture.

Complete product system
24.600 € regular one-time license
  • Everything in NavCore
  • Controlled 403 authorization recovery
  • Associated-value route payloads
  • Feature-owned routes and A/B/C/D tests
  • Dynamic navigation and three-column SplitView
Request a license

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 terms

Let’s map your hardest navigation flow.

Bring a deep link, authentication path or cross-feature journey. We will show how NavCorePro models it.

info@neelixx.com

Submitting opens a prepared email in your default mail app.

Built with care in Hamburg.

Native Apple platform architecture, shaped by real product work.