Skip to content

Devices and pairing

Rails
Status ✅
Code app/controllers/devices_controller.rb, app/views/devices/{index,edit,new}.html.erb, app/models/device.rb, config/locales/app.en.yml (app.devices.*, app.pair.*)

Verified against code: 2026-10-11

Purpose

A user pairs a watch once with the 6-digit code it shows; from then on that device uploads its tracks to the logbook by itself. The devices page lists the paired devices and lets the user rename or unpair them. The protocol between watch and server (pairing request, polling, tokens, unpair from the watch) is in device-api.md; this file covers the web side.

In the signed-in area a paired watch is a device. On /pair it is still a watch, because it isn't paired yet.

Devices (/my/devices)

Page head "Devices" / "Watches paired to your account. They upload their tracks straight to your logbook." with a button "+ Pair a device" → /pair.

Lists the user's devices that are not unpaired, newest first, as cards:

Element Content
Title Watch icon + name: the name typed on the web, else the name the watch reported, else the model name from the Garmin model table (Garmin) or the raw model code (other platforms), else "Unknown"
Badge Green "Paired"
App Version Last reported app version, or "–"
Paired On Pairing date and time (short format), or "–"
Last Sync Last time the device talked to the API (short format), or "Never"
ID Device id, cut to 16 characters, monospace
Button "Edit"

Empty: watch icon, "No devices paired yet", "Pair your Garmin watch once and the WatchApp uploads every track by itself.", button "Pair your watch now" → /pair.

Edit device (/my/devices/:id/edit)

Back link "Devices", title "Edit device".

Field Rules
Name Max 100 characters. Placeholder: the model name (or "fēnix 7"). Hint "Shown on your devices page. Leave it empty to use the name the watch reports. Tracks keep the name they were recorded with."

"Save device" → /my/devices with "Device saved."

  • A typed name wins over the name the watch reports when it registers again.
  • An empty name hands naming back to the watch.
  • Tracks keep the device name they were recorded with.

Danger zone "Unpair device": "The watch can't upload tracks any more until you pair it again. Tracks already uploaded stay." Button "Unpair device", confirm "Unpair this device? It can't upload tracks until you pair it again." The device is marked unpaired, disappears from the list, and its next upload is refused (device-api.md). Notice "Device unpaired. It can't upload tracks any more."

Pair (/pair)

Auth layout. Stays at the top level (not under /my) because the watch screen prints "sailever.com/pair".

Card: eyebrow "Pair your watch", title "Connect your watch".

Signed out

"Sign in first. After that you come straight back here to enter the code from your watch." Button "Sign in" → sign-in page with redirect_to=/pair. Note "New to SailEver? Join the beta".

Signed in

Element Content
Lede "Pair once and every trip from the SailEver WatchApp lands in your logbook."
Steps 1 (watch icon) "On the watch open SailEver and choose Pair device. It shows a 6-digit code." · 2 (link icon) "Enter the code here. It stays valid for 10 minutes."
Field "Pairing code": numeric keyboard, 6 digits ([0-9]{6}), max 6, placeholder "000000", one-time-code autofill, autofocus
Button "Pair watch"
Link "← Back to my watches" → /my/devices

Submitting (POST /pair, signed in only)

Case Result
Code blank Page again (422), alert "Please enter the 6-digit pairing code displayed on your watch."
No device with that code, or the code expired Page again (422), alert "Invalid or expired pairing code. Please check your watch screen."
Valid The device is assigned to the user (taking it from a previous owner if it had one), its old token is cleared, the code is used up. Redirect to /my/devices with "Device paired." The watch picks up its new token on its next poll.
More than 5 attempts in 5 minutes (per user) 429 Too Many Requests (plain response, no page)

Known deviations

  • "Back to my watches" and the devices subtitle "Watches paired to your account" use "watch" for paired devices in the signed-in area.
  • The empty state and the pair page only mention Garmin, although Wear OS devices pair the same way.
  • Too many pairing attempts show a bare 429 response instead of the page with an alert.