Extracts structured carbon data from 20 concrete EPD (Environmental Product Declaration) PDFs and presents a small Next.js app that lets a non‑expert builder compare products by embodied carbon across the full EN 15804 life cycle — stage by stage — filter by strength and location, and see where data is not declared (which is never treated as zero). Every figure is traceable to its source EPD page.
- Live app: add Vercel URL here
- Reasoning:
EXTRACTION.md - Data:
data/*.json— one record per EPD
| File | What it is |
|---|---|
lib/epd.ts |
Canonical zod schema — the single contract shared by extraction, validation, and the app. |
data/*.json |
One structured record per EPD (identity, product/strength, location, declared unit, per‑module GWP family with raw tokens + source pages, and a module_status map). |
scripts/extract.ts |
Reproducible Anthropic‑SDK pipeline (forced tool‑call → zod‑validated → retry loop). Reads PDFs from public/epds. |
scripts/validate.ts |
Structural + semantic checks (GWP‑total = fossil+biogenic+luluc; A1‑A3 = A1+A2+A3; raw↔value; boundary↔value; plausibility band). |
scripts/extraction-brief.md |
The extraction spec used to drive the run. |
npx tsx scripts/validate.ts # validate all data/*.json (expects 0 errors)
ANTHROPIC_API_KEY=... npx tsx scripts/extract.ts # re-run extraction (optional)Extraction was performed by Claude reading each PDF (multimodal) constrained to the
schema, then verified deterministically; see EXTRACTION.md.
app/page.tsx+components/Explorer.tsx— filterable product table and multi‑select stage‑by‑stage comparison.components/ComparePanel.tsx— stacked per‑module GWP bars; not declared is shown distinctly and whole‑of‑life totals that omit stages are labelled partial.app/epd/[id]/page.tsx— full per‑module provenance table linking to the source EPD page.lib/gwp.ts— the honesty logic (status‑aware totals, comparability caveats).
npm run dev # http://localhost:3000
npm run build # production build (static: home + 20 detail pages)Data is read and zod‑validated at build time from data/*.json; source PDFs are in
public/epds for provenance links.
- A not‑declared stage is
nullwith a status, never0. - Only modules every product declares (at least A1–A3) are directly comparable; mixed life‑cycle coverage is flagged, not silently summed.
- Module D (a recycling credit beyond the system boundary) is shown separately and never added into the life‑cycle total.
- Every carbon figure links to its source EPD and page.