Skip to content

CAPAG Funder Scan — Unlock the Money hackday#1

Open
joaquinOEF wants to merge 23 commits into
mainfrom
hackday/2026-06-11/capag-funder-scan
Open

CAPAG Funder Scan — Unlock the Money hackday#1
joaquinOEF wants to merge 23 commits into
mainfrom
hackday/2026-06-11/capag-funder-scan

Conversation

@joaquinOEF

Copy link
Copy Markdown

CAPAG Funder Scan

Overlays Brazil's CAPAG municipal fiscal-capacity ratings (Tesouro Nacional) with CityCatalyst climate data (emissions, climate risk) so climate funders (BNDES/CCFLA) can segment all 5,566 municipalities by creditworthiness × climate need and pick the right instrument per city.

Team: Joaquin van Peborgh · Carole Viaene

What it does

  • Scan — all 5,566 municipalities, multiselect CAPAG tiers × climate-risk chips, synced map + table + URL state
  • Brazil map — Leaflet/CartoDB, CAPAG-colored dots, dot size = selected risk score, zoom-to-selection
  • City panel — fiscal indicators (with explainers), merged multi-source inventory (SEEG + SINIR + SNIS + EPE), CCRA hazards, and a rule-based financing-instrument recommendation
  • Export CSV of the filtered set; EN / PT-BR i18n for the Brazilian funder audience

Revenue connection

OEF as the trust layer in climate-finance deal flow: screening for BNDES/CCFLA, premium CityCatalyst scan + per-city briefs. 2,316 CAPAG-C cities locked out of federal credit = the blended-finance market nobody can see today.

Built to graduate into CityCatalyst

Chakra UI v3 + CC design tokens, CC's i18next stack, .cursor/rules/citycatalyst-style.mdc so conventions carry forward.

Reusable research

research/ has verified CAPAG findings (methodology, 2023 break, data access, the CCRA /current gotcha) for other teams.

🤖 Generated with Claude Code

Joaquin van Peborgh and others added 15 commits June 11, 2026 11:48
- research/: verified CAPAG findings (methodology, 2023 break, gotchas, data access) — reusable by other teams
- scripts/fetch_capag.py: latest Treasury XLSX -> data/capag.json (5,568 municipalities)
- scripts/probe_citycatalyst.py: IBGE<->LOCODE crosswalk via CCRA BR city list (99.96% match) + stratified SEEG/CCRA probe (32/32 live)
- README: status + demo skeleton

Co-Authored-By: Claude Fable 5 <[email protected]>
- Chakra UI v3 + trimmed CC blue_theme tokens (src/lib/theme.ts, from CityCatalyst app-theme.ts)
- Poppins/Open Sans via next/font, same CSS-var wiring as CC
- Explorer rebuilt on Chakra Table/Badge/NativeSelect with semantic tokens
- .cursor/rules/citycatalyst-style.mdc so Cursor sessions follow CC conventions

Co-Authored-By: Claude Fable 5 <[email protected]>
- CityPanel drawer: indicator explainers, SEEG sector emissions (kg->t per CC convention), CCRA hazard bars, rule-based instrument recommendation with visible reasoning
- /api/city/[locode] route: aggregates 14 SEEG sub-sector refs to GPC sectors + CCRA hazards, 24h cache
- scripts/fetch_risks.py + data/risks.json: national CCRA snapshot, 5,566 cities, 0 errors
- Explorer: high-risk hazard filter (>=50) with sort, Top-climate-risk column, clickable rows

Co-Authored-By: Claude Fable 5 <[email protected]>
…s + CC polish

- /api/city: SEEG backbone + SINIR (solid waste) + SNIS (wastewater) + EPE (scope-2/3 energy), per-sector source attribution; completes all 5 GPC sectors
- Multiselect CAPAG tier cards and climate-risk chips (OR semantics, >=50) with Material icons
- CC sector colors + icons on emission bars; hazard icons in table and panel
- CC-style top bar; research/data-access.md updated (SIRENE not available municipally)

Co-Authored-By: Claude Fable 5 <[email protected]>
- Leaflet/CartoDB map synced to filters: CAPAG-colored dots (IBGE centroids via scripts/fetch_centroids.py), dimmed non-matches, dot size scales with selected risk score, click opens city panel
- Theme: add missing base.light/dark tokens (nav title was rendering dark-on-dark); selected tier cards and risk chips now navy #001EA7 with white text
- Table: Top 3 risks column with icons + scores, selected hazards first and bold

Co-Authored-By: Claude Fable 5 <[email protected]>
…t, URL state, zoom-to-selection

