thermograph/frontend/content/pages.yaml

29 lines
1.3 KiB
YAML
Raw Permalink Normal View History

Extract the glossary and static-page SEO copy into a schema-validated content/ tree (#241) The weather-terms glossary (9 entries) and four static pages' SEO title/ description were hardcoded directly in web/content.py - a 1019-line module that also owns all SSR rendering logic - mixed in with code that changes on a completely different cadence and for different reasons. Add content/glossary.yaml and content/pages.yaml (a new repo-root content/ tree, a sibling of backend/ and frontend/ paths.py resolves the same way - the seed of a future thermograph-copy repo per the architecture decision doc's own §4) plus web/content_loader.py: a small loader that validates each file's shape at load time (required fields present and non-empty, no duplicate glossary slugs) and fails loudly on a malformed edit rather than rendering a blank glossary card or an empty <title>. content.py's GLOSSARY dict and the about/privacy/hub/glossary_index page_title/description literals now come from the loader. Scope: only content that is genuinely pure static data with no embedded template logic. cities_flavor.json (Wikipedia extracts, already its own generated file) and the homepage's title/description (embedded in home.html.j2 as Jinja block overrides, a heavily-tested product-critical template) are deliberately left as they are - a future pass, not required for this one. UI microcopy bound to frontend logic stays in frontend/, per the doc's own line between content and frontend. Verified: content/glossary.yaml generated programmatically from the live GLOSSARY dict (not hand-transcribed) and round-tripped byte-for-byte identical against it; content/pages.yaml's four entries checked field-by- field against the original hardcoded strings. Full backend suite green (362 passed, 4 skipped) with zero existing test changes needed beyond one assertion made escaping-aware (a pre-existing Jinja double-escape quirk on the one title containing "&amp;", intentionally preserved not fixed). Built and booted the real Docker image: content/ present at /app/content, and curled /glossary, /glossary/percentine, /about, /privacy from inside the running container - all four render with the exact expected title text.
2026-07-21 01:21:11 +00:00
# SEO title/description for the static pages (not the per-city/per-month pages,
# whose titles are built dynamically from city data in web/content.py). Each key
# is the page identifier passed to content_loader.load_page(); see
# backend/web/content_loader.py and docs/README.md.
pages:
about:
title: "About Thermograph: how the weather grades are calculated"
description: >-
How Thermograph works: ~45 years of ERA5 climate history, a &plusmn;7-day
seasonal window, and empirical percentiles that grade each day relative to
its own location.
privacy:
title: "Privacy | Thermograph"
description: >-
What Thermograph does and does not collect: no tracking, no ads, no
account required, and location that never leaves your browser.
hub:
title: "City climate pages: averages, records and how today compares"
description: >-
Browse climate pages for hundreds of cities worldwide: average
temperatures by month, all-time records, and how today's weather compares
to local history.
glossary_index:
title: "Weather &amp; climate glossary: heat index, feels-like, percentile, and more"
description: >-
Plain-language definitions of weather and climate terms: climate normal,
percentile, temperature anomaly, feels-like, heat index, wind chill,
humidity, and reanalysis.