# Companion app pairing QR — integration handoff **Status:** web-UI side SHIPPED (CompanionIntroOverlay.vue, 2026-07-16). This doc is the contract + requirements for the companion-app side (worked on separately, on the Mac). ## What the web UI now does The "Remote Companion" intro modal (shown once after first dashboard login, and in the public demo) gained a second screen: 1. **Screen 1 (existing):** APK download QR (desktop) / download button, plus a new **"I've installed it"** button to the right of the download button. 2. **Screen 2 (new, slide transition):** a **pairing QR** the companion app scans to auto-fill the server entry, with a **Back** button returning to screen 1. On small screens (where you can't scan your own display) an **"Open in companion app"** deep-link button is shown above Back, using the same URI as the QR. ## The QR payload / deep link (the contract) A single URI, also usable as an OS deep link: ``` archipelago://pair?v=1&url=[&pw=] ``` Query parameters: | param | required | meaning | |-------|----------|---------| | `v` | yes | Payload version, currently `1`. Reject/ignore unknown majors gracefully — show "please update the app". | | `url` | yes | Full origin the app should connect to, scheme included: `https://demo.archipelago-foundation.org`, `http://archipelago.local`, `http://192.168.1.228`, etc. No trailing slash guaranteed either way — normalize. | | `pw` | no | Login password. **Only present in the public demo** (shared demo password `entertoexit`). Real nodes never embed a password — the frontend doesn't have it. | Examples the web UI actually emits: - Demo: `archipelago://pair?v=1&url=https%3A%2F%2Fdemo.archipelago-foundation.org&pw=entertoexit` - Real node, browsed via LAN IP: `archipelago://pair?v=1&url=http%3A%2F%2F192.168.1.228` - Real node kiosk (UI runs on localhost, so it advertises the mDNS name from `system.get-hostname`): `archipelago://pair?v=1&url=http%3A%2F%2Farchipelago.local` ## Companion app requirements 1. **Scan entry point:** the app's action is labeled **"Scan Node's QR"** (implemented 2026-07-17; the modal copy in CompanionIntroOverlay.vue was updated to match). 2. **Parse the URI** (from camera scan AND from an OS deep-link intent — register the `archipelago://` scheme so the "Open in companion app" button on phones works). 3. On success, **create/update a saved server entry**: - Server address = `url` exactly as given (respect the scheme — the demo is https, LAN nodes are typically http, `.local` mDNS names must work). - If `pw` present, prefill the password and attempt auto-login; otherwise land on the password prompt for that server. - If an entry with the same origin already exists, update it rather than duplicating. 4. **Demo flow (the showcase):** scanning the demo QR should take a fresh install to a logged-in demo session in one step — url `https://demo.archipelago-foundation.org`, password `entertoexit`, no manual typing. 5. **Robustness:** - Tolerate unknown extra query params (forward compat — we may add `name`, `cert` fingerprint, etc. under `v=1`). - Self-signed HTTPS on `.local`/LAN addresses may appear later; don't hard-fail the parse on scheme. - Bad/foreign QR → clear error, stay on the scan screen. ## Notes / future extensions (not in v1) - A real-node pairing **token** instead of a password (backend mints a one-time token, QR carries it, app exchanges it for a session) — needs a backend RPC; the `v` param exists so we can bump when this lands. - Optional `name` param (node display name) so the app labels the entry nicely. ## Testing checklist (app side) - [ ] Scan demo QR from https://demo.archipelago-foundation.org → auto-connected demo session. - [ ] Scan a real node's QR (LAN IP origin) → entry created, password prompt shown. - [ ] Scan a kiosk node's QR (`http://.local`) → mDNS resolution works on the phone. - [ ] Tap "Open in companion app" on a phone browser → deep link opens the app with the same behavior. - [ ] Re-scan same node → no duplicate entry.