Surfaced while gating async-digital-site#546, which proposes a public repo description naming Universal Links as a supported input. The capability is real but thinner than that claim implies, and nothing here is tested.
Measured on main @ depth-1 clone, 2026-08-30
URLPathRouter carries exactly one scheme: public let scheme: String, set once in init(scheme:routes:) (Sources/Iris/URLRoute.swift:142-148).
parse(_:) hard-rejects anything else: guard url.scheme == scheme else { return nil } (URLRoute.swift:153).
URLPattern takes its host from the first path segment of the pattern string: self.host = segments.first ?? "" (URLRoute.swift:73).
grep -rn https Sources/ returns zero hits.
- The only router test constructs
scheme: "demo" (Tests/IrisTests/URLPathRouterTests.swift:18).
What that means in practice
Universal Links are routable — URLPathRouter(scheme: "https", routes: [URLPattern("myapp.com/profile/:id")]) works. Three consequences follow that a reader of a one-line description would not expect:
- One router serves one scheme. An app accepting both
myapp://profile/1 and https://myapp.com/profile/1 needs two URLPathRouter instances and its own dispatch between them. Nothing in the package composes them.
- Every Universal Link pattern must repeat the domain as its first segment, because pattern host is segment zero. A custom-scheme pattern reads
profile/:id; the Universal Link equivalent reads myapp.com/profile/:id, and the two cannot share a route table.
- It is untested and undocumented for
https. AGENTS.md names .onOpenURL as "the standard SwiftUI universal-link / custom-scheme entry point", which is true of the modifier but says nothing about the router behind it.
What breaks if this is never fixed
An adopter who picks the package up because its description promises Universal Links writes one router, gets nil from every https URL, and has to read the source to find the scheme guard. That is the friction the case-study series exists to argue we design out.
Options, not a prescription
- Document the two-router pattern in
AGENTS.md and add an https test. Cheapest, makes the existing behaviour honest.
- Let
URLPathRouter hold a set of accepted schemes, keeping host matching as-is.
- Separate scheme from host in
URLPattern so one table serves both.
Pick before the public description claims Universal Links as a headline capability.
Surfaced while gating async-digital-site#546, which proposes a public repo description naming Universal Links as a supported input. The capability is real but thinner than that claim implies, and nothing here is tested.
Measured on
main@ depth-1 clone, 2026-08-30URLPathRoutercarries exactly one scheme:public let scheme: String, set once ininit(scheme:routes:)(Sources/Iris/URLRoute.swift:142-148).parse(_:)hard-rejects anything else:guard url.scheme == scheme else { return nil }(URLRoute.swift:153).URLPatterntakes its host from the first path segment of the pattern string:self.host = segments.first ?? ""(URLRoute.swift:73).grep -rn https Sources/returns zero hits.scheme: "demo"(Tests/IrisTests/URLPathRouterTests.swift:18).What that means in practice
Universal Links are routable —
URLPathRouter(scheme: "https", routes: [URLPattern("myapp.com/profile/:id")])works. Three consequences follow that a reader of a one-line description would not expect:myapp://profile/1andhttps://myapp.com/profile/1needs twoURLPathRouterinstances and its own dispatch between them. Nothing in the package composes them.profile/:id; the Universal Link equivalent readsmyapp.com/profile/:id, and the two cannot share a route table.https.AGENTS.mdnames.onOpenURLas "the standard SwiftUI universal-link / custom-scheme entry point", which is true of the modifier but says nothing about the router behind it.What breaks if this is never fixed
An adopter who picks the package up because its description promises Universal Links writes one router, gets
nilfrom every https URL, and has to read the source to find the scheme guard. That is the friction the case-study series exists to argue we design out.Options, not a prescription
AGENTS.mdand add an https test. Cheapest, makes the existing behaviour honest.URLPathRouterhold a set of accepted schemes, keeping host matching as-is.URLPatternso one table serves both.Pick before the public description claims Universal Links as a headline capability.