Fixing iOS Universal Links: 'Open in App' Was Opening Safari
Deep links from Google Calendar opened Safari instead of the app. Two issues: missing paths in the Apple App Site Association file and a URL scheme collision with Google OAuth.
When users create walks in PlanPal, they sync to Google Calendar with a deep link: https://planpal-ai.app/open/walk/255. Tapping it should open the app. Instead, Safari opened.
Issue 1: Missing AASA Path
iOS Universal Links require an Apple App Site Association file listing which URL paths open in the app. Mine was missing /open/*:
{
"applinks": {
"details": [{
"appID": "6FUHTSC77Y.com.planpal.mobile",
"paths": ["/app/*", "/subscription/success", "/subscription/cancel"]
}]
}
}
The /open/* paths used by Google Calendar links weren't listed. iOS had no idea these URLs should open in the app. Fix:
'paths' => ['/app/*', '/open/*', '/subscription/success', '/subscription/cancel'],
Issue 2: URL Scheme Collision
Even after fixing the AASA, the planpal:// custom URL scheme wasn't working. Expo's scheme property in app.json was being silently ignored because I had a manual CFBundleURLTypes entry for Google OAuth:
"CFBundleURLTypes": [{
"CFBundleURLSchemes": ["com.googleusercontent.apps.xxx"]
}]
Expo's prebuild logged a warning I initially missed:
» ios: scheme: "ios.infoPlist.CFBundleURLTypes" is set in config.
Ignoring abstract property "scheme": planpal
Fix: add planpal to the existing array instead of relying on the abstract property:
"CFBundleURLSchemes": ["planpal", "com.googleusercontent.apps.xxx"]
Then npx expo prebuild --platform ios --clean to regenerate.
Gotcha: AASA Caching
Apple's CDN caches AASA files for up to 24 hours. After updating, delete and reinstall the app to force a re-fetch -- or wait. URL scheme changes also require a full native rebuild since they're baked into the iOS binary at build time.
Built while working on PlanPal.
Back to danielships ->