Project Plateau
Project Plateau: four glass plates, one living valley, and the road back to camp.
翻訳待ち
No updates detected yet. GitHub releases will appear here.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗A free static website that randomly picks a Zwift route from the worlds active that day.
Open the site, choose Ride or Run, optionally set minimum or maximum distance and climbing (in km/m or mi/ft; they apply to the route plus lead-in), and press "Spin". Event-only routes and routes not yet released are left out.
The Calendar tab shows today's worlds, the current Route and Climb of the Week, the climb portals (Watopia's daily climb and France's climb of the month), and a month grid of guest worlds with the weekly challenges across each week. On phones the grid becomes a list. Its code is in calendar.js.
For badge chasers: tick the routes you have done under "My completed routes" (or press "Mark as done" on a picked route), then set Route badges to "Not done yet". Ride and Run are tracked separately. Progress is saved in the browser on that device; "Copy my progress link" makes a link that loads it on another device or serves as a backup. The link stores one bit per route using the permanent positions in data/route-order.json, which is append-only so old links keep working.
data/schedule.json and data/routes.json are generated by scripts/update_data.py from Zwift's MapSchedule_v2.xml and GameDictionary.xml. Each route also gets a link to its Zwift Insider page when one exists; the results are cached in data/route-links.json so only new routes are checked, and misses are retried weekly. data/weekly.json holds Route and Climb of the Week, read from Zwift Insider's Ride of the Week calendar (Zwift publishes no data file for them); if that page can't be read, the last good file is kept and an alert issue opens. data/portal.json holds the climb portal rotation from Zwift's PortalRoadSchedule_v1.xml: Watopia's daily portal climb and France's Climb Portal of the Month, with Zwift Insider links; these are shown on the Calendar only, never in the spinner. The "Update Zwift data" GitHub Action runs it twice a day (04:23 and 17:23 UTC) and commits only when something changed. To run it by hand: Actions tab, "Update Zwift data", "Run workflow".
Add ?now= with a UTC time to the page URL to see what the picker does at that moment, for example ?now=2026-10-05T04:02Z.
GitHub Pages lets browsers cache files for 10 minutes. When you change app.js, calendar.js or styles.css, bump the ?v= number on its tag in index.html in the same commit, so visitors never get the new page with an old script or stylesheet.
The daily Action opens a GitHub issue when something needs a look, and closes it automatically once things are fine again:
data-alert): Zwift's world schedule is about to run out with no newer one published, or a guest world appears with no known partner world (add it to GUEST_PAIRS in scripts/update_data.py).update-failed): the run itself failed. The site keeps working with the last good data.To test it, run the Action by hand with "Open a test alert issue" ticked; the next normal run closes the test issue.
Every push runs the "Tests" GitHub Action:
python3 -m unittest discover -s tests (no network needed).node tests/run.js (needs Playwright: npm install --no-save playwright and npx playwright install chromium). It serves the site locally with a frozen copy of the data from tests/fixtures/data, so results don't change as the daily data updates. Run one suite with node tests/run.js calendar. If a change needs newer data in the tests, refresh the snapshot with cp data/*.json tests/fixtures/data/.