Skip to content

feat(aasa): add applinks block for Universal Links#11

Merged
variablefate merged 2 commits into
mainfrom
feat/aasa-applinks
May 12, 2026
Merged

feat(aasa): add applinks block for Universal Links#11
variablefate merged 2 commits into
mainfrom
feat/aasa-applinks

Conversation

@variablefate
Copy link
Copy Markdown
Owner

Production prerequisite for variablefate/roadflare-ios#113 (Universal Links). Adds the `applinks` block to the existing `.well-known/apple-app-site-association` so iOS recognizes share URLs as deep-link targets.

Diff

```diff
{

  • "applinks": {
  • "details": [
  •  {
    
  •    "appIDs": ["6Y98438M9X.com.roadflare.RoadFlare"],
    
  •    "components": [
    
  •      { "/": "/share/d/*", "comment": "Driver profile share — opens Add Driver flow" },
    
  •      { "/": "/share/r/*", "comment": "Rider profile share" }
    
  •    ]
    
  •  }
    
  • ]
  • },
    "webcredentials": {
    "apps": [
    "6Y98438M9X.com.roadflare.RoadFlare"
    ]
    }
    }
    ```

Single file, 11 insertions, 0 deletions. `webcredentials` block (Sign in with Apple Passwords) preserved unchanged.

App ID confirmed

Team ID `6Y98438M9X` + Bundle ID `com.roadflare.RoadFlare` matches:

  • The existing `webcredentials.apps` entry in this file (already working in production)
  • `RoadFlare.xcodeproj/project.pbxproj`'s `DEVELOPMENT_TEAM` + `PRODUCT_BUNDLE_IDENTIFIER`
  • The entitlement file `RoadFlare/RoadFlare/RoadFlare.entitlements` (just `applinks:roadflare.app` — Apple resolves the App ID at install time)

Path scope

Path Routes to Notes
`/share/d/*` iOS Add Driver flow Via `AppState.handleIncomingUserActivity` → existing `handleIncomingURL` (npub parser is path-segment-agnostic)
`/share/r/*` iOS Add Driver flow today Reserved scope — when a rider-side iOS surface ships, the routing can fork without a second AASA roundtrip
`/`, `/privacy`, `/terms`, etc. Stays in browser Not in `components` — iOS won't claim these

Serving

GitHub Pages serves `.well-known/` files at the right URL with `Content-Type: application/json` by default (no MIME-type alias needed for the AASA's extensionless name). The repo already has a `.nojekyll` file, so the `.well-known/` directory isn't filtered by Jekyll. Confirmed the existing webcredentials AASA is reachable today, which validates the serving pipeline.

Verification (after merge + DNS propagation)

Apple's CDN caches AASA aggressively. Existing installs may need `Settings → Developer → Associated Domains Development` to re-fetch during testing; new installs pull fresh.

🤖 Generated with Claude Code

Adds the `applinks` block to the existing AASA file so iOS recognizes
`https://roadflare.app/share/d/<npub>` and `/share/r/<npub>` URLs as
deep-link targets for the RoadFlare app (App ID 6Y98438M9X.com.roadflare.RoadFlare).
The existing `webcredentials` integration (Sign in with Apple Passwords)
is preserved unchanged.

This is the production prerequisite for [variablefate/roadflare-ios#113](variablefate/roadflare-ios#113) — the
`applinks:roadflare.app` entitlement is a no-op until Apple's CDN can
fetch a valid AASA from this domain. Once this lands and the next App
Store build ships, tapping a roadflare.app share URL anywhere on iOS
(Messages, Mail, etc.) opens the app directly with the Add Driver sheet
pre-filled, with the share page as the natural fallback when the app
isn't installed.

## Path components

- `/share/d/*` — driver share. Routes to the iOS `Add Driver` flow via
  the existing `AppState.handleIncomingUserActivity` handler.
- `/share/r/*` — rider share. Same routing today (parser is npub-segment-agnostic);
  scope reserved here for when a dedicated rider-side iOS surface ships.

Other paths on roadflare.app (`/`, `/privacy`, `/terms`, etc.) remain
web-only — they are not in the `components` filter and will continue to
open in Safari as expected.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@variablefate
Copy link
Copy Markdown
Owner Author

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

AASA components evaluate first-match-wins in array order. Modern
`components` `*` wildcard semantics are ambiguously documented for
`/` handling, so be explicit: prepend exclude rules for any path
deeper than the single npub segment (e.g. `/share/d/foo/bar`),
which the site doesn't render anyway.

Defensive — the iOS app's `DriverQRCodeParser` already no-ops on
non-npub URLs, so the prior overcapture risk was a graceful silent
failure. This makes the AASA spell out the intended scope instead
of leaning on Apple's wildcard interpretation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@variablefate variablefate merged commit eebc4ba into main May 12, 2026
@variablefate variablefate deleted the feat/aasa-applinks branch May 12, 2026 01:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant