Přehled
Cestou necestou je webová aplikace pro prezentaci cesty na mapě: vybereš zastávky, dopravní prostředek a přehraješ animovanou jízdu po trase. Trasu uložíš pod krátký odkaz a pošleš komukoli.
| Stack | Next.js 15 (App Router, React 19, TypeScript) · Mapbox GL JS 3 · Mapbox Directions & Geocoding v6 · Neon Postgres (@neondatabase/serverless) · Vercel (region fra1) |
|---|---|
| Produkce | https://cestou-necestou.online (Vercel alias: cestou-necestou.vercel.app) |
| Autor | Alemon (alemon.cz) |
| Název | Idiom „cestou necestou" – auto a kolo jedou cestou (po síti), letadlo a vlak necestou (vzduchem, přímo). Dvě slova, bez pomlčky. |
Co appka umí
- Zastávky – přidání klikem do mapy (s automatickým pojmenováním podle obce) nebo vyhledáním; přejmenování, přeskládání, smazání. První je start, poslední cíl. Max. 25.
- Čtyři dopravní prostředky – auto a kolo po reálné síti (Mapbox Directions), vlak po skutečných kolejích (BRouter, OpenStreetMap) se 3 vagony, letadlo po ortodromě.
- Animace jízdy – vozidlo se pohybuje po trase, za ním se kreslí červená stopa, mapa ho může sledovat; play/pauza, posuvník, rychlost 1–10, smyčka.
- Statistika – délka trasy v km, odhad času podle průměrné rychlosti prostředku, další zastávka a vzdálenost k ní.
- Uložení a sdílení – krátký odkaz
/t/<slug>, OG metadata pro náhled v chatech, režim prezentace bez panelu. - Editace – vlastník trasy (tajný klíč v prohlížeči) může trasu měnit, kopírovat i smazat; právo editace přenese na jiné zařízení editačním odkazem.
Instalace a nasazení
fra1. V SQL editoru spusť obsah schema.sql (viz Neon a schéma DB). Skript je idempotentní – lze spouštět opakovaně.pk.…) s výchozími public scope. Viz Mapbox token.vercel.json ho vynucuje ("framework": "nextjs"), přesto zkontroluj. package.json musí být v kořeni repozitáře (nebo nastav Root Directory).NEXT_PUBLIC_* proměnné je nutný Redeploy – zapékají se do bundlu při buildu./, přidej dvě zastávky, ulož – tím ověříš Mapbox i spojení na Neon.Proměnné prostředí
| Proměnná | Povinná | Popis |
|---|---|---|
DATABASE_URL | ano | Pooled connection string z Neonu (…-pooler.eu-central-1.aws.neon.tech/…?sslmode=require). Jen na serveru. |
NEXT_PUBLIC_MAPBOX_TOKEN | ano | Public token pk.…. Je viditelný v prohlížeči – zapékaný při buildu. |
NEXT_PUBLIC_SITE_URL | ne | Veřejná URL – nastav https://cestou-necestou.online, ať OG odkazy vedou na hlavní doménu. Bez ní se použije VERCEL_PROJECT_PRODUCTION_URL, lokálně localhost:3000. |
Vzor je v .env.example; lokálně vytvoř .env.local (je v .gitignore).
Neon a schéma DB
create table if not exists routes (
id bigserial primary key,
slug text unique not null, -- veřejný identifikátor, 7 znaků
title text,
vehicle text not null check (vehicle in ('car','train','plane','bike')),
stops jsonb not null, -- [{lat, lng, name}, …]
created_at timestamptz not null default now(),
updated_at timestamptz not null default now(),
views integer not null default 0 -- zvyšuje se při každém načtení
);
create index if not exists routes_created_at_idx on routes (created_at desc);
alter table routes add column if not exists edit_key text; -- tajný klíč vlastníka, 24 znaků
alter table routes add column if not exists updated_at timestamptz not null default now();
V databázi je jen seznam zastávek a prostředek. Geometrie trasy se dopočítává při každém načtení, takže se neukládají velké polylines a změna prostředku je okamžitá.
Mapbox token
- Stačí výchozí public scope (
STYLES:TILES,STYLES:READ,FONTS:READ,DATASETS:READ,VISION:READ). Directions a Geocoding nemají vlastní scope – fungují s každým tokenem. - Nikdy nezaškrtávej Secret scope – token je v bundlu a v každé URL požadavku.
- Po zprovoznění přidej URL restriction:
https://cestou-necestou.online/*ahttps://cestou-necestou.vercel.app/*. Preview deploymenty pak token odmítne (mají náhodné URL) – buď je nepoužívej, nebo pro ně měj druhý token bez restrikce. - Free tier (orientačně): 50 000 map loads, 100 000 Directions a 100 000 Geocoding požadavků měsíčně.
Lokální vývoj
cp .env.example .env.local # doplň hodnoty
npm install
npm run dev # http://localhost:3000
npm run build # ověření produkčního buildu
npm run db:init # psql "$DATABASE_URL" -f schema.sql
window, proto se RouteApp načítá přes RouteAppLoader s dynamic(…, { ssr: false }). Do RouteApp.tsx nedávej nic, co by muselo běžet na serveru.Ovládání
Levý panel
| Sekce | Co dělá |
|---|---|
| Čím pojedeš | Výběr prostředku. Změna okamžitě přepočítá trasu (u auta/kola volá Mapbox Directions). |
| Přidat zastávku | Vyhledání místa (Mapbox Geocoding, česky) – Enter nebo tlačítko Hledat, výsledek klikem přidáš na konec. Alternativně klik do mapy. |
| Zastávky | Seznam v pořadí jízdy. Název je editovatelný (uloží se při opuštění pole), šipky přeskládají, ✕ odebere. Svislá červená přerušovaná linka spojuje start a cíl. |
| Trasa | Délka v km a odhad času z průměrné rychlosti prostředku (viz tabulka). Pod tím poznámka, jak byla trasa spočítána. |
| Animace | Rychlost 1–10, Mapa sleduje jízdu (kamera drží vozidlo ve středu), Opakovat. Vše se projeví i za jízdy. |
| Uložit a sdílet / Tvoje trasa | Název trasy a akce podle stavu – viz Ukládání, sdílení, editace. |
Mapa
- ⛶ Celá trasa – přizpůsobí výřez celé trase.
- ▶ Prezentace / ✎ Upravit – schová/zobrazí panel.
- Zoom +/− vpravo dole; kompas je vypnutý, mapa je vždy severem nahoru.
- Klik do mapy přidá zastávku na konec.
Lišta přehrávače (dole)
- ▶ / ❚❚ / ↺ – přehrát, pauza, znovu od začátku (po dojetí).
- Posuvník – přetažením skočíš na libovolné místo trasy, i za jízdy.
- Legenda – start, ujeté km, cíl.
- Prostředek a další zastávka – např. „→ Kodaň za 312 km" nebo „v cíli: Kodaň" (na mobilu skryté).
- − 4× + – rychlost animace, funguje i v prezentaci.
Klávesové zkratky
| Klávesa | Akce |
|---|---|
| Mezerník | Přehrát / pauza |
| + / − | Rychlost animace o 1 výš / níž |
Zkratky se ignorují, když je kurzor v textovém poli.
Ukládání, sdílení, editace
Stavy trasy
| Stav | Kde | Tlačítka v patičce |
|---|---|---|
| Nová, neuložená | / | Uložit odkaz → vytvoří slug, zkopíruje odkaz, přesměruje na /t/<slug>, uloží editační klíč do prohlížeče. |
| Uložená, jsi vlastník | /t/<slug> | Uložit změny (aktivní jen když je co uložit) · Kopie (nový slug, původní zůstane) · v sekci Tvoje trasa navíc Smazat trasu a Editační odkaz. |
| Uložená, nejsi vlastník | /t/<slug> | Uložit jako kopii – úpravy se uloží pod novým odkazem, původní zůstane. |
Odkazy v sekci uložené trasy
- Kopírovat odkaz –
/t/<slug>, veřejný, pro sdílení. - Odkaz na prezentaci –
/t/<slug>?present=1, otevře se bez panelu. - Editační odkaz (jen vlastník) –
/t/<slug>?key=<editKey>. Po otevření se klíč ověří, uloží do localStorage daného prohlížeče a z URL zmizí. Neposílej veřejně. - Smazat trasu (jen vlastník) – po potvrzení nevratně smaže; odkaz vrátí 404.
Jak funguje vlastnictví
Při vytvoření trasy server vygeneruje 24znakový edit_key (~120 bitů) a vrátí ho jednou v odpovědi. Klient ho uloží do localStorage["cestounecestou:editkey:<slug>"]. Při otevření trasy klient klíč ověří HEAD požadavkem, takže editační UI se zobrazí jen s platným klíčem; neplatný se z úložiště odstraní. Server porovnává klíč přímo ve WHERE klauzuli, bez shody se nic nezmění.
Režim prezentace
Zapneš tlačítkem ▶ Prezentace nebo parametrem ?present=1. Panel je skrytý, mapa na celou obrazovku, lišta přehrávače zůstává. Doporučený postup: zapnout Mapa sleduje jízdu, přiblížit tak, aby byla trasa čitelná, Mezerník. Pro plátno bez lišty prohlížeče použij F11.
Dopravní prostředky
Vše je definováno v lib/types.ts v objektu VEHICLES. Přidání nového prostředku = nový záznam + rozšíření typu VehicleId a check constraint ve schema.sql.
| Pole | Význam |
|---|---|
icon | Emoji pro textové kontexty (OG popis). |
img | Ikona markeru na mapě, pohled shora, míří nahoru. Cesta v /public. |
menuImg | Ikona do výběru a lišty přehrávače, boční pohled. |
angle | Korekce natočení ve stupních, když obrázek nemíří přesně nahoru (180 = míří dolů). Běžně 0. |
size | Výška markeru v px. Šířka se odvodí z poměru stran obrázku. |
trailer | Volitelné tažené vozy – viz Vlaková souprava. |
label | Zobrazovaný název. |
kmh | Průměrná rychlost pro odhad času. |
route | mapbox · brouter · straight · greatcircle – viz Routování. |
profile | Jen pro mapbox: driving nebo cycling. |
Výchozí hodnoty
| Prostředek | Routing | km/h | Velikost | Poznámka |
|---|---|---|---|---|
| 🚗 Auto | Mapbox driving | 80 | 52 px | |
| 🚆 Vlak | BRouter rail | 110 | 84 px + 3× vagon 88 px | po kolejích dle OSM; fallback přímé spojnice |
| ✈️ Letadlo | ortodroma | 800 | 64 px | |
| 🚲 Kolo | Mapbox cycling | 18 | 56 px | cyklostezky a vedlejší silnice |
Ikony a obrázky
- PNG s průhledným pozadím. Při generování žádej sytě zelené pozadí (#00FF00) a odstraň ho v editoru – „transparent" u generátorů obrázků často vyrobí falešnou šachovnici.
- Marker se otáčí kolem středu obrázku, proto vozidlo vycentruj a ořízni těsně (pár px okraje). Nezvětšuj do čtverce – obdélník je v pořádku.
- Výška obrázku = délka vozidla na obrazovce (
size). Průhledný okraj se počítá do délky, což u vlaku vytvoří mezery mezi vozy. - Pohled shora s mírným nadhledem (cca 20° náklon) funguje ve všech směrech jízdy; klasický „3/4 pohled" vypadá špatně, když vozidlo míří dolů.
Prompt pro generování (základ)
Flat cartoon comic-style vehicle icon for a travel map marker, seen from above at a
high angle (bird's-eye view tilted about 20°, roof dominant). The vehicle points
straight UP. Bold thick dark outlines, simple rounded shapes, bright flat colors,
small white glossy highlights, no gradients, no text, no ground, no shadow, no
scenery, no rails, no road. Centered, ~85% of canvas, plain solid #00FF00 background.
Square 1024×1024 PNG, readable at 48 px.
Paleta appky: červená #E63946, tmavě modrá #1B2A41, krémová #EDE6D8.
Vlaková souprava
Vlak je lokomotiva (img) + trailer.count vagonů (trailer.img), každý jako samostatný marker. Každý vůz má vlastní pozici na trase a vlastní natočení, takže se souprava v oblouku ohýbá.
train: {
img: "/vehicles/train-loco.png", size: 84,
trailer: { img: "/vehicles/train-car.png", count: 3, size: 88, gap: 0 },
…
}
| Pole | Význam |
|---|---|
count | Počet vagonů. |
size | Délka vagonu v px (výška obrázku). |
gap | Mezera mezi vozy v px. Může být záporná – vozy se překryjí (užitečné, když má PNG průhledný okraj). |
Rozestupy jsou v pixelech a přepočítávají se na metry podle aktuálního zoomu (metersPerPixel v geo.ts), takže souprava drží pohromadě při libovolném přiblížení. Každý vůz je tuhé těleso s oběma konci na trati (viz Animace), proto se souprava v obloucích ohýbá jako skutečný vlak. Při změně zoomu v pauze se přeskládá.
Routování tras
| Režim | Jak | Kde |
|---|---|---|
mapbox | Mapbox Directions v5, geometries=geojson&overview=full, všechny zastávky jako waypointy v jednom požadavku (limit 25). Volá se přímo z prohlížeče s public tokenem. | RouteApp.tsx |
brouter | Železnice. Klient volá POST /api/rail; server se ptá veřejné instance brouter.de s profilem rail (OSM koleje) a identifikuje se hlavičkou User-Agent cestou-necestou (https://cestou-necestou.online; route presentation app). Odpověď se kešuje 30 dní v Next Data Cache, takže se stejná kombinace zastávek počítá jednou. Timeout 55 s (maxDuration = 60). | app/api/rail/route.ts |
greatcircle | Ortodroma mezi po sobě jdoucími zastávkami, 64 segmentů na úsek (greatCircle). | geo.ts |
straight | Přímé spojnice zastávek. Použije se jako fallback, když router selže. | – |
Když router selže (síť, limit, BRouter nenajde trať), appka spadne na přímé spojnice a zobrazí toast. Geometrie se do DB neukládá – počítá se při každém načtení (u vlaku z cache).
rail routuje po všem, co má v OSM koleje (včetně tramvají a vleček), bez jízdních řádů. Je to hobby server bez garance dostupnosti – proto cache a fallback. Kdyby přestal stačit: OpenRailRouting (Geofabrik, self-host v Dockeru, rozlišuje elektrifikaci a rozchod), Transitous (plánování podle jízdních řádů, nutná dohoda s provozovateli). Google Routes transit má 10 000 volání měsíčně zdarma, ale výsledky smí být zobrazeny jen na Google mapě.Animace
Trasa je pole bodů [lat, lng] s kumulativní vzdáleností (cumulative). Stav animace (pos v km, playing, …) žije v useRef, aby se React nepřekresloval každý frame – mapa se aktualizuje přímo (setData zdroje trail, setLngLat markerů).
| Parametr | Hodnota | Kde |
|---|---|---|
| Rychlost jízdy | speed × 15 px/s na obrazovce (speed 1–10 → 15–150 px/s); v km/s se přepočítává podle zoomu každý frame – při přiblížení vozidlo zpomalí, při oddálení zrychlí | tick() |
| Natočení vozidla | tětiva mezi zadním a předním bodem vozu na trase (délka vozu = size px → km podle zoomu); pozice = střed tětivy | placeConsist |
| Vyhlazení otáčení | podle zoomu: 45 % rozdílu za frame při zoomu ≥ 12, 90 % při zoomu ≤ 6 (lineárně mezi); při skoku posuvníkem bez vyhlazení | CONSIST.SMOOTH_* |
| Velikost soupravy | podle zoomu: 100 % velikosti ze size při zoomu ≥ 12, 55 % při zoomu ≤ 6 | CONSIST.SCALE_* |
| Zjednodušení trasy | Douglas–Peucker, tolerance 8 m (jen Mapbox/BRouter geometrie) | simplify v geo.ts |
| Max. krok mezi framy | 0,1 s (po přepnutí záložky se neposkočí) | tick() |
Vozidla jsou modelována jako tuhá tělesa na trati: přední i zadní bod vozu leží na trase, natočení je tětiva mezi nimi. Drobné klikatiny geometrie (kolejiště, výhybky) tak délka vozu sama vyprůměruje a na malém zoomu, kde jeden vůz měří desítky km, se vůz natáčí podle celkového směru trati. pos je přední bod hlavního vozu; vagony se zavěšují za sebe (přední bod = zadní bod předchozího − gap). Před startem se trasa extrapoluje dozadu, aby souprava vyjížděla zpoza startu. Rychlost, smyčka a sledování se čtou z settings refu každý frame.
Vrstvy na mapě
| Id | Popis |
|---|---|
ghost | Celá trasa, tmavě modrá přerušovaná, 40 % krytí. |
trail-halo + trail | Ujetá část – bílý podklad 8 px a červená 4 px linka. |
| markery zastávek | mapboxgl.Marker s tečkou a popiskem; start a cíl vyplněné. |
| marker vozidla (+ vagony) | mapboxgl.Marker s rotationAlignment: "map", rotace = azimut + angle. |
Architektura
- Server (Vercel Functions, Node): stránky
/a/t/[slug], API pod/api/routes. Přístup k DB jen tady (lib/db.ts). - Klient: jedna velká komponenta
RouteApp.tsx(mapa, panel, animace, uložení). Mapbox Directions i Geocoding volá prohlížeč přímo. - Data: tabulka
routesv Neonu. Trasa = zastávky + prostředek; geometrie se nepersistuje. - Styl:
app/globals.css, CSS proměnné; mapbox CSS importované jako první, aby ho pravidla appky mohla přebít.
Struktura souborů
API reference
Všechny odpovědi jsou JSON. Chyby mají tvar { "error": "text" }. Editační operace vyžadují hlavičku x-edit-key.
POST/api/routes
Vytvoří trasu. Tělo:
{
"vehicle": "car" | "train" | "plane" | "bike",
"stops": [ { "lat": 50.08584, "lng": 14.42295, "name": "Praha" }, … ], // 2–25
"title": "Volitelný název" // max 120 znaků
}
Odpověď 201: { "slug": "k7m2xq4", "editKey": "…24 znaků…" }. editKey se vrací jen tady, nelze ho později získat znovu. Kolize slugu se řeší až 5 pokusy.
GET/api/routes/:slug
Vrátí { slug, title, vehicle, stops }, jinak 404. Zvýší views.
HEAD/api/routes/:slug
Ověření klíče: 204 pokud x-edit-key sedí, jinak 403. Bez těla.
PUT/api/routes/:slug
Přepíše trasu. Tělo stejné jako u POST. 401 bez klíče, 403 při neshodě, 400 při neplatných datech, 200 { slug }.
DELETE/api/routes/:slug
204 po smazání, 401/403 jako u PUT.
POST/api/rail
Železniční geometrie přes BRouter. Tělo { "stops": [ { "lat", "lng" }, … ] } (2–25). Odpověď { "path": [[lat, lng], …], "points": n }. 502 když je BRouter nedostupný, 422 když trať nenajde (text chyby v error). Klient v obou případech použije přímé spojnice.
Validace (lib/validate.ts)
- Prostředek musí existovat ve
VEHICLES. - 2–25 zastávek, souřadnice v rozsahu, zaokrouhlené na 5 desetinných míst.
- Název zastávky max. 120 znaků; prázdný se nahradí souřadnicemi.
Bezpečnost
- Mapbox token je veřejný z principu; chraň ho URL restrikcí a nikdy mu nedávej secret scope.
- DATABASE_URL je jen na serveru; klient s DB nemluví.
- Editační klíč se přenáší jen hlavičkou nebo jednorázově v URL (
?key=), odkud se po ověření odstraní. V DB je uložen jako SHA-256 hash (lib/hash.ts) – únik databáze neumožní editaci tras. Pro starší trasy s klíčem v čistém textu je veschema.sqlzakomentovaná migrace (pgcrypto). - Názvy zastávek se do DOM vkládají přes
escapeHtml(popisky markerů) nebo React (panel). - Rate limit (
lib/ratelimit.ts): 10 uložení/min a 6 železničních výpočtů/min na IP (odpověď429). Limiter je in-memory, tedy per instance funkce – pro tvrdší ochranu přidej pravidlo ve Vercel Firewall. - Bezpečnostní hlavičky (
next.config.mjs):X-Content-Type-Options: nosniff,X-Frame-Options: DENY,Referrer-Policy: strict-origin-when-cross-origin,Permissions-Policybez kamery/mikrofonu/polohy.
SEO
Vše je řešeno přes Next.js Metadata API, bez externích balíčků. Základem je NEXT_PUBLIC_SITE_URL – musí být nastavená při buildu, jinak sitemap i canonical ukazují na Vercel alias.
| Co | Kde | Poznámka |
|---|---|---|
/sitemap.xml | app/sitemap.ts | Jen / a dokumentace. Uložené trasy záměrně ne – jsou to sdílené odkazy uživatelů. |
/robots.txt | app/robots.ts | Povoluje vše kromě /api/, odkazuje na sitemapu. |
| Title, description, keywords, canonical, robots | app/layout.tsx | Title template %s · Cestou necestou; canonical /. |
| Open Graph + Twitter karta | app/layout.tsx, app/opengraph-image.tsx | Obrázek 1200×630 generovaný na edge (next/og) – brand a stopa. |
| OG obrázek každé trasy | app/t/[slug]/opengraph-image.tsx | Název trasy (nebo „Start → Cíl"), prostředek a počet zastávek. Náhled v chatech tak ukazuje konkrétní cestu. |
| Canonical trasy, noindex u 404 | app/t/[slug]/page.tsx | Trasy se indexovat mohou (kdyby ne, přidej robots: { index: false } do generateMetadata). |
JSON-LD WebApplication | app/page.tsx | Strukturovaná data pro Google + skrytý <h1> (vizuální hlavičku má aplikace vlastní). |
| Favicon | app/icon.svg | Next ho zaregistruje automaticky. |
Google Search Console
- search.google.com/search-console → Přidat vlastnictví → typ Doména →
cestou-necestou.online. - Ověření DNS TXT záznamem u registrátora domény (Vercel → Domains ho umí přidat, pokud DNS spravuje Vercel).
- Sitemaps → přidat
https://cestou-necestou.online/sitemap.xml. - Kontrola URL → „Požádat o indexování" pro
/.
Kontrola náhledů: Facebook Sharing Debugger, X Card Validator, nebo jednoduše vložit odkaz do chatu (WhatsApp, Messenger, Slack).
Řešení potíží
| Příznak | Příčina | Řešení |
|---|---|---|
| Vercel: No Output Directory named "public" | Framework Preset „Other" nebo package.json v podsložce | Settings → Build: preset Next.js, správný Root Directory. vercel.json má "framework": "nextjs". |
Mapa prázdná, styl a fonty se načítají, žádné .vector.pbf | Kontejner mapy má 0 px výšku (CSS .mapboxgl-map { position: relative } přebilo pravidlo appky) | Opraveno: mapbox CSS je importované jako první v globals.css, selektor .mapwrap .map. Neměň pořadí importů. |
| Text „Chybí NEXT_PUBLIC_MAPBOX_TOKEN" | Proměnná nebyla při buildu | Nastav ji ve Vercelu a Redeploy. |
| Marker zobrazuje text (např. „Vlak") místo obrázku | PNG na dané cestě neexistuje (404) | Ověř URL /vehicles/….png v prohlížeči; zkontroluj názvy a že je nasazený aktuální types.ts. |
| Vozidlo je tenká čárka / vagony s mezerami | PNG má velké průhledné okraje | Ořízni těsně; případně záporný gap. |
| Vozidlo jede pozpátku | Obrázek nemíří nahoru | Otoč PNG v editoru nebo nastav angle. |
| Vozidlo se „cuká" | Šum v geometrii trasy | Řeší model tuhého tělesa + simplify; ladit lze toleranci 0.008 km a konstanty CONSIST v RouteApp.tsx (vyhlazení a velikost podle zoomu). |
| Router nedostupný – použity přímé spojnice | Mapbox Directions nebo BRouter selhal (limit, síť, >25 zastávek, trať nenalezena) | Zkontroluj konzoli / odpověď /api/rail; u vlaku zkus zastávku posunout blíž ke kolejím. |
| Vlak jede po tramvajové trati nebo vlečce | Profil rail nerozlišuje typ kolejí | Přidej mezibod na správné trati. |
| Výpočet vlakové trasy trvá dlouho | BRouter počítá dlouhé tratě desítky sekund | Poprvé je to normální; podruhé jde z cache. Limit funkce je 60 s. |
| Uložení vrátí 500 | Chybí tabulka / sloupce | Spusť schema.sql; zkontroluj DATABASE_URL. |
| Nevidím tlačítka editace u své trasy | Klíč není v tomto prohlížeči | Otevři editační odkaz, nebo ulož jako kopii. |
| Po rozbalení zipu je nasazená stará verze | Přepsány jen některé soubory | Porovnej podle struktury; zejména lib/types.ts, RouteApp.tsx, globals.css. |
Limity a licence
- Max. 25 zastávek (limit Mapbox Directions i validace API).
- Vlak i kolo jedou podle dat OpenStreetMap – kde OSM koleje nebo cyklostezku nezná, trasa je horší. BRouter veřejný server je bez SLA.
- Mapbox: nutná atribuce (zůstává v rohu mapy), free tier viz výše. Podmínky: mapbox.com/legal/tos.
- OpenStreetMap data (© přispěvatelé OSM, ODbL) – atribuce v mapě.
- Fonty Space Grotesk a IBM Plex Mono (OFL) přes Google Fonts.
- Neon free tier: sdílený výpočet, uspává se po nečinnosti – první požadavek po pauze může trvat ~1 s.
Možné rozšíření
- Zastávky s obsahem – fotka a text, které se ukážou, když vozidlo dojede do zastávky (pauza animace, karta v liště).
- Tematické podklady – satelit pro letadlo,
streetspro město; přepínač v panelu. - Export videa – záznam canvasu (
MediaRecorder) do WebM pro sociální sítě. - Jízdní řády pro vlak přes Transitous (skutečné spoje, přestupy, časy).
- Seznam mých tras – stránka s trasami, ke kterým má prohlížeč klíč.
- Hash editačního klíče v DB.