Share from Chat (header → share) produces a URL that includes the thread id. Opening it loads that conversation from this device’s encrypted history for the signed-in account (same email / account suffix).
| Environment | Link type | Use exp://? |
|---|---|---|
Release builds (App Store, Play Store, TestFlight, EAS production/preview APK/IPA, expo run:ios / expo run:android without Expo Go) |
Real app link: chatapp://chat/<sessionId> |
No. Never ship or document exp:// for end users. |
| Expo Go + Metro (local development only) | exp://<host>:<port>/--/chat/<sessionId> |
Yes — only here, only while Metro is running. |
The app scheme chatapp comes from scheme in app.json.
Implementation (src/utils/chat-share-link.ts): buildChatDeepLink uses Linking.createURL only in Expo Go (Constants.appOwnership === 'expo'), which yields exp://…/--/chat/<id> for local dev. Development clients (expo run:ios / expo run:android) and release builds use an explicit chatapp://chat/<id> so Android matches iOS (Android was previously generating exp:// in more cases because createURL followed the dev server).
When someone taps Share on the Chat screen in a release (or development client) build, the message contains a URL like:
chatapp://chat/1773997746072-c8284159a20b8
That is the correct format for production. Recipients open it like any app link:
- iOS: tap in Messages, Notes, Mail, etc. — iOS hands the URL to your app if it’s installed.
- Android: same; the intent filter for
chatappopens your app.
No exp:// hostname and no Metro — the link works offline from the user’s perspective (the app still needs to load data from local history after launch).
iOS Simulator (app installed with bun run ios / EAS build, not Expo Go):
xcrun simctl open booted "chatapp://chat/<SESSION_ID>"Android (emulator or device, your package must handle the view intent):
adb shell am start -a android.intent.action.VIEW -d "chatapp://chat/<SESSION_ID>"Replace <SESSION_ID> with an id from Share on a device/simulator, or from History / persisted store (same string as in chatapp://chat/…).
To open https://yourdomain.com/chat/<id> in the app (better for SMS and SEO), you must add Associated Domains (iOS) and App Links (Android) in your Expo config and host the apple-app-site-association / assetlinks files. See Expo linking. Until then, chatapp:// is the supported real link for release.
Use this only when testing with Expo Go and a running Metro bundler. Do not use these URLs in release notes, marketing, or App Store metadata.
- Start Metro:
bun run start - Note the port (often 8081).
bunx uri-scheme open "exp://127.0.0.1:8081/--/chat/<SESSION_ID>" --iosExample:
bunx uri-scheme open "exp://127.0.0.1:8081/--/chat/1773997746072-c8284159a20b8" --iosAndroid emulator (Expo Go + Metro on host):
bunx uri-scheme open "exp://10.0.2.2:8081/--/chat/<SESSION_ID>" --androidThe /--/ segment is required for Expo Go routing to app/chat/[sessionId].tsx.
If you copied a release-style share URL and need to test in Expo Go:
- Take the session id after
chat/(e.g.1773997746072-c8284159a20b8). - Build:
exp://127.0.0.1:<PORT>/--/chat/<SESSION_ID>(use your Metro port). - Run
bunx uri-scheme open "…" --ios(or--androidas above).
This conversion is only for local Expo Go debugging — not for store builds.
| Goal | Command / URL |
|---|---|
| Share in release | Use the in-app Share sheet → chatapp://chat/<id> |
| Open release link in Simulator | xcrun simctl open booted "chatapp://chat/<id>" |
| Open release link on Android | adb shell am start -a android.intent.action.VIEW -d "chatapp://chat/<id>" |
| Test route in Expo Go | bunx uri-scheme open "exp://127.0.0.1:8081/--/chat/<id>" --ios |
- Route:
src/app/chat/[sessionId].tsx - Share URL helper:
src/utils/chat-share-link.ts(buildChatDeepLink— uses your appscheme, so release =chatapp://, notexp://) - Post–sign-in pending id:
src/utils/chat-deeplink-pending.ts