You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(mobile,web): copied thread links open the mobile app - #29815
Stacked on https://git.cafe/pingdotgg/t3code/pulls/26290. On a phone, a copied thread link (https://app.t3.codes/threads/<env>/<thread>) opened the browser, which then offered the app. With T3 Code installed, the link now opens the thread in the app directly. Both PRs already change native code, so they can ship in one release.
How it works
app.t3.codes claims its thread links.apps/web/public/.well-known/ gets apple-app-site-association.json and assetlinks.json, both scoped to /threads/* and listing the production, preview, and dev apps. Apple fetches the file without an extension, so vercel.ts rewrites /.well-known/apple-app-site-association to the .json file, which Vercel serves as application/json. A rewrite is not a redirect, which Apple refuses. On app.t3.codes, requests go through to the latest channel's deployment, which serves both files.
The apps claim app.t3.codes. iOS adds applinks:app.t3.codes next to the existing Clerk domains. Android adds a verified (autoVerify) intent filter for https://app.t3.codes/threads/.
The app routes the link.https://app.t3.codes is a linking prefix, so /threads/<env>/<thread> reaches the existing threads/:environmentId/:threadId route that t3code://threads/… already uses, including ?prompt= handling. Other app.t3.codes paths are not claimed and stay in the browser.
Identifiers. The Apple team ID (ARK85ZXQ4Z) and bundle IDs come from app.config.ts. The Android SHA-256 signing fingerprints are copied from https://clerk.t3.codes/.well-known/assetlinks.json, which already verifies these apps for passkeys. app.config.test.ts checks that every variant's identifiers appear in both files and that its native config claims the hosted app's host.
Desktop. No change. There is no cross-browser way for a desktop app installed outside a store to claim https links, so the chooser and Remember my choice stay the way there.
Shipping order
The files must be live on app.t3.codes before the new mobile builds reach users. Android verifies autoVerify filters at install time, and iOS fetches through Apple's CDN, which caches. After the web deploy, check https://app-site-association.cdn-apple.com/a/v1/app.t3.codes and Google's Digital Asset Links API for each package.
With the app installed, a phone skips the chooser. Someone not connected to the thread's machine lands in the app's existing "Thread on another machine" handling instead of the chooser. They can still open the link in the browser (long-press on iOS) to get the chooser.
Testing
apps/mobile/app.config.test.ts: each variant's bundle ID and package appear in the two files, and its config claims applinks:app.t3.codes and the /threads/ intent filter. Dropping the dev app from the Apple file fails the development row.
vp run check:changed: format, lint, knip, typecheck (34 packages), tests (22 files), and the React compiler check pass.
Not run: a native build, a device install, or a deploy. Universal links and app links can only be verified against the deployed files with a signed build.
github-actionsBot
added
vouch:trusted
PR author is trusted by repo permissions or the VOUCHED list.
size:M
30-99 changed lines (additions + deletions).
📱 Native Change
Changes the native fingerprint; merging blocks production OTAs until a new store build ships.
labels
Nov 3, 2026
Macroscope's review found this PR requires human approval — Copied thread links now open the installed mobile app directly instead of showing the browser chooser. Human review is needed to confirm this default destination change, including the experience when the app is not connected to the thread's machine.
No code changes detected at b3b6216. Prior analysis still applies.
You can add or adjust custom eligibility rules. Learn more.
Reviewing files that changed from the base of the PR and between 559dbcd and b3b6216.
You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.
Use the checkbox below for a quick retry:
Trigger review
No actionable comments were generated in the recent review.
Walkthrough
The mobile app and hosted site now associate HTTPS links on app.t3.codes under /threads/ with the app. React Navigation recognizes the hosted URL, link filtering checks route text without query or fragment content, and thread-sharing instructions describe how links open in different contexts.
Changes: Thread link handling
Layer / File(s)
Summary
Platform association and link configuration apps/web/public/.well-known/*, apps/web/vercel.ts, apps/mobile/app.config.ts, apps/mobile/app.config.test.ts
The site publishes iOS and Android associations for the production, preview, and development app identifiers. Mobile configuration adds iOS and verified Android handling for HTTPS /threads/ links on app.t3.codes. Tests check the configured links and app identifiers against the association files.
App navigation and route filtering apps/mobile/src/App.tsx, apps/mobile/src/lib/appLinking.ts, apps/mobile/src/lib/appLinking.test.ts, docs/user/prompt-links.md
React Navigation adds the hosted app URL as a link prefix. shouldHandleAppLink checks route text before query and fragment markers; its test includes an HTTPS URL with matching marker strings in the query. The instructions describe app and non-app link behavior.
sequenceDiagram
actor User
participant OS as Mobile operating system
participant Site as Hosted site
participant App as T3 Code app
participant Navigation as React Navigation
User->>OS: Open HTTPS thread link
OS->>Site: Request platform association
Site-->>OS: Return app association
OS->>App: Open matching thread link
App->>Navigation: Match hosted URL prefix
Verify the deployed Apple association endpoint before relying on iOS users opening thread links directly in the app.
Pre-merge checks: 4
Check name
Status
Explanation
Title check
The title clearly and concisely describes the primary change: copied thread links now open the mobile app.
Description check
The description provides the problem, implementation details, scope, shipping considerations, behavior, and focused verification results. It does not use the template headings exactly and does not exp…
Linked Issues check
Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check
Check skipped because no linked issues were found for this pull request.
Full details: Description check
Explanation
The description provides the problem, implementation details, scope, shipping considerations, behavior, and focused verification results. It does not use the template headings exactly and does not explicitly document maintainer approval, but it is otherwise sufficiently complete.
Finishing Touches
Generate docstrings
Commit to this branch
Create a new PR
Generate unit tests (beta)
Commit to this branch
Create a new PR
Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
CodeRabbit Verify
Run CodeRabbit Verify to test the changes in this pull request.
Reviewing files that changed from the base of the PR and between 6c91076 and 301aaab.
Files selected for processing: 2
apps/mobile/src/lib/appLinking.test.ts
apps/mobile/src/lib/appLinking.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 1 remain after this review.
…open
The lifecycle filter matched "expo-development-client" and "://expo-sharing"
anywhere in the URL, so a link such as
https://app.t3.codes/threads/env/thread?prompt=Fix%20expo-development-client
opened the app without navigating. Match them in the route only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (Running the fork's tests in apps/mobile)
Failing check: Running the fork's tests in apps/mobile
The failing check was "Running the fork's tests in apps/mobile". Four cases in `apps/mobile/app.config.test.ts` failed, all named "keeps the iOS and Android identifiers…". The test errored at line 42 because the app config's iOS `associatedDomains` was `undefined`.
**Why:** Upstream pingdotgg#29815 (b183048) makes copied thread links open the mobile app. It adds `applinks:app.t3.codes` to the iOS associated domains and serves an apple-app-site-association file on app.t3.codes. That file lists only upstream's Apple team and bundle IDs (`ARK85ZXQ4Z.com.t3tools.t3code*`). Loom's `mobile-identity` seam replaces the iOS identity: it uses Loom's own bundle IDs and team, and only claims associated domains for Loom's own auth domain when Connect is set up. So the upstream line adding `applinks:app.t3.codes` was rightly not carried into the fork's `associatedDomains`. Loom's iOS app can never appear in app.t3.codes's file, so the claim would do nothing. Upstream's new test assertions assume upstream's iOS identity. Android keeps upstream's package name under the seam, so upstream's Android intent-filter and assetlinks assertions still hold, and they pass unchanged.
**What I changed:** In `apps/mobile/app.config.test.ts`, I carried the `mobile-identity` seam onto upstream's two iOS assertions, marked `fork: mobile-identity`:
- Loom's iOS config does not claim `applinks:app.t3.codes`.
- The hosted apple-app-site-association file still lists upstream's team plus each variant's upstream identifier, so that part of upstream's consistency check is kept.
I raised that file's row in `docs/fork/seams.tsv` from 1 to 3 marked lines. The test file now passes (6/6), and lint, format and `check_seams` are clean. I changed no upstream code.
One thing for another session: upstream's new `expo-image-picker` microphone permission string in `apps/mobile/app.config.ts` still says "Allow T3 Code…". It belongs to the brand-copy check, not this one, so I left it alone.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
📱 Native ChangeChanges the native fingerprint; merging blocks production OTAs until a new store build ships.size:M30-99 changed lines (additions + deletions).vouch:trustedPR author is trusted by repo permissions or the VOUCHED list.
1 participant
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on https://git.cafe/pingdotgg/t3code/pulls/26290. On a phone, a copied thread link (
https://app.t3.codes/threads/<env>/<thread>) opened the browser, which then offered the app. With T3 Code installed, the link now opens the thread in the app directly. Both PRs already change native code, so they can ship in one release.How it works
apps/web/public/.well-known/getsapple-app-site-association.jsonandassetlinks.json, both scoped to/threads/*and listing the production, preview, and dev apps. Apple fetches the file without an extension, sovercel.tsrewrites/.well-known/apple-app-site-associationto the.jsonfile, which Vercel serves asapplication/json. A rewrite is not a redirect, which Apple refuses. On app.t3.codes, requests go through to the latest channel's deployment, which serves both files.applinks:app.t3.codesnext to the existing Clerk domains. Android adds a verified (autoVerify) intent filter forhttps://app.t3.codes/threads/.https://app.t3.codesis a linking prefix, so/threads/<env>/<thread>reaches the existingthreads/:environmentId/:threadIdroute thatt3code://threads/…already uses, including?prompt=handling. Other app.t3.codes paths are not claimed and stay in the browser.ARK85ZXQ4Z) and bundle IDs come fromapp.config.ts. The Android SHA-256 signing fingerprints are copied fromhttps://clerk.t3.codes/.well-known/assetlinks.json, which already verifies these apps for passkeys.app.config.test.tschecks that every variant's identifiers appear in both files and that its native config claims the hosted app's host.Shipping order
autoVerifyfilters at install time, and iOS fetches through Apple's CDN, which caches. After the web deploy, checkhttps://app-site-association.cdn-apple.com/a/v1/app.t3.codesand Google's Digital Asset Links API for each package.Behaviour to know
Testing
apps/mobile/app.config.test.ts: each variant's bundle ID and package appear in the two files, and its config claimsapplinks:app.t3.codesand the/threads/intent filter. Dropping the dev app from the Apple file fails the development row.vp run check:changed: format, lint, knip, typecheck (34 packages), tests (22 files), and the React compiler check pass.Claude Opus 5.5 in Claude Code, run from T3 Code.
🤖 Generated with Claude Code