---
title: modern-swift-dev/pathways-swift
framework: Swift Package Catalog
role: article
path: packages/modern-swift-dev/pathways-swift
---

# modern-swift-dev/pathways-swift

Pathways is a small, dependency-free Swift package for defining typed deep-link paths, converting those paths to and from Codable values, and dispatching incoming URLs to main-actor handlers.

## Features

- Strongly typed URL path parameters through Swift `Codable` - Encoding models into percent-escaped URL paths - Decoding URL paths into application-defined models - Typed and path-only routing handlers - Optional exact-host filtering - Query parameter delivery to handlers - Experimental fragment-route and fragment-parameter support - Swift 6 concurrency annotations and main-actor handler execution - No third-party runtime dependencies

## Requirements

- Swift 6.0 or newer - macOS 15 or newer - iOS 18 or newer - tvOS 18 or newer - watchOS 10 or newer - visionOS 1 or newer

## Installation

In Xcode, use **File > Add Package Dependencies** and enter:

```text https://github.com/modern-swift-dev/pathways-swift.git ```

Or add the package in `Package.swift`:

```swift dependencies: [     .package(         url: "https://github.com/modern-swift-dev/pathways-swift.git",         from: "1.0.0"     ) ] ```

Add `Pathways` to the target that uses it:

```swift .target(     name: "YourTarget",     dependencies: [         .product(name: "Pathways", package: "pathways-swift")     ] ) ```

## Quick start

### 1. Define a route

Adopt `Pathway` and declare a path pattern. Placeholder names begin with `:` and correspond to Codable keys.

```swift import Pathways

struct ProductRoute: Pathway {     static let pattern = "/products/:productID"

let productID: Int } ```

### 2. Encode and decode

```swift import Foundation import Pathways

let path = try PathwayEncoder.shared.encode(ProductRoute(productID: 42)) // /products/42

let url = URL(string: "https://example.com/products/42")! let route = try PathwayDecoder.shared.decode(ProductRoute.self, from: url) // route.productID == 42 ```

### 3. Register a handler

```swift var router = Pathways()

router.register(host: "example.com", ProductRoute.self) { route, query in     navigateToProduct(id: route.productID, campaign: query["campaign"]) }

let handled = try router.handle(url) ```

The handler executes on the main actor. `handle(_:)` returns `false` when no route matches and throws when a matched typed route cannot be decoded.

## Route patterns

Patterns contain literal path components and named placeholders:

```text /teams/:teamID/members/:memberID ```

The model stays flat and each placeholder maps to a Codable key:

```swift struct MemberRoute: Pathway {     static let pattern = "/teams/:team_id/members/:member_id"

let teamID: Int     let memberID: UUID

enum CodingKeys: String, CodingKey {         case teamID = "team_id"         case memberID = "member_id"     } } ```

Supported scalar values include strings, booleans, integer and floating-point types, raw-value Codable enums, UUIDs, and ISO 8601 dates. Nested values and collections are not supported.

## Path-only routing

Register a path directly when no typed path values are needed:

```swift router.register(host: "example.com", path: "/settings") { query in     navigateToSettings(tab: query["tab"]) } ```

Path-only registrations use prefix matching by default, so `/settings` also matches `/settings/privacy`. Pass `matching: .exact` when the complete normalized path must match:

```swift router.register(host: "example.com", path: "/settings", matching: .exact) { query in     navigateToSettings(tab: query["tab"]) } ```

Exact matching also applies to typed routes. Each `:` placeholder matches one non-empty path component.

## Query and fragment parameters

Handler dictionaries contain standard query parameters by default. For URLs that encode a route and parameters in the fragment, opt in per registration:

```swift router.register(     host: "example.com",     path: "/callback/#complete",     supportFragmentParams: true ) { parameters in     completeSignIn(token: parameters["token"]) } ```

This supports a URL such as `https://example.com/callback#complete?token=abc`. Fragment handling is experimental.

## Examples

The [Examples](Examples/README.md) directory contains standalone packages:

- [CodableRoutes](Examples/CodableRoutes/README.md) demonstrates model encoding and decoding. - [RoutingCenter](Examples/RoutingCenter/README.md) demonstrates host-aware dispatch and query parameters.

Each can be run independently with `swift run` from its directory.

## Documentation

- [Guide](https://modern-swift-dev.github.io/docs/pathways-swift/) - [Examples](https://modern-swift-dev.github.io/docs/pathways-swift/examples/) - [API documentation](https://modern-swift-dev.github.io/docs/pathways-swift/documentation/pathways/)

## Contributing

Guides and examples live in [Documentation/Site](Documentation/Site). The [central documentation repository](https://github.com/modern-swift-dev/docs) owns the shared Astro theme, builds the guides and DocC API reference, and publishes them daily. For local builds and previews, follow the [docs README](https://github.com/modern-swift-dev/docs/blob/main/README.md).

See [CONTRIBUTING.md](CONTRIBUTING.md) for development and maintenance instructions.

## License

Pathways is available under the MIT License. See [LICENSE](LICENSE).

## Package Metadata

Repository: modern-swift-dev/pathways-swift

Default branch: main

README: README.md
