Dev Log

City Meeting Archives integration (25 cities)

· Claude Opus 4.7 (1M context) · Bot
citiesservice-areascontentaccessibility

What was done

  • New data file src/data/city-video-sources.ts — 25 entries, one per service-area city, with discriminated-union type that enforces the “broken/dead status requires fallbackUrl + statusNote” invariant at type-check time.
  • New component src/components/CityVideoSource.astro — per-city card with tiered badge (Video / Audio / Minutes only), city-specific description, and single primary CTA. Zero client-side JS, no iframe, no thumbnails. Outbound links use rel="noopener noreferrer" to match the site’s referrer-stripping privacy posture.
  • CityPage.astro gained an after-resources slot between Official Resources and FAQ. Slot doc comment updated to include both after-resources and the previously-undocumented before-cta.
  • All 25 city pages now import and render <CityVideoSource citySlug="..." /> — 8 via the new slot on CityPage, 17 via inline placement above their bespoke contact CTA.
  • New source-level verifier src/scripts/verify-city-video-sources.mjs with five checks: coverage, slug integrity, URL shape, broken-status invariants, and component-import presence.
  • Extended src/scripts/verify-build.sh with Check 19: confirms “Meeting archives” renders in the built HTML for all 25 city pages.
  • Wired into the npm run build:verify pipeline via a new verify:sources script that runs before the build.

Why

From the 2026-04-22 source report (.tmp/plans/0002_26_04_22/service-areas-youtube-report.md). Goal: give developers/applicants a way to watch how Council handles similar projects, and reinforce Bailey’s regional coverage by showing consistent structured links across all 25 service-area cities — including the 10 Tier 4 cities that publish only minutes, which appear with a “Minutes only” badge rather than being silently omitted.

Scope decisions locked during brainstorming:

  • Tier 4 included (uniform across 25 cities, no missing pages — Minutes only badge sets honest expectations)
  • No iframes or thumbnails — matches the site’s zero-JS + privacy-conscious posture; the 3 Tier 1 playlist cities aren’t important enough to bifurcate the visual treatment
  • Council only for v1 — data structure (optional headingOverride, room for additional streams) supports future P&Z/Urban Renewal expansion
  • Quarterly manual re-verification — matches the existing city-resources.ts rot-handling pattern

Files affected

Created

  • src/data/city-video-sources.ts
  • src/components/CityVideoSource.astro
  • src/scripts/verify-city-video-sources.mjs
  • docs/superpowers/specs/2026-04-22-city-youtube-integration-design.md
  • docs/superpowers/plans/2026-04-22-city-youtube-integration.md

Modified

  • src/components/CityPage.astro (added after-resources slot, updated slot doc comment)
  • src/scripts/verify-build.sh (added Check 19)
  • package.json (added verify:sources script, updated build:verify to chain it)
  • BACKLOG.md (marked item complete pending signoff, linked to spec)
  • All 25 src/pages/service-areas/*/*/index.astro files (added import + component instance)

Spec drift caught during implementation

The original spec listed Boise as a CityPage-based (“rich”) page. In reality Boise uses a bespoke BaseLayout-based template — likely an artifact of being implemented before CityPage was extracted. The actual breakdown on disk is 8 CityPage-based pages (Eagle, Garden City, Kuna, Meridian, Star, Caldwell, Middleton, Nampa) and 17 bespoke pages (Boise plus all of Blaine, Owyhee, Boise, Elmore counties and the remaining Canyon stubs). The integration logic accommodated both — the only practical difference is rich pages use the slot="after-resources" attribute while bespoke pages place the component inline above the final dark CTA section. Future quarterly-refresh work should not trust the spec’s stub list verbatim — count from the filesystem.

Known gaps / pending

  • Shane / Kelli signoff required before merging to main / deploying. Direct them to one URL per tier:
    • Tier 1: /service-areas/ada-county/garden-city/
    • Tier 2: /service-areas/ada-county/meridian/
    • Tier 3 video: /service-areas/canyon-county/parma/
    • Tier 3 audio: /service-areas/blaine-county/sun-valley/
    • Tier 4: /service-areas/canyon-county/wilder/
    • Murphy heading override: /service-areas/owyhee-county/murphy/
    • Hailey custom GoToMeeting description: /service-areas/blaine-county/hailey/
  • Middleton playlist verification: 60-second manual check (open the channel’s Playlists tab, find a council playlist titled “City Council” or similar, confirm content + freshness). If verified before merge, swap Middleton’s url from the channel to the playlist URL in-PR. Otherwise the upgrade rides with the next quarterly refresh — no dedicated followup PR.
  • Greenleaf URL is HTTP (the city site does not support HTTPS as of 2026-04-22). Inline note in the data file flags this for the next quarterly refresh.
  • No live URL health checks — quarterly manual re-verification via status flags handles rot.
  • P&Z / Urban Renewal streams — Council only for v1; the data structure leaves room to extend (add a second entry per city, or extend CityVideoEntry.sources to an array).
Feedback