Generate and check the website
The product introduction and feature tours live in docs/. Documentation is generated from the audience folders in documentation/; the installed guide uses the same sources.
The homepage update link, news, and docs/releases/ are generated from the
versioned release notes. Edit
those Markdown files, not generated pages or marked homepage/sitemap regions.
These helpers do not publish anything.
The same generation writes docs/releases/releases.json from published notes
and the verified image catalog. Drafts stay out of update offers. See the
publication and E2E flow.
Shared colors and six text-size roles live in docs/site-theme.css. Reuse those
tokens in homepage, guide, and release styles; reserve blue for actions and accents.
The installed guide loads documentation/tools/website/guide-theme.js before its
styles to follow the app's saved theme. Dark guide colors live in
documentation.css; print output uses the light palette.
Guide navigation uses compact desktop rows and larger mobile targets. The topic
menu and article outline collapse below 960px. Edit the shared layout in
generate_documentation.py, documentation.css, and documentation.js, then
regenerate both outputs.
App guide links retain the same-origin app tab as their opener. The installed
guide-navigation.js returns to that running tab and closes the guide on
Back to app. Direct guide visits use the app link as a fallback. Links outside
the guide open separately without access to the app tab.
In an active Python virtual environment, install the release generator's dependency, then generate and check the pages:
python -m pip install -r documentation/tools/website/requirements.txt
python documentation/tools/website/generate_documentation.py
python documentation/tools/website/generate_releases.py
python documentation/tools/website/generate_documentation.py --check
python documentation/tools/website/generate_releases.py --check
python documentation/tools/website/check_documentation.py
python documentation/tools/website/check_memory_profile.py
python -m unittest discover -s documentation/tools/tests -p 'test_website_releases.py'
node --test documentation/tools/tests/test_site_analytics.mjs
python3 documentation/tools/build.py docs regenerates the guide and checks
release-page freshness. Regenerate release pages with generate_releases.py
after editing release notes. Use build.py docs --check to check both outputs
without writing.
The memory check requires the Docker Compose CLI but does not start containers. It compares service limits, paired tuning settings, and the memory guide's Compose example with the shipped templates.
Generation reads the explicit teaser: >- metadata field for banner, news,
archive summaries, and release-page descriptions. It inserts that same teaser
below the H1 in full website and GitHub notes. Teasers are plain text, limited
to 160 characters; see the authoring convention.
The news headline and banner identify the version independently of chapter order.
The banner sits above the homepage hero and links to the full notes.
A null publication date means Upcoming; the latest
published release is selected by date and version. Generated output is committed
with its Markdown source.
The mirror publisher refreshes this output before copying the site and prepares
the same teaser and Markdown body for GitHub Releases without metadata. Use the same virtual
environment when running ../mtl-explorer-private/publish-to-github.py.
python3 documentation/tools/website/check_seo.py
python3 -m http.server 8765 --bind 127.0.0.1 --directory docs
With the preview running, check its HTML against the working copy:
python3 documentation/tools/website/check_seo.py --base-url http://127.0.0.1:8765/
The check covers canonicals, old-domain references, unique metadata, H1/main,
JSON-LD, breadcrumbs, image dimensions, local resources/fragments, sitemap,
robots, and navigation reachability. --base-url additionally reads the HTML,
sitemap, and robots over HTTP and compares their bytes with local files. It
does not fetch every asset or verify external links, indexing, or rich-result
eligibility. The offline check is the default.
Synthetic GPX examples are generated by generate_examples.py.
See the example notes.
Real screenshots of year filters use the public demo dataset; see the
capture notes.
Segment screenshots were captured on 6 September 2026 with public demo routes in an isolated
local backend; see the capture notes.
Google Health images are real app captures with synthetic data; see their source notes. Capture from the current app through the Codex in-app browser, using public or fully synthetic data. Keep raw captures on the external drive. With Pillow available, encode the two JPEG captures at the website's four WebP sizes:
python documentation/tools/website/prepare_health_screenshots.py /Volumes/EXT_HD_1TB/mytraillog/website-health-refresh/2026-10-03
The helper preserves screenshot content and aspect ratio, never upscales, and reports
dimensions and byte sizes. Match HTML dimensions and srcset widths to that
output; update image cache versions and source notes when replacing captures.
When a release is explicitly requested, use ../mtl-explorer-private/publish-to-github.py and then run
the read-only check against https://mtl-explorer.com/. Inspect Search Console
separately for the selected canonicals and the sitemap's successful read.
Product tours, release pages and every generated public documentation page load
analytics from docs/site-analytics.js. The installed app guide instead loads
guide-analytics.js, which follows the application's optional Umami configuration.
The page's
hostname selects the configuration automatically:
| Page hostname | Tracker host | Umami website ID |
|---|---|---|
mtl-explorer.com |
stats.mtl-explorer.com |
eb0877dd-d24d-4a5d-8735-eaeed78f0f38 |
localhost, 127.0.0.1, [::1] (any port) |
umami.me.mindalyze.com |
c221b96a-f9e6-4f6a-b272-2f6649371876 |
| Other hostnames or files opened directly | Disabled | — |
The preview command above uses the test website. Publishing the same files at
mtl-explorer.com uses production automatically. The tracker starts asynchronously
after window load and respects Do Not Track in both environments. Page code does
not wait for analytics. Query strings and fragments are excluded, including
campaign query parameters. There are no custom click events or tracking-dependent
navigation.
The website and installed guide use Umami's default anonymous visitor and session identification. They supply no Distinct ID and create no custom identifier in local or session storage. Generated public documentation links to the homepage's Site analytics notice.
When changing tracking, verify the selected host and website ID in both environments, then check a blocked/hanging script and a failed/hanging collector in a browser. Pages must finish loading and their links and screenshot controls must work in every case. Intercept test submissions so local verification does not add synthetic visits to the live analytics database.
Component release previews: add --components to prepare_update_preview.
Release manifests and ownership settings: release updates.