Live demo: https://material-trace.leonsilva.dev
Access to the hosted demo is controlled. Request access before opening the live environment.
MaterialTrace LCA is a climate-intelligence product prototype for building-material manufacturers. It turns ready-mix concrete production data into a traceable, versioned, EPD-style environmental-impact result.
The project is built as a portfolio-grade slice of product-carbon software: manufacturing inputs are validated against simplified PCR-like rules, converted into A1/A2/A3 GWP results with versioned demo emission factors, stored with calculation lineage, prepared for scenario comparison, and exported as deterministic EPD-style JSON with an optional PDF presentation download.
The main engineering signal is auditability. A reviewer should be able to trace every result back to persisted inputs, units, factor IDs, factor versions, formulas, rule profile versions, and calculation steps.
This is a software-engineering prototype. It is not a verified LCA tool and does not generate verified Environmental Product Declarations. Demo emission factors are used for illustration only.
| Reviewer signal | MaterialTrace implementation |
|---|---|
| Turn manufacturing data into product-carbon outputs | Ready-mix concrete assessment flow from production inputs to EPD-style report export |
| Translate domain rules into software | YAML-backed ready_mix_concrete.v0.1 PCR-like profile and backend validation engine |
| Keep calculations explainable | A1 raw materials, A2 inbound transport, and A3 manufacturing energy calculations with stable trace steps |
| Preserve audit history | Immutable persisted calculation runs with result, trace, factor, and validation snapshots |
| Handle factor governance | Versioned demo emission factors with source labels, regions, units, and factor-set versioning |
| Build maintainable product software | FastAPI, Pydantic, SQLAlchemy, Alembic, PostgreSQL, React, TypeScript, Vite, Docker Compose, and pytest |
| Communicate limitations responsibly | Prototype disclaimer, demo factor labeling, and non-compliance boundary in docs, UI, and report export |
The seeded local demo path uses Demo Materials GmbH, Munich Plant, and a
C30/37 Ready Mix Concrete product.
- Start the Docker Compose stack and seed the demo product data.
- Open the frontend dashboard and select the ready-mix concrete demo product.
- Create an assessment and enter production quantities for materials, inbound transport, and manufacturing energy.
- Run backend validation to surface missing values, range warnings, and rule-profile findings.
- Run the assessment to persist A1/A2/A3 GWP totals and the full calculation trace.
- Inspect the result and trace views to review module totals, factor versions, formulas, and input lineage.
- Duplicate the baseline into a scenario, adjust production inputs, rerun the calculation, and compare persisted baseline versus scenario runs.
- Export the deterministic EPD-style JSON report for the persisted calculation run, or download the optional PDF presentation export.
Current demo screenshots and PDF presentation sample are committed under
skills/materialtrace-demo-evidence/MTL-127.
They use seeded demo data only: Demo Materials GmbH, Munich Plant, and
C30/37 Ready Mix Concrete.
The gallery below follows the primary demo workflow. Evidence media is shown as static thumbnails.
- Project source of truth: product scope, project alignment, MVP behavior, non-goals, and epic plan.
- Architecture: runtime components, backend layer boundaries, data flow, immutable calculation runs, and current/planned implementation boundaries.
- Local observability workflow: structured JSON logs, request IDs, calculation trace IDs, and opt-in console spans for reviewer demos.
- Domain model and calculation guide: LCA-inspired entities, declared unit and GWP terminology, A1/A2/A3 formulas, validation, factor versioning, trace snapshots, and demo assumptions.
- Report export contract: deterministic EPD-style JSON shape, optional PDF presentation export, audit boundary, and disclaimer requirements.
- Portfolio demo script: local setup, seeded demo data, UI walkthrough, backend smoke command, API fallback, scenario comparison, and report export.
- Infrastructure proof: lightweight Kubernetes manifests, optional FluxCD/OpenTofu skeletons, and deployment-proof boundaries; Docker Compose remains the primary demo path.
- Climate Intelligence mapping: concrete mapping between MaterialTrace features and Climate Intelligence Software Engineer signals.
backend/ FastAPI, SQLAlchemy, Alembic, domain services, seed data, and tests.
frontend/ React, TypeScript, Vite, product workflow pages, and typed API client.
docs/ Source of truth, domain model and calculation guide, and report export contract.
infra/ Docker Compose guidance plus Kubernetes, Flux, and OpenTofu proof.
.github/ GitHub project files and GitHub Actions CI workflows.
From frontend/:
npm install
npm run dev
npm run lint
npm run format:check
npm run typecheck
npm run buildThe frontend reads VITE_API_BASE_URL and defaults to http://localhost:8000.
From the repository root:
(cd backend && uv run ruff check .)
(cd backend && uv run ruff format --check .)
(cd backend && uv run mypy app)
(cd backend && uv run pytest)
npm install --prefix frontend
npm --prefix frontend run lint
npm --prefix frontend run format:check
npm --prefix frontend run typecheck
npm --prefix frontend run buildGitHub Actions runs the same MVP quality gates on pull requests and pushes to
master: backend lint, format check, mypy, and pytest; frontend lint, format
check, typecheck, and production build. Backend CI intentionally does not
provision PostgreSQL for the current test suite because API tests override the
database dependency with in-memory SQLite, while Docker Compose and local app
runtime continue to use PostgreSQL.
To apply formatting locally:
(cd backend && uv run ruff format .)
npm --prefix frontend run formatDocker Compose is the primary reviewer workflow. It runs the FastAPI backend, React/Vite frontend, PostgreSQL, and Redis from the repository root.
- Docker Engine or Docker Desktop with the
docker composeplugin. - Ports
5173,8000,5432, and6379available, unless you override them in a local.envfile. - Local image aliases for PostgreSQL, Redis, Python, and Node. The Compose file
uses
pull_policy: neverso VPN/offline runs do not try to pull from Docker Hub during startup.
Before connecting to a restricted network or VPN, pull the public base/service images once and tag the aliases used by Compose:
docker pull postgres:16-alpine
docker pull redis:7-alpine
docker pull python:3.12-slim
docker pull node:22-alpine
docker tag postgres:16-alpine localhost/materialtrace/postgres:16-alpine
docker tag redis:7-alpine localhost/materialtrace/redis:7-alpine
docker tag python:3.12-slim localhost/materialtrace/base-python:3.12-slim
docker tag node:22-alpine localhost/materialtrace/base-node:22-alpineYou can copy .env.example to .env for local overrides, but it is not
required. Keep the default database credentials for the fastest demo path.
Start the stack:
docker compose up --build --pull neverIn a second terminal, apply migrations and seed the demo data:
docker compose exec backend uv run alembic upgrade head
docker compose exec backend python -m app.seed.demo_dataThe seed command is safe to rerun locally. It creates or reuses Demo Materials
GmbH, Munich Plant, and the C30/37 Ready Mix Concrete product with product
category ready_mix_concrete and declared unit 1 m3.
Run the backend API smoke script from the repository root to verify the local happy path without the UI:
node scripts/smoke-demo-api.mjsThe script creates a fresh assessment for the seeded demo product, submits
inputs, validates, runs the calculation, fetches result and trace snapshots,
fetches the EPD-style JSON report export, and prints the total GWP plus
trace_id. The UI also offers an optional PDF presentation download from the
same persisted report source. See Backend demo smoke script
for API base URL overrides and troubleshooting.
Open the local services:
- Frontend:
http://localhost:5173 - Backend API:
http://localhost:8000 - Backend health check:
http://localhost:8000/health - PostgreSQL:
localhost:5432 - Redis:
localhost:6379
Default PostgreSQL database, user, and password are all materialtrace.
The backend container uses service-name URLs inside the Compose network:
DATABASE_URL=postgresql+psycopg://materialtrace:materialtrace@postgres:5432/materialtrace
REDIS_URL=redis://redis:6379/0
If you change POSTGRES_DB, POSTGRES_USER, or POSTGRES_PASSWORD, Compose
uses those values for the backend container connection URL. If you change
BACKEND_PORT, also set VITE_API_BASE_URL to the matching browser-visible
backend URL, for example http://localhost:8001.
Run checks against the running stack:
docker compose exec backend uv run pytest
docker compose exec frontend npm run lint
docker compose exec frontend npm run format:check
docker compose exec frontend npm run typecheck
docker compose exec frontend npm run buildStop the stack:
docker compose downThis removes Compose containers and the default network, but keeps named volumes
and images. Use docker compose down --volumes only when you intentionally want
to reset the local PostgreSQL and Redis data. Do not use
docker compose down --rmi local, docker compose down --rmi all, or
docker system prune -a when you want to keep reusable MaterialTrace images.
- Missing local image aliases: if Compose reports that
localhost/materialtrace/postgres,redis,base-python, orbase-nodecannot be found, disconnect from the restricted network or use an approved internal image source, then run the prerequisitedocker pullanddocker tagcommands. Do not rundocker compose pullfrom a VPN path where Docker Hub is blocked. - Ports already in use: set
FRONTEND_PORT,BACKEND_PORT,POSTGRES_PORT, orREDIS_PORTin.env. If the backend host port changes, setVITE_API_BASE_URLto the same browser-visible backend URL. - Database auth or schema looks stale: if you changed database names,
users, or passwords after the first run, the named
postgres_datavolume may still contain the old cluster. Stop the stack and reset volumes withdocker compose down --volumes, then start the stack and rerun migrations and seed data. - Backend cannot connect to PostgreSQL: wait for the PostgreSQL health check
to pass, confirm the
DATABASE_URLinside the backend uses hostpostgres, and rerundocker compose exec backend uv run alembic current. - Demo product is missing: rerun
docker compose exec backend python -m app.seed.demo_dataafter migrations. - Frontend cannot reach the API: confirm the backend responds at
http://localhost:8000/healthor updateVITE_API_BASE_URLif you changedBACKEND_PORT. - Python package or PyPI build failures: the backend image runs
uv sync --extra devduring build. If that step times out fetching from PyPI, build from an unrestricted network or set your approvedHTTP_PROXY,HTTPS_PROXY, andNO_PROXYvalues beforedocker compose build; Compose forwards those proxy values into the backend build. - npm registry or VPN build failures: set
NPM_CONFIG_REGISTRYbeforedocker compose buildif your network requires an internal npm mirror. Docker Hub pulls are expected to fail on restricted VPN paths unless the local aliases already exist.
Compose tags the locally built application images as:
localhost/materialtrace/backend:local
localhost/materialtrace/frontend:local
Set MATERIALTRACE_IMAGE_TAG before building if you need a different local tag.
To create a local backup of the project images:
mkdir -p .docker-backups
docker compose build backend frontend
docker save -o .docker-backups/materialtrace-project-images-local.tar \
localhost/materialtrace/postgres:16-alpine \
localhost/materialtrace/redis:7-alpine \
localhost/materialtrace/base-python:3.12-slim \
localhost/materialtrace/base-node:22-alpine \
localhost/materialtrace/backend:local \
localhost/materialtrace/frontend:localTo restore that backup later:
docker load -i .docker-backups/materialtrace-project-images-local.tar
docker image inspect \
localhost/materialtrace/postgres:16-alpine \
localhost/materialtrace/redis:7-alpine \
localhost/materialtrace/base-python:3.12-slim \
localhost/materialtrace/base-node:22-alpine \
localhost/materialtrace/backend:local \
localhost/materialtrace/frontend:localIf any of those images are missing while you are on the VPN, disconnect from the VPN or use an approved internal registry/export source to restore them. Do not run docker compose pull or docker pull for Docker Hub images from the VPN path.
This repository now includes the FastAPI backend, React/Vite frontend, Docker Compose local stack, PostgreSQL persistence, demo seed data, ready-mix validation, A1/A2/A3 calculation, trace persistence, an initial scenario comparison workflow, EPD-style JSON report export workflows, and optional PDF presentation export.
Kubernetes deployment-proof manifests plus optional FluxCD and OpenTofu skeletons are included for backend/frontend shape. Production runtime hardening remains intentionally scoped to later tickets.
Licensed under the Apache License 2.0. See LICENSE.






