| name | add-building-year-city |
| description | Use when adding a new city or town to the Danish Building Years tool, including extracting INSPIRE BBR data, fetching OSM context, updating places.json, and verifying the Svelte app. |
Add a City to Danish Building Years
Use this skill from the repository root when the user asks to add another city/town to the building-year map.
Workflow
-
Pick a city id, display name, postal string, and bbox.
id: lowercase ASCII slug, e.g. roskilde.
name: display name, e.g. Roskilde.
postal: BBR postal string, e.g. 4000 Roskilde.
bbox: south,west,north,east.
-
Probe BBR address formatting before extraction.
sqlite3 data/downloads/DK_INSPIRE_BBR.gpkg <<'SQL'
.headers on
.mode tabs
select addressRepresentation
from building
where addressRepresentation like '%CITY_OR_POSTAL%'
limit 30;
SQL
Common patterns:
- Small localities may be stored as
Street, Locality, Postal City, so use BBR_LOCALITY and BBR_POSTAL.
- Larger postal cities may be stored as
Street, Postal City, so use BBR_ADDRESS_PATTERN='%, 4000 Roskilde'.
- Danish letters are not always used in locality names; Årsdale is stored as
Aarsdale.
- Make sure the national BBR GeoPackage exists.
uv --project api run building-years download-bbr
- Generate the city with the root command.
For postal-pattern cities:
uv --project api run building-years add-city \
--id roskilde \
--name "Roskilde" \
--postal "4000 Roskilde" \
--bbox "55.613,12.03,55.675,12.145"
For locality-based cities:
uv --project api run building-years add-city \
--id svaneke \
--name "Svaneke" \
--locality "Svaneke" \
--postal "3740 Svaneke" \
--bbox "55.13,15.13,55.1455,15.1555"
For exact BBR address patterns:
uv --project api run building-years add-city \
--id aarsdale \
--name "Årsdale" \
--postal "3740 Svaneke" \
--address-pattern "%, Aarsdale, 3740 Svaneke" \
--bbox "55.1005,15.134,55.1145,15.1585"
The command generates OSM buildings/context, extracts BBR points/records, and
updates data/places.json.
- If manually editing
data/places.json, use this shape:
{
"id": "roskilde",
"name": "Roskilde",
"bbrLocality": "",
"postal": "4000 Roskilde",
"bbox": {
"south": 55.613,
"west": 12.03,
"north": 55.675,
"east": 12.145
},
"files": {
"buildings": "roskilde-osm-buildings.geojson",
"context": "roskilde-osm-context.geojson",
"bbrPoints": "roskilde-bbr-inspire-points.geojson",
"bbrRecords": "roskilde-bbr-inspire-records.json"
}
}
The app loads city files through frontend/src/routes/data/[placeId]/+server.ts, so no frontend import is needed after places.json is updated.
Verification
Run:
npm run check
npm run build
Start or restart the dev server:
npm run dev
Verify in the browser:
- The new city appears in the
Place selector.
- Metrics match the generated BBR summary.
- Point mode renders.
- Heatmap mode renders.
- Browser console has 0 errors and 0 warnings.
For large cities, expect the renderer to sample visible BBR dots and aggregate heat cells. The metrics and activity chart should still use the full BBR dataset.
Failure Modes
0 BBR rows usually means the address pattern is wrong. Probe addressRepresentation.
- Browser freezes or black screenshots usually mean too many SVG elements are being rendered; keep full data for metrics, but cap visual render layers.
- Huge client bundles mean city data is being imported into
+page.ts; keep city data behind /data/[placeId].
- Large postal areas can include surrounding villages. Use
BBR_BBOX to scope the extract to the intended city area.