Skip to content

[Medium] Extend QR/URL format to carry both LAN URL and mesh room code #151

Description

@bitflicker64

filedrop-mesh epic

This is a sub-issue of the umbrella epic: #155.


Description

The current QR encodes a single LAN URL: http://192.168.x.x:port/<token>#<key>. With mesh, a single QR needs to carry both the LAN URL and the mesh room code, because the receiver's phone doesn't know in advance which path will work.

This sub-issue defines and implements the QR + URL format that handles both cases transparently.

Goals

  • One QR works in both same-network and cross-network scenarios.
  • A phone scanning the QR never has to choose which transport to use — the receiver page figures it out.
  • Backward-compatible: an old receiver client scanning a new QR can still hit the LAN URL if it's reachable.

Proposed URL format

The QR encodes a deep link on the signaling host:

https://<signal-host>/r/<ROOM>#<LAN_URL>?<key>

Where:

When the receiver opens the deep link, the receiver page:

  1. Reads key from the fragment.
  2. Reads LAN_URL from the fragment.
  3. Tries LAN_URL first (cheap, fast, no signaling roundtrip).
  4. If the LAN URL is unreachable (timeout, connection refused), falls back to the signaling room <ROOM> and switches to MeshTransport.

Why fragment for both LAN URL and key?

The fragment is never sent to the server. Both the LAN URL and the key ride in the fragment so neither leaks through any HTTP request — including the initial GET to the signaling host's landing page. The signaling host only ever sees the room code in the path.

Fallback for old clients

For receivers running an older filedrop web client that doesn't understand the new format, the QR can also embed the plain LAN URL as a fallback path (e.g., via a tiny JavaScript shim that detects old clients and redirects). Decide the exact mechanism in the PR; the simplest is to encode both URLs in the fragment separated by a sentinel character.

Expected vs Actual

Expected: One QR. Two transport paths. The receiver picks the working one.

Actual: One QR. One path. LAN-only.

Steps to land

  1. Define the URL schema above in docs/mesh-url-format.md (small spec doc).
  2. Sender: build the QR string in src/qr.js from (signalUrl, roomCode, lanUrl, keyHex).
  3. Receiver: update the landing page to parse the new format, try the LAN URL with a short timeout, fall back to mesh.
  4. Backward compatibility: detect an old client (User-Agent or version marker) and redirect to the LAN URL only.
  5. Terminal UI: show the mesh code alongside the LAN URL in the metadata box, with a clear visual indicator that mesh is active.
  6. Tests:
    • QR string roundtrips through the parser.
    • LAN-URL-first-then-mesh fallback: unit-test the decision logic with mocked timeouts.
    • Old-client detection redirects correctly.

Location

  • modified: src/qr.js — renderMeshQR(signalUrl, roomCode, lanUrl, keyHex, options)
  • modified: the receiver-side HTML served at the LAN URL — add the format-detection + fallback logic
  • new doc: docs/mesh-url-format.md

Difficulty

Medium — the format itself is simple; the receiver-side fallback timer and old-client detection need real device testing.

Dependencies

Notes

Pick a sentinel character for the fragment that won't appear in URL-encoded payloads. Newline is safe since fragments are URL-encoded by the browser before the page reads them. Document the choice in the spec doc.

Part of the filedrop-mesh epic (#155).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions