Paquet YunoHost pour Cartourse (ex-RaceTracer)
  • JavaScript 83.6%
  • CSS 14.1%
  • Shell 2.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
CptCurk 3c1371324f Paquet YunoHost Cartourse (ex-RaceTracer)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 12:42:45 +03:00
conf Paquet YunoHost Cartourse (ex-RaceTracer) 2026-10-13 12:42:45 +03:00
doc Paquet YunoHost Cartourse (ex-RaceTracer) 2026-10-13 12:42:45 +03:00
scripts Paquet YunoHost Cartourse (ex-RaceTracer) 2026-10-13 12:42:45 +03:00
sources/app Paquet YunoHost Cartourse (ex-RaceTracer) 2026-10-13 12:42:45 +03:00
.gitignore Paquet YunoHost Cartourse (ex-RaceTracer) 2026-10-13 12:42:45 +03:00
config_panel.toml Paquet YunoHost Cartourse (ex-RaceTracer) 2026-10-13 12:42:45 +03:00
LICENSE Paquet YunoHost Cartourse (ex-RaceTracer) 2026-10-13 12:42:45 +03:00
manifest.toml Paquet YunoHost Cartourse (ex-RaceTracer) 2026-10-13 12:42:45 +03:00
README.md Paquet YunoHost Cartourse (ex-RaceTracer) 2026-10-13 12:42:45 +03:00
tests.toml Paquet YunoHost Cartourse (ex-RaceTracer) 2026-10-13 12:42:45 +03:00

Cartourse for YunoHost

3D race routes from GPX: animated flyovers with a 3D ribbon, broadcast graphics, iframe embeds, EBU OGraf & HyperFrames export. Cartourse was called RaceTracer up to v1.0 (see Moving from RaceTracer below).

Install Cartourse with YunoHost

Overview

Cartourse turns a GPX file into a 3D race route you can play, embed and broadcast.

  • 3D terrain player — MapLibre GL JS (BSD-3) + open Terrain Tiles. Viewers can rotate, tilt and zoom while it plays (drag, wheel, pinch, +/− buttons); the camera keeps following the race, Auto camera (or a double-click) brings the automatic framing back.
  • Smooth camera over mountains — the camera pivot follows a smoothed altitude of the route instead of the terrain under the screen centre: no more jumps over ridges and valleys.
  • 3D ribbon — a translucent wall standing on the route, revealed with the race (or the classic flat line).
  • Leader marker of your choice — pulsing dot, arrow lying on the ground and pointing the way, bike, your own image, or nothing.
  • Open imagery by default — Sentinel-2 cloudless 2016 (EOX, CC BY 4.0); IGN orthophotos (France), OpenTopoMap, OSM, custom XYZ; Esri optional.
  • Cinematic, deterministic timeline — fly to start → 180° orbit over the start → the trace draws while the camera floats above a smoothed route (70° pitch by default) → smooth outro to a top view. In the final zoom-out the point cards shrink (size adjustable) and can be limited to the start and the finish.
  • Points by kilometre (start, city, sprint, mountain HC/1–4, danger, feed, finish) popping up in 3D, flashing when passed, shown on the elevation profile; automatic climb detection.
  • Animation themes — Classic (default), Broadcast, Minimal, Neon, plus a theme designer in the editor: colours, shapes, borders, icon, pole, entrance animation (rise, pop, slide, drop, flip, wipe, zoom, fade), pass effect, lower-third — live preview, no CSS needed.
  • Logos: one top-left (next to the title), one top-right, plus a row under the elevation profile with as many logos as you like (the first one centred) — per client, overridable per stage.
  • Town & village names on the elevation profile, detected automatically from OpenStreetMap (Overpass API) and written vertically, road-book style; hide, rename or turn them into points in the editor.
  • Per-client page style: background / text / tab colours and free CSS for the client page and the stage pages (empty = default look).
  • Camera keyframes captured with the mouse, blended with smootherstep interpolation.
  • Clients → stages: shared branding, one page per stage, one client page with a tab per day.
  • Embeds: /embed/<id> iframes, snippet builder, oEmbed, postMessage API.
  • EBU OGraf export for DaVinci Resolve 21+ (and SPX / CasparCG / Sofie): 3D map graphic + transparent overlay graphic, real-time and non-real-time.
  • HyperFrames export: npx hyperframes render → MP4.

Shipped version: 1.2.0~ynh1

Install at the root of a domain

