feat/atlas-plan
needs attention1abe7d0 · fullPR #307reviewed 2026-07-14 02:53 UTC0H · 4M · 8L · 6I- Purpose
- Public GEO/SEO atlas showing Mexico's energy infrastructure — a differentiator for API leads and AI answer engine visibility
- Goal
- Add three new map layers (planned CFE projects, private-sector generation pipeline, planned transmission) + fix DG annualization + PostHog engagement insights
- Sub-goals
- SG-1: Private-generation layer — 18 CNE/SENER Atención Prioritaria renewables (dec-2025), MIA-derived coordinates, toggleable
- SG-2: Planned-transmission layer — Plan SEN 2025-2030 lines and substations, schematic routes
- SG-3: CFE construction/planning projects layer + Hidro Peñitas rehab fix
- SG-4: Plant COD backfill (227→311) and OSM re-geocode (243 matched, unmatched dimmed)
- SG-5: DG panel 2025 data + annualization fix for irregular CNE semiannual periods
- SG-6: PostHog growth dashboard insights for atlas engagement
- What
- Single commit re-isolating atlas work onto current main. index.html: 3 new data fetches, 6 new layers, 4 popup handlers, dgPeriodSpanYears, e_note. Six JSON files updated/added. PostHog Terraform: 7 insights + 7 dashboard tiles.
- Why
- Re-isolation PR (#295 diverged from main). Closes the gap the CFE-only layer left by adding the private developer pipeline (3,312 MW) and planned transmission corridors.
- Areas
- apps/web/public/atlas+86−17infra/posthog+256−0
- Blast
- 2 areas, 9 files, +342/-17 lines. Static HTML+data (no build) + Terraform. Zero platform-app impact.
Findings · 18
correctness3
PostHog engagement insight uses EventsNode with $session_duration — will show null/zero
infra/posthog/insights.tf
growth_atlas_engagement_time: $session_duration is a session property, not an event property. EventsNode math_property reads event-level properties. Will silently produce 0/null. Fix: use SessionsNode with math='median'/'avg' and no math_property.
enabled filter uses string 'true' for a boolean PostHog property (pre-existing pattern)
infra/posthog/insights.tf
Coordinate order, MapLibre expressions, dgPeriodSpanYears all verified correct
apps/web/public/atlas/index.html
security3
No SRI hash on maplibre-gl loaded from unpkg CDN
apps/web/public/atlas/index.html
Pre-existing gap. Compromised CDN = same-origin access via the iframe. Add integrity= hash to the script tag.
Four new popup handlers extend unsanitized setHTML() pattern
apps/web/public/atlas/index.html
MapLibre setHTML() = innerHTML with no sanitization. Static data source keeps risk low today but pattern is structural.
External GitHub raw fetch (demand/PND) into innerHTML with no schema validation
apps/web/public/atlas/index.html
conventions2
layer_label rename in postMessage bridge is undocumented — latent trap for future instrumentation
apps/web/public/atlas/index.html
Atlas event names consistent; GROUPS/TOGS pattern correct; dashboard layout contiguous
infra/posthog/insights.tf
tests2
No CI JSON schema validation for atlas data files
apps/web/public/atlas/data/private_generation.json
Terraform PostHog insights require no unit tests
infra/posthog/insights.tf
improvement4
txColor redundant explicit arms for licitacion/planeacion that match the fallback default
apps/web/public/atlas/index.html
e_note CNE/SIPyME note is a long inline string in sync() — will stale as data evolves
apps/web/public/atlas/index.html
privFC p.st→stg correct: st is battery storage MW in private_generation.json
apps/web/public/atlas/index.html
dgNatAvgState non-annualization correct — kW/system ratio is span-independent
apps/web/public/atlas/index.html
seo4
atlas/index.html missing <meta name=description> and <link rel=canonical>
apps/web/public/atlas/index.html
Pre-existing. Static file — Next.js metadataBase doesn't help. Atlas is at sitemap priority 0.85. Needs explicit head metadata.
No OG/Twitter meta tags on atlas page
apps/web/public/atlas/index.html
No JSON-LD structured data (Dataset/Map schema)
apps/web/public/atlas/index.html
Sitemap and llms.txt already include /atlas — no regression
apps/web/src/app/sitemap.ts