Invite page never links to the app stores on production — hostname check omits codmir.app
Description
An invited user opening a project invitation on a phone is never offered the mobile app. The "get the app" path on the invite confirmation page silently falls back to an internal download page instead of the App Store or Play Store. The cause is a hardcoded hostname allowlist that does not include the production domain. The page checks for `codmir.com`, `www.codmir.com` and `app.codmir.com`, but production serves from `www.codmir.app`. None of the three ever match, so the production branch is unreachable and every mobile visitor takes the development fallback. This fails silently rather than erroring: the fallback page returns HTTP 200, so there is no broken link, no 404, and nothing in the logs. It simply never sends anyone to a store. A second, independent defect sits behind the same code path: the iOS link is built with a placeholder App Store ID (`id0000000000`). Even once the hostname check is corrected, iOS visitors would land on a dead App Store page. The Android link appears correct — its package identifier matches the one declared by the mobile app. Impact: this sits on the new-user acquisition path. Accepting an invitation is the first thing a new user does, and on mobile the app is the intended destination. Both defects are on that path, and the silent-fallback behaviour means it can persist indefinitely without generating a single error report.
Steps to Reproduce
1. Open a project invitation link on a mobile device (or any browser with a mobile user agent) against the production site at www.codmir.app — the path is /join/confirm?token=<invite token>. 2. Follow the flow to the point where the page offers to open or install the mobile app. 3. Tap the option to get/download the app. Observed: the browser navigates to the site's own /download page. Expected: the browser navigates to the App Store (iOS) or Play Store (Android). Confirming the hostname premise independently: curl -sL -o /dev/null -w '%{url_effective}\n' https://codmir.app/ -> https://www.codmir.app/ The production host is www.codmir.app, which is absent from the allowlist the page tests against.
Expected Behavior
On the production site, a mobile visitor who does not have the app installed is sent to the correct native app store for their platform — the App Store on iOS, the Play Store on Android — using a real, resolvable store listing. The environment check that selects store links versus the development fallback should be driven by configuration rather than a hardcoded list of hostnames, so that adding or changing a domain cannot silently disable it.
Actual Behavior
Every mobile visitor on production is sent to the site's internal /download page instead of a store listing. The production branch is dead code in production. The condition guarding it is: const isProduction = window.location.hostname === "codmir.com" || window.location.hostname === "www.codmir.com" || window.location.hostname === "app.codmir.com"; Production serves from www.codmir.app, so this evaluates false on every real request and control always reaches the fallback `return "/download"`. No error is surfaced. The fallback page responds HTTP 200, so the failure produces no 404, no console error, and no server-side log entry — it is invisible to monitoring. Separately, the iOS branch — unreachable today, but wrong once reached — returns: https://apps.apple.com/app/codmir/id0000000000 `id0000000000` is a placeholder, not a real App Store ID, and resolves to a dead store page.
Environment
Product
Codmir Web — invite acceptance flow
Environment
Production web application at https://www.codmir.app (Next.js App Router, client component). Reproduced with a mobile user agent; the defective branch is user-agent independent and depends only on window.location.hostname, so it affects all mobile platforms equally. Verified 2026-09-23.
Activity
No comments yet.