The default path is /: https://coursemap.example.org/ serves the public home, /c/<client>, /r/<stage>, /embed/<stage>, and the editor lives at /admin.

sudo yunohost app install ./cartourse_ynh -a "domain=coursemap.example.org&path=/&init_main_permission=visitors&init_admin_permission=admins&embed_origins=*&seed_demo=0&import_racetracer=1"

A domain-root install needs the domain to be free (no other app on it).

Moving from RaceTracer

The app id changed (racetracer → cartourse), so this is a new install rather than an upgrade. Your data is copied automatically:

# 1. safety first
sudo yunohost backup create --apps racetracer
# 2. remove the old app — WITHOUT --purge, so /home/yunohost.app/racetracer stays on disk
sudo yunohost app remove racetracer
# 3. install Cartourse at the root of the same domain; "import_racetracer=1" copies the old data
sudo yunohost app install ./cartourse_ynh --force \
  -a "domain=coursemap.example.org&path=/&init_main_permission=visitors&init_admin_permission=admins&embed_origins=*&seed_demo=0&import_racetracer=1"
  • Clients, stages, logos and original GPX files are copied (never moved or deleted).
  • Old links keep working: /racetracer/... is redirected (301) to the same page at the new address, so iframes already embedded on other websites keep playing.
  • The postMessage API accepts and sends both cartourse and the old racetracer key.
  • Clients created with v1.0 have the Broadcast theme saved explicitly; switch them to Classic in Look → Point animation theme if you want the new default.

Package layout

manifest.toml            YunoHost packaging v2 (helpers 2.1)
scripts/                 install (+ RaceTracer import), upgrade, remove, backup, restore, change_url, config
conf/nginx.conf          public location + SSO-protected /admin (injects a shared secret header)
conf/systemd.service     Node.js service, hardened
config_panel.toml        allowed iframe origins
sources/app/             the application itself (zero npm dependencies)
  server.mjs             HTTP server, routing, API, legacy URL redirects
  lib/                   store (JSON files), domain, pages, places (OSM towns), exporters (OGraf, HyperFrames), zip, demo seed
  public/engine/         rt-core (timeline/camera maths), rt-player (MapLibre), rt-ribbon (3D ribbon layer),
                         rt-themes (theme designer → CSS), rt-ui, rt-overlay, rt-ograf (OGraf bridge),
                         rt-dem (terrain elevation), rt-player.css (layout + built-in themes)
  public/admin/          editor SPA (clients, stages, camera, theme designer)
  public/vendor/         MapLibre GL JS 6.13 (BSD-3), GSAP 3.15 (HyperFrames export only)

Run it locally (without YunoHost)

cd sources/app
RT_ADMIN_OPEN=1 node server.mjs          # Node.js >= 18, no npm install needed
# → http://127.0.0.1:8095/         public home
# → http://127.0.0.1:8095/admin    editor (open, for local testing only!)
npm test                                 # smoke tests (parsing, timeline, exports)

Environment variables: PORT, HOST, DATA_DIR, BASE_PATH (empty = domain root), RT_ADMIN_SECRET, RT_ADMIN_OPEN, RT_EMBED_ORIGINS, RT_SEED_DEMO, RT_LEGACY_PATHS (old URL prefixes to redirect, default /racetracer), RT_OVERPASS_URL (Overpass endpoints for town names, space separated).

Town names need outgoing HTTPS from the server to the public Overpass API (overpass-api.de, with two mirrors as fallback). They are fetched once per stage (at creation, when the track is replaced, or the first time an older stage is viewed) and stored with the stage.

Security model

  • /admin is a separate YunoHost permission (default group admins), enforced by SSOwat.
  • nginx adds X-RT-Admin: <random secret> only inside the /admin location and strips it everywhere else; the app refuses admin routes without it. The Node process listens on 127.0.0.1 only.
  • Embed pages send Content-Security-Policy: frame-ancestors <configured origins>; all other pages frame-ancestors 'self'. YunoHost's X-Frame-Options is cleared so embeds work.
  • Uploaded SVGs are served with a restrictive CSP.

Licences

Cartourse code: AGPL-3.0-or-later. Town names: © OpenStreetMap contributors (ODbL). MapLibre GL JS: BSD-3-Clause. GSAP: GreenSock standard licence (free, bundled only in HyperFrames exports because HyperFrames requires it). Imagery/terrain: see attribution in the map (EOX, IGN, OpenTopoMap, OpenStreetMap contributors, Mapzen/AWS Terrain Tiles).