Skip to content

relaxfinger/URLRouter

Repository files navigation

URLRouter

🇨🇳 中文 · Documentation · Blog tutorial

A SwiftUI routing foundation for modular Apple-platform apps.

iOS 17+ · macOS 14+ · tvOS 17+ · watchOS 10+ · Swift 6

URLRouter gives an app one predictable front door for navigation. A button, a push notification, a Universal Link, or another Feature can all submit the same HTTPS URL. URLRouter validates it, lets the owning Feature resolve it, and updates SwiftUI navigation in the presentation style declared by the URL.

It is useful once an app has more than a few screens: callers no longer need to know another Feature's View type, initializer, or navigation container. They only use that Feature's documented URL contract.

Choose your path

If you want to… Start here
Open one page from a SwiftUI button Five-minute quick start
Add Universal Links and a modular Feature Package Getting started guide
Understand ownership and URL contracts Architecture guide
Add remote switches, queueing, telemetry, or CI checks Production governance
Follow a complete beginner-friendly walkthrough Technical blog

The README is deliberately short. The linked guides contain the rationale, production details, and Chinese counterparts without forcing every app to adopt advanced features on day one.

Install

In Xcode, choose File → Add Package Dependencies… and add:

https://github.com/relaxfinger/URLRouter.git

Add URLRouter to the App target and to any Feature Package that declares a RouteModule.

dependencies: [
    .package(url: "https://github.com/relaxfinger/URLRouter.git", from: "2.4.7")
]

URLRouterPolicyProvider is an optional product from the same package. Add it only when the App needs a cache-first remote route-policy lifecycle. Feature packages should normally depend on URLRouter only.

.product(name: "URLRouter", package: "URLRouter")
// App-shell target only, when remote policy is needed:
.product(name: "URLRouterPolicyProvider", package: "URLRouter")

Five-minute quick start

1. Let a Feature own its paths and destination views

import SwiftUI
import URLRouter

enum ArticleFeature {
    static let module = RouteModule(
        id: "articles",
        resolve: { link in
            guard case ["articles", let id] = link.pathComponents, !id.isEmpty else {
                return nil
            }
            return ModuleRoute(
                moduleID: "articles",
                routeID: "detail",
                parameters: ["id": id]
            )
        },
        destination: { route in
            guard route.routeID == "detail", let id = route.parameters["id"] else {
                return nil
            }
            return AnyView(ArticleDetailView(articleID: id))
        }
    )
}

Returning nil from resolve means “this URL is not mine.” A Feature can own many URLs; keep their parsing and destination creation together.

2. Register Feature modules once at the scene root

import SwiftUI
import URLRouter

@main
struct CompanyApp: App {
    @State private var router = ModuleRouter()

    private let registry = ModuleRouteRegistry(modules: [ArticleFeature.module])

    var body: some Scene {
        WindowGroup {
            RouterHost(router: router) {
                ContentView()
            } destination: { route in
                registry.destination(for: route)
            }
            .moduleLinkRouting(
                router: router,
                registry: registry,
                allowedHosts: ["example.com"]
            )
        }
    }
}

Install RouterHost and moduleLinkRouting exactly once per scene. Keep one ModuleRouter per window so multi-window navigation stays independent.

3. Navigate with the standard SwiftUI API

struct ArticleRow: View {
    @Environment(\.openURL) private var openURL
    let articleID: String

    var body: some View {
        Button("Read article") {
            openURL(URL(string: "https://example.com/articles/\(articleID)?presentation=push&version=1")!)
        }
    }
}

The URL is the public contract:

https://example.com/articles/42?presentation=push&version=1

presentation is required and may be push, tab, sheet, or fullScreenCover. Start with one route like this. Then follow the getting-started guide to use URL builders, Universal Links, tabs, and a versioned route contract safely.

When to add the optional production features

Do not build every feature at once.

Need Add
Web links should open the same route as the app Universal Links
A Feature or all routing must be remotely paused URLRouterPolicyProvider and a ModuleRoutePolicyStore
A notification, link, and button can arrive together One ModuleRouteCoordinator per scene
Support needs to explain why a link failed ModuleRouteObservability
Marketing or web clients depend on published links RouteContracts.json and contract CI

These are opt-in. URLRouter does not choose your network client, authentication flow, remote-config vendor, analytics vendor, or backend. The App owns those decisions; the package provides focused routing seams.

Demo and verification

URLRouterDemo is an iOS 17+ reference app. It shows local Feature Packages, all four presentation styles, cross-package navigation, a cache-first policy lifecycle, telemetry, and coordinated concurrent routes.

swift test
swift Scripts/validate_route_contract.swift RouteContracts.json

The core library and RouterHost support all four listed Apple platforms. On macOS, SwiftUI presents a fullScreenCover route as a sheet because macOS does not provide fullScreenCover.

Project layout

Sources/URLRouter/                 # core routing library
Sources/URLRouterPolicyProvider/   # optional policy-refresh product
Tests/                             # SwiftPM unit tests
Features/                          # local Feature-package examples
URLRouterDemo/                     # executable iOS reference app
docs/                              # task-focused documentation

License and community

URLRouter is available under the MIT License. Before contributing, read CONTRIBUTING.md. For support, security reports, and the maintenance policy, see SUPPORT.md, SECURITY.md, and MAINTENANCE.md.

About

SwiftUI URL routing for modular Apple apps, with Universal Links, route policy, observability, and safe concurrent navigation.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors