Skip to content

fix: use public deployment URL for deep links and AD4M-connect appInfo (mobile bug)#611

Open
HexaField wants to merge 2 commits into
devfrom
fix/capacitor-public-url
Open

fix: use public deployment URL for deep links and AD4M-connect appInfo (mobile bug)#611
HexaField wants to merge 2 commits into
devfrom
fix/capacitor-public-url

Conversation

@HexaField

@HexaField HexaField commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Mobile (Capacitor) builds were producing broken deep-link URLs because window.location.origin resolves to capacitor://localhost — a scheme that only opens inside the running app on the originating device.

Reported example:

✗ capacitor://localhost#/communities/QmzSYwdfbx2Z2txdwyXCCuowT5q1jM7SrRecNVeTbB32oz14m28/iluulaknboyqppochknhpcbg/conversation

Expected:

✓ https://fluxsocial-dev.netlify.app/#/communities/QmzSYwdfbx2Z2txdwyXCCuowT5q1jM7SrRecNVeTbB32oz14m28/.../conversation

Two places propagate this off-device:

  • app/src/utils/registerMobileNotifications.tsappUrl + appIconPath get embedded in push-notification deep links by the AD4M push service.
  • app/src/app.tsappInfo.url + appInfo.iconPath are sent to AD4M-connect and stored on the capability token.

Fix

New app/src/utils/publicUrl.ts resolves the public URL with this precedence:

  1. VITE_PUBLIC_URL (build-time env) — explicit, preferred. Mobile builds inherit it at build time.
  2. window.location.origin when it points at a real public host (not capacitor:, not localhost, not *.local).
  3. Hardcoded fallbackhttps://fluxsocial-dev.netlify.app for non-prod, https://fluxsocial.netlify.app for prod. The fallback exists so the bug surfaces as "wrong-but-public site" rather than "links 404 silently."

Both .env.development and .env.production now ship VITE_PUBLIC_URL, so the fallback is a safety net rather than the normal path.

Test plan

  • Unit tests (publicUrl.test.ts) cover every branch — env precedence, trailing-slash strip, blank-env fallthrough, netlify preview pass-through, capacitor/localhost/null fallback, plus a regression test that rebuilds the exact failing URL from the report and asserts the fix.
  • Smoke test — pure logic validated against 18 assertions in an isolated node run (Flux's local jest setup is missing vue-jest + jest-environment-jsdom; tests are written to the jest convention used by upsertById.test.ts so they'll run in CI where the environment is intact).
  • Visual verification — install the dev TestFlight / APK build after this lands, tap a push notification, confirm it opens https://fluxsocial-dev.netlify.app/... rather than capacitor://localhost/....
  • AD4M-connect popup — install on web, confirm the app-info card still shows the correct URL (no regression for the non-Capacitor case).

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced deep linking support for web and mobile applications with improved URL configuration for sharing and navigation
  • Improvements

    • Fixed mobile notification configuration to properly handle deep links
    • Better public URL resolution across development, preview, and production environments, including Capacitor mobile builds

…D4M-connect appInfo

In Capacitor (mobile) builds, `window.location.origin` is
`capacitor://localhost` — a scheme that only resolves inside the
running app. The two places that propagate this off-device were:

- `registerMobileNotifications.ts` — `appUrl` and `appIconPath` are
  embedded in push-notification deep links. Tapping a notification on
  any device produced a `capacitor://localhost#/communities/...`
  link, broken everywhere except the device that originated it.
- `app.ts` — `appInfo.url` and `appInfo.iconPath` are sent to the
  AD4M-connect popup and stored on the capability token. Same
  problem, less visible (only surfaces in admin / debug views).

Add `utils/publicUrl.ts` with a pure resolver:

  1. Use `VITE_PUBLIC_URL` (build-time env var) when set.
  2. Otherwise use `window.location.origin` IF it points at a real
     public host (not `capacitor:`, not `localhost`, not `*.local`).
  3. Otherwise fall back to the canonical Coasys deployment —
     fluxsocial-dev.netlify.app for non-prod, fluxsocial.netlify.app
     for prod. The fallback exists so the bug surfaces as
     "links go to the right-but-shared deployment" rather than
     "links 404 silently."

Set `VITE_PUBLIC_URL` in `.env.development` and `.env.production` to
the canonical deployments. Mobile builds inherit these by virtue of
Vite baking them at build time.

The exported helpers `publicAppUrl()` and `publicIconUrl()` wrap the
runtime reads (`import.meta.env`, `window.location`); tests call
`resolvePublicAppUrl()` directly so every branch is covered without
monkey-patching globals.

Test covers:
- `isPublicOrigin` — accept/reject across https, http, capacitor,
  ionic, localhost variants, 127.0.0.1, [::1], `.local`, malformed.
- `resolvePublicAppUrl` — env precedence, trailing-slash strip, blank
  env fall-through, netlify-preview pass-through, capacitor fallback
  (dev + prod), localhost fallback, null fallback.
- Regression — reconstructs the exact failing URL from the bug report
  and asserts it now matches the expected
  `https://fluxsocial-dev.netlify.app/#/communities/.../conversation`
  form with no `capacitor` in it anywhere.
@netlify

netlify Bot commented Jun 15, 2026

Copy link
Copy Markdown

Deploy Preview for fluxsocial-dev ready!

Name Link
🔨 Latest commit ca14403
🔍 Latest deploy log https://app.netlify.com/projects/fluxsocial-dev/deploys/6a2fd243e934b20008189d1b
😎 Deploy Preview https://deploy-preview-611--fluxsocial-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@HexaField, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 51 minutes and 15 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0b1a2657-eb57-4737-adc2-1b0ba8874a9f

📥 Commits

Reviewing files that changed from the base of the PR and between 4032ac4 and ca14403.

📒 Files selected for processing (1)
  • app/src/utils/publicUrl.ts
📝 Walkthrough

Walkthrough

Introduces app/src/utils/publicUrl.ts with URL resolution logic for Flux deep links, validates public origins, and resolves a stable base URL via env override, window.location.origin, or hardcoded fallbacks. Sets VITE_PUBLIC_URL in dev/production env files. Replaces window.location.origin in app.ts and registerMobileNotifications.ts with the new helpers.

Changes

Public URL Resolution for Deep Links

Layer / File(s) Summary
publicUrl.ts utility and env config
app/src/utils/publicUrl.ts, app/.env.development, app/.env.production
Adds isPublicOrigin, ResolveOptions, resolvePublicAppUrl, publicAppUrl, and publicIconUrl with priority-ordered URL resolution (env override → window.location.origin → hardcoded fallback). Sets VITE_PUBLIC_URL in both env files.
Wiring into app init and mobile notifications
app/src/app.ts, app/src/utils/registerMobileNotifications.ts
Replaces window.location.origin with publicAppUrl() and publicIconUrl() in the Ad4m appInfo config and push notification config.
Test suite for publicUrl
app/src/utils/__tests__/publicUrl.test.ts
Covers isPublicOrigin accept/reject cases, resolvePublicAppUrl env precedence and window origin passthrough, Capacitor/localhost fallback behavior, and a deep-link regression assertion.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hopping past capacitor: traps,
A public URL fills the map!
No localhost links in shared deep links,
VITE_PUBLIC_URL sets the pinks.
The rabbit stamps each test with glee —
Deep links now work as they should be! 🌐

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically identifies the main change: using public deployment URLs for deep links and AD4M-connect appInfo to fix a mobile bug, matching the core problem and solution in the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/capacitor-public-url

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/utils/publicUrl.ts`:
- Around line 71-74: The code at line 71-74 accepts any non-empty
`opts.envPublicUrl` value without validating that it is actually a valid public
HTTP(S) origin. Before returning the stripped env value, validate that it is a
proper HTTP or HTTPS URL. If the env value is not a valid public origin (does
not start with http:// or https://), reject it and allow the code to continue to
the next fallback logic rather than returning the invalid value, preventing
misconfigured env values from producing broken external deep links.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9c443724-b15d-4dad-a2fd-7d2de9701289

📥 Commits

Reviewing files that changed from the base of the PR and between bc3bae2 and 4032ac4.

📒 Files selected for processing (6)
  • app/.env.development
  • app/.env.production
  • app/src/app.ts
  • app/src/utils/__tests__/publicUrl.test.ts
  • app/src/utils/publicUrl.ts
  • app/src/utils/registerMobileNotifications.ts

Comment thread app/src/utils/publicUrl.ts
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant