Skip to main content

EpicRide, the desktop client

EpicRide is the browser client for the work you would rather not do on a phone: planning a route properly, editing a track, writing up a trip. It runs at epicride.fastgis.eu and talks to the same API as everything else.

:::caution Being written This page describes what the client is and how it is put together. Screen-by-screen walkthroughs are still to come. :::

The client opens on a Dashboard of what you are riding rather than on a map. That is the front of a bigger idea with its own page: events — a time, a roster and the library records you ride, at four sizes from a solo trip to a rally.

The client's biggest single tool has its own page: the roadbook editor — a WYSIWYG editor for FIA-layout rally roadbooks with OpenRally export and print.

How it fits together​

EpicRide is a single-page app in front of its own small gateway, which sits between the browser and the FastGIS API rather than the browser calling the API directly. The gateway holds the session, so an API key never reaches the page.

The gateway is configured by the DESKTOP_GW_* variables — DESKTOP_GW_UPSTREAM names the API it proxies to, DESKTOP_GW_REDIS_URL holds its sessions, DESKTOP_GW_SECRET_KEY signs them. It answers GET /healthz with {"ok":true,"service":"desktop-gateway"}.

What it does​

AreaWhat you get
DashboardThe first screen: invitations waiting on your answer, what is running now, and what is coming up
EventsA time, a roster and the records you ride — trip, group ride, tour or rally, each with its own console at a URL you can paste. See Events
PlanBuild a route leg by leg, with an elevation strip and profile chart alongside the map. Gates, bollards and toll booths on a motorcycle or car route are drawn on it (closed ones in red) and listed under the summary; a closed gate the router could not avoid gets a red warning. Advanced settings carry Avoid closed gates (on by default) and, with dirt-first on, Max detour (1.2× / 1.5× / no cap) — both saved with your settings and shared in meaning with the rider app. When dirt-first was capped, the panel offers the full route with its extra length
ModesSwitch the routing character — the same start and finish, ridden differently
Finding thingsFuel, food, campsites, viewpoints, mountain passes, dark-sky sites, forgotten and remote places, beaches, MTB trails, curvy roads, wild-camp spots and scenic villages — the same searches the rider app has. Search around the map, or along the route you are planning: results come back in the order you will pass them, an added stop lands in the right place in the route rather than after the destination, and the list tells you the longest stretch with none of them on it. Where it matters you can rank by ride time instead of straight-line distance, because a beach across a fjord is an hour away
LibraryEverything you have recorded, imported, derived or authored — routes, rides, trails, points and roadbooks — searchable by name, description and tag, filtered by category or map area, with multi-select bulk actions (show on map, export, share, delete) and per-item pages. Filters live in the page URL, so a filtered view is a link you can paste. The same library opens as a picker inside the planner ("From library…", insert a saved line into the route) and the roadbook editor
TrafficRoad closures, roadworks, queues and accidents from national traffic feeds, coloured by severity: red stops you, amber costs you time. The count says when the picture is partial rather than pretending it is complete, and the publisher's own wording is shown untranslated because some licences require it
Sketch and vector toolsDraw and edit geometry, then save it back
RoadbookGenerate tulip-diagram pacenotes from a track
StoriesAuthor and publish trip stories and StoryMaps
SocialFriends, shared items and the leaderboard
Live ridersWatch friends who are sharing their position. Positions are pushed, so a marker moves within a second rather than at the next poll — and the poll stays as the fallback, so a hiccup slows the map down instead of emptying it. The desktop is read-only here: it shows you where people are and never broadcasts your own position
SharingShare any library record with your friends, one of your sharing groups, or as a public link. A share grants access, never a copy: the recipient reads your record, your edits show up for them, and Stop sharing takes access back — including from a link already handed out. Shares live in the same ledger the rider app reads, so what you share on the desktop appears in the app's share inbox. A public link is shown once, when it is created; the server keeps only a hash of it, and it expires after 30 days unless you re-share to extend it
GarageYour motorcycles and riding styles, shared with the rider app
SupportAn in-app chat backed by the support bot

Anything you save is the same record the rider app sees — the library, the garage and your routes are one dataset, not a desktop copy.

Watching a ride happen​

The live layer is read-only by design, and that is enforced rather than promised. The gateway proxies the live plane as a one-way valve: frames come down to the browser, and of the frames a browser could send, only a keepalive is passed on. The two frames that would matter — "here is my position" and "stop sharing" — are writes, and they never leave the gateway.

This is why the desktop reaches the live plane through the gateway at all rather than holding a credential of its own. A token in a browser is a token that publishes as you; a socket the gateway owns is not.

If the socket cannot open, or closes, the map falls back to asking every 15 seconds. You lose the second-by-second smoothness and nothing else.

Signing in​

Sign in through the gateway with the same account you use everywhere else. The gateway sets its own session cookie; DESKTOP_GW_COOKIE_SECURE should stay on anywhere with TLS.

An account holds one desktop session and one phone at a time. Signing in or out on the desktop never touches the phone; only Sign out phone (below) does.

  • The same browser signing in again goes straight in. The gateway recognises it by a long-lived "this browser" cookie (desktop_gw_device, httpOnly), which is not a credential and does nothing without the password.
  • A different browser is asked first: "Your account is signed in on Chrome · Windows (last active 3 min ago). Sign in here? That browser will be signed out." Cancel changes nothing anywhere. Sign in here takes the seat. The question stays valid for two minutes; after that the answer is "That took too long — sign in again". If yet another browser takes the seat while you decide, you are asked again, naming that one.
  • The browser that was signed out leaves the app on its next request, or within seconds if the live map is open, and shows "Signed out — alice signed in on Firefox · macOS at 14:02" with a Sign in button. A password change, or a sign-out from another device, shows its own short reason the same way — "Signed out — alice signed this browser out from iPhone · iOS 26.4 at 14:02" when the phone did it, or "Signed out — an administrator signed this account out everywhere".

Devices. Settings → Devices shows both seats: This browser and Phone, each with its name and when it was last active ("riding now" while the phone is sharing its position or in a group ride), or "No phone signed in". Sign out phone asks first — "Sign out iPhone · iOS 26.4? It will stop sharing location and receiving calls for this account." — then signs that phone out; its next request shows who signed it out and from where. Use it for a lost or lent phone. This browser signs itself out with the header's Sign out; the gateway only lets the desktop list the seats and sign out the phone seat, never its own.

Browsers are named from their User-Agent ("Firefox · macOS", "Edge · Windows"; "Web browser" when it cannot tell). A desktop seat can change browsers at most SEAT_TAKEOVER_DAILY_CAP times (default 5) in 24 hours; past that, sign-in answers "too many device switches".