Gå til hovedinnhold

Claude guidelines for sales/kommune/

Per-kommune sales pages at /kommune/<slug>/ for cold-outreach to Norwegian kommuner. 357 pages, each showing one kommune's Placepoint footprint. Completely separated from markdown/ - different folder, dedicated docs plugin instance, unlisted (no sidebar, no search index, no sitemap, no nav entry), reachable only via direct link.

For the shared sales-tree blueprint (docs plugin idiom, unlisted+caution block, idempotent gen, meta.json + mdx + conditional blocks, AutogenDisclaimer, sales-helpers.ts), see ../CLAUDE.md. This file holds rules specific to the kommune surface.

Mechanics

Env flags for backfills

  • ONLY_KARTLAG=1 - only the 4 kartlag overlays, ~1 min/kommune
  • ONLY_MATCHING_ZOOM=1 - only the rådhus-centered zoom shot
  • ONLY_FOKUS_BILDER=1 - only the aerial-photo shot
  • SKIP_KARTLAG=1 - skip overlays in the full flow
  • KARTLAG_TILE_WAIT_MS=<ms> - override the 18 s WMS-tile wait, e.g. 45000 for the natur/Artsdatabanken layer that occasionally times out

Matching-zoom and rådhus-coords

Matching-zoom centers on the rådhus from ./radhus-coords.json (OSM Nominatim → Kartverket Stedsnavn → centroid fallback). Centroids land in forests/fjords for irregular shapes (Gol). The s-value is 20000 (~5 km wide); earlier captures used s=2400 which was too tight to read as a kommune overview.

Property selection (gotoFirstWorkingCadastre)

Ranks: (1) same-knr first (URL contains /cadastres/<knr>/), (2) keyword score (kulturhus > NAV > rådhus > ...), (3) original table order. Without (1), Gol's eiendom shots showed an Oslo property the kommune happens to also own. All four imagery passes require eiendomHasNoImagery() === false; if every pass fails, no eiendom shots are captured and the generator hides the entire "Detaljer per eiendom" block.

Kartlag tile-wait

18 s minimum (6 s left ~6 failures across 1071 shots; 12 s left a handful; 18 s drops below 0.5 %). For re-shoots of slow layers (Artsdatabanken/natur in particular) override with KARTLAG_TILE_WAIT_MS=45000. The "Offentlig ol. bygg" filter on matching-zoom retries up to 5 times (PR #43, was 3) with 5 s waitFor + 5 s scroll + 5 s click + 3 s post-click per attempt, and 3000×attempt inter-attempt waits; logs ! captured WITHOUT filter when all attempts fail.

setBasemap() destroys the cadastre URL

../../scripts/tour/helpers.ts setBasemap() does page.goto(/map?projectId=...) to reach the basemap selector, which kills any /map/cadastres/... URL. After every setBasemap call inside the kommune section we MUST re-navigate to the chosen cadastre URL before shooting; without that step eiendom-fokus-bilder.png, eiendom-3d.png, and the leietagere shots are captured at the bare /map?projectId view with no Eiendom panel. Fixed in PR #43 - the kommune section now does await page.goto(chosenUrl, ...) after each setBasemap.

captureEiendom3d patience

The "Sentrer kartet" target icon takes 5-12 s to render in big cities; an early hard check skipped the 3D shot. clickSentrerKartet(page, { waitForMs }) accepts an optional wait (12 s in 2D, 8 s in 3D in PR #43) and a missing icon is no longer fatal - the cx/cy/cz URL camera params are the fallback. Aremark and similarly rural kommuner show terrain only in 3D, which is the honest representation of Norway's 3D-mesh coverage outside major cities.

Conditional eiendom blocks

The .mdx template hides two blocks when the corresponding meta keys equal meta.matching (the picker's "no real cadastre" sentinel): the aerial-photo shot (meta.eiendomFokusBilder) and the entire "Detaljer per eiendom" section (meta.eiendomFokus). Without these gates, the 338 fallback kommuner rendered 5+ broken images each. The 19 with a real cadastre URL keep the full section. After a re-run that fills in real URLs, regenerate the affected mdx so the block reappears (delete the file, run gen-kommune-pages.ts).

Comprehensive re-shoot pipeline

Use the template under ../../scripts/kommune/ (copy and adapt) to chain:

  1. SKIP_KARTLAG=1 ONLY_MATCHING_ZOOM=1 run-kommune-shards.sh 4 --all
  2. backfill-eiendom-fallback.sh 4
  3. KARTLAG_TILE_WAIT_MS=45000 ONLY_KARTLAG=1 run-kommune-shards.sh 4 --all
  4. Delete every generated mdx, regenerate, upload-images-only.sh, npm run deploy, set-cache-headers, AFD purge.
  5. scripts/kommune/verify-screenshots.py

Wall-clock ≈ 9 h with 4 workers per shard.

../../scripts/kommune/wholesale-polish.sh is a related runner that re-shoots only kommuner whose meta.json still has old s=2400 matching-zoom URLs OR fallback eiendomFokus URLs, with batched mdx-regen + incremental deploys after every BATCH_SIZE kommuner. Real-world pacing measured 2026-04-29 with WORKERS=8 BATCH_SIZE=30: ~1h 12m per batch (~50 min sharded tour + ~15-25 min deploy). Resumable: the Step A staging script reads each kommune's meta.json and only includes ones still on s=2400 zoom or fallback eiendomFokus, so already-polished kommuner are skipped automatically.

Auth retry behavior in sharded mode

PR #47 fixed the bug where a single Azure B2C auto-login failure dropped the shard's remaining 2-3 slugs (the manual-login fallback was waiting 120 s for human input that never came in unattended runs). Now: when WORKER_INDEX is set in ../../scripts/tour/auth.ts createAuthenticatedContext and B2C fails, we retry once after a 5 s backoff and then throw immediately if it still fails. The shard exits non-zero quickly so the rest of the batch isn't held up; lost slugs (if any) come back as a small targeted re-shoot via KOMMUNE_SLUGS=<csv> run-kommune-shards.sh. Pre-fix loss rate was ~1 % (1 crash in 4 batches on 2026-04-29 lost herøy-mr, hurdal, ibestad).

Audit storage after a deploy

../../scripts/kommune/verify-screenshots.py lists every kommune/img/<slug>/ blob and cross-checks against the expected per-kommune set (reads meta.json so the conditional aerial shot is checked only where required). Outputs /tmp/kommune-screenshot-audit.txt and /tmp/kommune-screenshot-bad-slugs.txt (comma-separated slug list, ready for KOMMUNE_SLUGS=$(cat ...) re-shoot).