Austria-Maps

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

What this is

A single self-contained HTML page (index-at.html) showing an interactive choropleth map of Austria’s 94 political districts (politische Bezirke, including Vienna as one Statutarstadt and the 23 Statutarstädte/Bezirke of the other states), with a popup-menu toggle between eleven metrics: average net income of employees, life expectancy at birth, total fertility rate, mean annual temperature, annual precipitation, population density, a live current-temperature reading fetched client-side from Open-Meteo, the strongest party in the 2024 Nationalratswahl (National Council election), the unemployment rate, the foreign-population share, and a maths education-standards score (published only per Bundesland, not per district — see “Data provenance” below). The page supports DE/IT/EN language switching and a manual light/dark theme toggle (with a glow accent in dark mode). There is no build step, no server-side code, and no package.json — the page is opened directly in a browser or served as a static file. It is deployed via GitHub Pages at https://helmutqualtinger.github.io/Austria-Maps/.

This repo mirrors the structure of two sibling projects, Italia-Maps (107 Italian provinces) and Svizzera-Maps (26 Swiss cantons), at the next level down in feature/place count. All three were generated by mirroring each other’s structure line-for-line rather than by sharing code, so they can and do drift independently — if you’re porting a fix from one to the others, check the sibling repos for the equivalent logic rather than assuming it doesn’t exist here.

Running / previewing

There is no build or test command. To preview locally:

python3 -m http.server 8732
# open http://localhost:8732/index-at.html

(file:// URLs work for a plain double-click open, but some browser extensions/tools can’t navigate to file://, so prefer a local server when using browser automation.)

Architecture

Everything lives in index-at.html: CSS in a <style> block, then a <script> block that defines MAP_DATA_AT (district boundaries + per-district stats) inline as a JSON literal, followed by the rendering/interaction logic. There is no framework, no build tool, and no external CDN dependency — SVG district shapes are pre-projected into path d-strings at data-prep time (see below), not computed in the browser. CSS class and JS identifiers use district (path.district, selectDistrict()), matching canton in Svizzera-Maps and province in Italia-Maps.

Key JS pieces in index-at.html (same pattern as the sibling repos):

Data files (source data, not read by index-at.html at runtime)

index-at.html is fully self-contained — the JSON files below are kept as human-readable source data and provenance, but the page does not fetch them:

Data provenance

If you need to re-fetch or extend a metric from Statistik Austria: their OGD (Open Government Data) catalog (data.statistik.gv.at/web/catalog.jsp) does not currently include a bulk district-level life-expectancy or fertility dataset — both had to be pulled from the “regionale Gliederungen” annex tables of the Sterbetafeln/Fertilität .ods releases instead (see above), which are not part of the OGD catalog. Check that catalog first for anything new, but don’t assume a district-level table exists there just because a Bundesland- or NUTS-level one does.

Regenerating index-at.html from the JSON files

There is no script in this repo that does this automatically — past sessions injected updated map_data_at.json content into index-at.html via a one-off Python snippet that replaces the const MAP_DATA_AT = …; literal in place (matching from "const MAP_DATA_AT = " to the following ";\n\nfunction hexToRgb" — the embedded data blob sits between RAMP and the hexToRgb/rgbToHex/rampColor/I18N block: RAMP first, then MAP_DATA_AT, then everything else, the same relative order as the sibling repos use for RAMP/MAP_DATA_CH/ MAP_DATA). If you add a new metric or refresh a data year, update map_data_at.json first, then re-run an equivalent replace rather than hand-editing the embedded JSON blob.