- Map left / compact filter rail right (2-col tier tiles, chips, search, match card)
- CAPAG color legend overlay; Clear filters button with active count
- Export CSV of full filtered set incl. all six risk scores
- Filters encoded in URL (?tiers=&risks=&uf=&q=) via one-shot restore + write-only effect (no swap loop)
- Zoom-to-selection fits map bounds to current matches

Co-Authored-By: Claude Fable 5 <[email protected]>
…en map

- Search input + state select + match count + Export CSV now a single full-width bar below the map+filters row (was stacked in the right rail)
- Map height 520->400px (320 on mobile); table rows now visible above the fold

Co-Authored-By: Claude Fable 5 <[email protected]>
- src/i18n: settings/client + en|pt translation.json, mirrors CC's react-i18next setup
- Adapted for single route: static resources (no lazy backend), no LanguageDetector at init;
  LanguageToggle applies stored lang in a mount effect (no hydration mismatch, next-themes style)
- All UI strings via t(); flat dotted keys (keySeparator/nsSeparator false); {{count, number}} Intl formatter (pt-BR 5.566)
- recommend.ts returns i18n keys + vars (not prose) so EN/PT render from one ruleset; hazard vars resolved in CityPanel.renderLine
- Nav language toggle EN|PT; full PT-BR fiscal terminology for Brazilian funders
- cursor rule + README updated

Co-Authored-By: Claude Fable 5 <[email protected]>
…ject matching, context

- data/projects.json + scripts/fetch_projects.py: 76 curated funded LatAm climate projects (sector/instrument/amount/funder/status/coords)
- lib/matchProjects.ts: rule-based retrieval ranking projects by sector×risk×CAPAG-instrument fit (no LLM, deterministic)
- /api/city route: adds city boundary (WKT MULTIPOLYGON -> GeoJSON via wellknown) + city_context (area/region)
- City detail fetch lifted to Explorer, shared by panel + map; CityPanel now presentational
- Panel widened to 2/3 (66vw), two-column: fiscal/emissions/risks | recommendation/projects
- CityMap: draws selected city boundary, fits to it; context stats (area/region/biome) in panel header
- i18n keys for projects section; research/data-access.md + README updated

Co-Authored-By: Claude Fable 5 <[email protected]>
Leaflet panes/controls use z-index up to ~1000; panel overlay was at 10/11 so the map
rendered on top. Bumped overlay to 1500 and panel to 1600.
…atch reasons

Fixes irrelevant matches (e.g. a 1%-transport sector pulling in BRT projects for a 98%-AFOLU city):
- weight project-sector matches by the city's emission SHARE, not top-N rank; drop sectors <10%
- cap climate-risk influence (0.5) below a dominant emission sector so the main driver leads
- handle compound instrument strings (split on ';') for the CAPAG-fit check
- expose match reasons per card ('Matched on: AFOLU emissions · Floods risk') for transparency
- relative score floor + require a sector match

Note: the funded-projects set is urban-infrastructure-heavy, so rural land-use (AFOLU) cities
legitimately have thinner analogues — now surfaces NbS/watershed projects as nearest neighbors.

Co-Authored-By: Claude Fable 5 <[email protected]>
…cing

- New CityBoundaryMap: read-only locator map inside the panel showing the selected city's
  boundary polygon (falls back to a centroid marker), fits to the shape
- Dashboard CityMap reverted to filter-only — no longer draws/zooms to the selected city
  (the dashboard map reflects the active filter; city geography lives in the panel)
- Panel spacing/hierarchy: larger title, p8, gap10/gapY8 between columns, taller bars (8px),
  more rhythm between sections, line-height on body copy — same information, less dense

Co-Authored-By: Claude Fable 5 <[email protected]>
Adds cities.json file which is processed from CityClimateCompass version
of the data to be simpler to index using scripts/extract_city_ids.js.
Joaquin van Peborgh and others added 8 commits June 15, 2026 10:42
…v1, existing data)

Points at the 'enter your mandate -> deployable, leverage-sorted pipeline' vision using only
data we already have (no RCL extraction, no emissions snapshot, no modeling):

- lib/leverage.ts: classify each city's catalytic leverage from CAPAG sub-indicators + n.d.
  blocker flags — graduation candidates (C w/ grade-A debt blocked by savings/liquidity),
  n.d. one-fix-away (specific Siconfi gap), ICF-gated (Dicf/Eicf). Ranks for 'sort by leverage'.
- lib/instrument.ts: CAPAG -> funder-language instrument group (credit/blended/grant_ta/distressed)
- MandateWizard: 3-step Build-a-mandate modal (instrument -> region -> climate) with live match
  count; applies filters + leverage sort and drops onto the table. Same controls also inline in
  the rail (instrument select, high-leverage toggle, match/leverage sort).
- Table: Instrument + Leverage columns (⚡ badge w/ blocker tooltip); both added to CSV export.
- page.tsx threads precomputed leverage onto each Row. Full EN/PT i18n.

