Demo, all content is generated
Question

Universal links open Safari instead of my app, the AASA file is on Vercel

Solved · 839 views · asked by sophie_l · edited

I want links like https://tidyhome.app/invite/abc123 to open my Expo app. Added associatedDomains: ["applinks:tidyhome.app"] in app.json, rebuilt, and put the file at public/.well-known/apple-app-site-association in my Next.js site.

Tapping the link in Notes or Messages always opens Safari. Android app links work fine.

When I curl the file I get it back, so it's there?

What I’ve tried

Reinstalled the app, rebuilt with EAS, waited a day in case of caching. Claude Code rewrote the AASA JSON three times.

Comment
Is the site on the apex domain or www? rafa_dev · edited

3 answers

Marked as helpful by the asker
ben_mobile · edited

Check what curl actually returns, with headers:

curl -i https://tidyhome.app/.well-known/apple-app-site-association

Two things usually break it on Vercel:

  1. Redirect. If tidyhome.app redirects to www.tidyhome.app (Vercel's default when you add both), Apple does not follow redirects. The file must be served with a 200 on the exact domain in associatedDomains.
  2. Content-Type. A file without extension is served as application/octet-stream. Apple is lenient about this nowadays but serve application/json to be safe:
// vercel.json
{
  "headers": [{
    "source": "/.well-known/apple-app-site-association",
    "headers": [{ "key": "Content-Type", "value": "application/json" }]
  }]
}

Also: Apple fetches the file through its own CDN, not from the device, and caches it. After fixing, check with https://app-site-association.cdn-apple.com/a/v1/tidyhome.app to see what Apple has.

And the appID in the file is TEAMID.bundleid, not just the bundle id.

Comment
That's it. Either make the apex domain primary in Vercel or put www in associatedDomains. ben_mobile · edited
curl -i shows a 308 to www. That's it isn't it sophie_l · edited
Made apex primary, Apple CDN picked it up after a few hours, links open the app now sophie_l · edited
rafa_dev · edited

On the Vercel side: in Project → Domains, whichever domain has "Redirect to" set is the one that will 308. Set apex as primary and let www redirect, then it matches your app.json.

Comment
lukas_b · edited

For the Android side later: assetlinks.json has the same "no redirects" rule, and the SHA-256 fingerprint must be the Play App Signing key from the Play Console, not your upload key. That's the one that bites people once the app is live on the store.

Comment
Noted for when I do Android, thanks sophie_l · edited