Co-Authored-By: Claude Fable 5 <[email protected]>
…) + aggregation cues

Turns the leverage cut from direction-only into real, defensible numbers — no modeling:
- scripts/fetch_fiscal.py + data/fiscal.json: extract real RCL + Dívida Consolidada per
  municipality from the CAPAG XLSX Datalake (RGF anexo 02 absolutes). 5,252 cities. SP RCL
  R$93.8B/DC R$30.7B reproduces the published 0.327 debt ratio exactly.
- lib/headroom.ts: headroom = max(0, 1.2×RCL − DC) (LRF municipal ceiling); unlock = headroom
  for bankable + graduation/n.d.-fix/ICF-gate cities, 0 for plain-C/distressed (no credit channel).
- Leverage column now shows 'unlocks ~R$X' (e.g. Fortaleza C → ~R$9.1B one fix away) and
  bankable headroom; city panel shows real RCL + headroom block.
- Pipeline header: '{total} deployable' (sum of real unlock across matches, e.g. credit → R$621.7B).
- Aggregation cue: 'Bundle N {instrument} cities into one facility' for the portfolio-altitude buyer.
- Leverage sort tiebreaks on unlock $; fiscal fields added to CSV export. Full EN/PT i18n.

Co-Authored-By: Claude Fable 5 <[email protected]>
5-slide explainer for a climate-finance literate user: (1) the invisible market thesis,
(2) what CAPAG is (A+→D, tiers/gates), (3) graduation candidates, (4) n.d. + ICF fixable gates,
(5) how to use it (mandate → leverage-ranked deployable pipeline).
- OnboardingCarousel: animated aurora blobs (color set per slide), CC tokens, dots + prev/next,
  z-index above Leaflet. Auto-opens once per browser (localStorage), reopens via header (i) button.
- Full EN/PT copy.

Co-Authored-By: Claude Fable 5 <[email protected]>
…ousel + hover)

- Mandate rail: stack the high-leverage toggle (full width) above a labelled sort segmented
  control (flex-1, wrapping) so long PT labels ('Só alta alavancagem', 'Melhor correspondência')
  no longer overflow the row.
- ICF table cells now have a per-grade hover tooltip (Aicf=top/'+' upgrade … Dicf/Eicf=gated).
- Carousel 'gates' slide expanded to define ICF (Aicf→Eicf, what each gate means) in EN/PT.

Co-Authored-By: Claude Fable 5 <[email protected]>
Standalone funder-facing prototype built on the capag-funder-scan data:
- Portfolio view: CAPAG tier x climate risk matrix (the "invisible market")
- Pipeline view: mandate-driven, eligibility-cleared, leverage-sorted city
  list surfacing graduation candidates (CAPAG C + grade-A debt) and ICF gates
- Per-city + batch investment-brief export
Runs on real data: CAPAG ratings/sub-indicators (Tesouro Nacional) joined to
real SEEG/SINIR/SNIS emissions and CCRA risk (CityCatalyst Global API).
Served at /capag-funder-tool.html when the app runs.

Co-Authored-By: Joaquin van Peborgh <[email protected]>
Co-Authored-By: Claude Opus 4.8 <[email protected]>
…rototype cross-link

- Tab bar (Explore | Portfolio) under the header.
- PortfolioMatrix: fiscal tier (rows) × climate-risk band (cols), each cell = real city count +
  real deployable R$ headroom; 'can't see today' markers on the credit-blocked/unrated × mod/high
  cells (the invisible market). Click a cell → drills into Explore pre-filtered (instrument + band,
  leverage sort). All real data (5,566 cities, RGF headroom) — no modeling.
- lib/risk.ts: overall climate-risk band from max CCRA hazard (high>=0.5, moderate>=0.25).
- Risk-band filter wired into Explore filtering/clear/activeFilters.
- Footer with sources + 'Open the standalone prototype' link (/capag-funder-tool.html); added a
  '← Open the live tool' back-link into Carole's prototype HTML. Full EN/PT.

Co-Authored-By: Claude Fable 5 <[email protected]>
'can't see today' was cryptic (read like 'no data'). Renamed marker to 'invisible to credit',
added a legend box under the intro and a hover tooltip explaining: climate-urgent cities the
guaranteed-credit system can't reach (C is blocked, n.d. unrated) — the blended-finance & TA
market. EN/PT.
…l-down)

The portfolio drill applied an instrument + risk-band filter, but the band had no visible
control — a hidden filter. Added a 'Filtered view' banner with a removable chip per active
filter (instrument, risk band, tiers, hazards, UF, high-leverage, search) + 'Clear all', so
it's always clear what's filtered and each can be cleared with one click. EN/PT.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants