
- Python51.3%
- TypeScript45.7%
- CSS2.6%
- JavaScript0.3%
Carbon ownership, not carbon awareness.

A carbon-footprint prototype for recording everyday activities, viewing deterministic emissions estimates, and tracking climate actions. The README describes a FastAPI backend and Next.js frontend, and notes that the project is not a security-audited production service.
Individual emissions are a meaningful slice of the climate problem, but they are largely invisible to the people producing them. People want to act, but they have no reliable, low-friction way to (a) measure their impact, (b) understand what's driving it, and (c) actually neutralize it. The result is a gap between…
From README.md in the repository.
Carbon ownership, not carbon awareness.
A full-stack carbon-footprint prototype with a deterministic accounting engine, a FastAPI backend and a Next.js frontend. The repository includes security and accessibility tests; this is a student project, not a security-audited production service.
The dashboard screen. More screens in the product walkthrough.
What it is: EarthShare is a carbon-footprint prototype. Users record everyday activities, receive deterministic emission estimates, view insights, and track progress by completing suggested climate actions.
Why it's different: Most carbon apps focus on awareness (charts, streaks, badges). EarthShare focuses on ownership (account, measure, neutralize). The behavioral model is the product.
Engineering: The backend includes JWT authentication, rate limiting, configurable CORS middleware, security headers, and request-schema validation. Carbon calculations are deterministic and do not use an LLM. SQLite is the local default; PostgreSQL migration and production deployment have not been verified.
From the repository root:
git clone https://github.com/Soham-o/EarthShare.git
cd EarthShare
python -m venv backend/.venv
# Activate the environment:
# macOS/Linux: source backend/.venv/bin/activate
# Windows PowerShell: .\backend\.venv\Scripts\Activate.ps1
python -m pip install -r backend/requirements.txt
Copy backend/.env.example to backend/.env, then start the API:
# macOS/Linux
cp backend/.env.example backend/.env
# Windows PowerShell: Copy-Item backend/.env.example backend/.env
cd backend
uvicorn app.main:app --reload
The API defaults to local SQLite and is available at http://localhost:8000.
In a second terminal from the repository root:
cd frontend
npm ci
Copy frontend/.env.example to .env.local in the frontend/ directory, then run:
# macOS/Linux
cp .env.example .env.local
# Windows PowerShell: Copy-Item .env.example .env.local
npm run dev
Open http://localhost:3000. The frontend's default API URL is http://localhost:8000. Never use the example JWT secret in a production deployment; configure a unique secret and explicit trusted CORS origins.
# Backend (from repository root, with the Python environment active)
cd backend
python -m pytest -q
# Frontend (in a second terminal, from repository root)
cd frontend
npm ci
npm test
npm run build
GitHub Actions runs backend tests, frontend tests and a frontend build for pull requests to main and pushes to main or fix/**.
Individual emissions are a meaningful slice of the climate problem, but they are largely invisible to the people producing them. People want to act, but they have no reliable, low-friction way to (a) measure their impact, (b) understand what's driving it, and (c) actually neutralize it. The result is a gap between intent and action.
Awareness asks: "Do you know your number?" Ownership asks: "What are you going to do about your number?"
EarthShare is designed around a single behavioral loop:
Log → Measure → Understand → Reduce or Offset → Repeat.
Every screen, every endpoint, and every data model exists to shorten the distance between a logged activity and a neutralized footprint. Ownership is the product.
The backend is organized into clearly separated layers — routes → services → repositories → models — so that business rules don't depend on framework details and the framework doesn't leak into business rules. This means:
All non-trivial logic — carbon calculation orchestration, user lifecycle, offset purchase flows, insight aggregation — lives in services. This keeps routes testable in isolation and lets us swap delivery mechanisms (HTTP today, a job runner tomorrow) without rewriting business logic.
Every database read/write goes through a repository. Benefits:
fetch calls.This is what makes the codebase easy to read, easy to test, and easy to extend.
/api/v1.The core calculator is pure, deterministic, and offline. Given the same input, it always returns the same number. There is no LLM, no external API, and no randomness in the calculation path. This matters because:
LLMs, if used at all, are confined to explanations and suggestions on top of the deterministic number — never inside it.
Security is implemented as defaults, not features.
CORS_ORIGINS environment setting. Configure explicit trusted origins in deployments; the current configuration code does not reject a wildcard automatically.Content-Security-Policy, X-Content-Type-Options, X-Frame-Options, Referrer-Policy and Permissions-Policy. HSTS is enabled for production deployments.422 responses; they should not expose stack traces.Secrets (JWT signing key, DB URL, allowed origins) are loaded from environment variables only — never committed.
main and fix/** branches.EarthShare targets a WCAG 2.1 AA mindset throughout the UI.
<button>, <nav>, <main>, <form>, <label>). Live regions announce async results (e.g. "Activity logged, 2.3 kg CO₂e added").aria-describedby.The carbon engine is a pure function over a static emission-factor table. Each calculation is effectively:
emissions = activity_quantity × factor[activity_type][region]
For one activity, the calculation uses a constant-time factor-table lookup and arithmetic; no performance benchmark is published in this repository.
The carbon calculation engine runs locally within the backend and uses an in-repository factor table:
The database URL is centralized in backend/app/core/config.py, and the app uses SQLAlchemy sessions and repository classes. SQLite is the verified local/test default. PostgreSQL migration, migrations against a PostgreSQL instance, and production deployment have not been verified, so a connection-string change alone should not be presented as a proven migration path.
Goal: Maximize judge-perceivable quality and maximize how far the codebase can travel after the hackathon.
| Decision | Why | What it buys us |
|---|---|---|
| Clean Architecture (routes → services → repos → models) | Keeps business rules independent of framework and DB | Easy to test, easy to refactor, easy to read |
| Service layer | One place for business logic; routes stay thin | Reusable logic across HTTP, jobs, and tests |
| Repository pattern | One place for persistence | Centralizes database access; alternate-database migration still needs validation |
| Deterministic carbon engine | Reproducibility and auditability beat cleverness here | Repeatable calculations from a versioned factor table |
| JWT authentication | Uses signed bearer tokens | Avoids a server-side session table for token state; production scale is not evaluated |
| SQLite for v1 | Zero-ops for the demo | Reliable hackathon-day deploy |
| Configurable database URL | Keeps the connection setting in one place | PostgreSQL compatibility remains unverified |
| Typed API client on the frontend | Single source of truth for request/response shapes | Fewer integration bugs, better DX |
| Accessibility tests | Catch selected accessibility regressions early | Automated accessibility assertions exist; full WCAG conformance is not claimed |
| LLMs out of the calculation path | Determinism > novelty for a measurement product | Numbers a judge can verify by hand |
The prototype separates routes, services, repositories, models and schemas, but production readiness, hosted deployment and database migration still need independent validation.
Dashboard — at-a-glance footprint, recent activities, and a clear next action.

Insights — breakdown by category, trend over time, and the largest contributors to your footprint.

Action marketplace — browse recommended climate actions, mark them complete, and see progress reflected in the app. This is not an offset-credit purchasing marketplace.

Progress — view completed actions, estimated CO₂ savings, weekly trends and badges.

flowchart LR
subgraph Client["🖥️ Frontend"]
UI["React UI<br/>WCAG-aligned"]
APIClient["Typed API Client"]
end
subgraph Edge["🛡️ Edge Protections"]
CORS["CORS middleware"]
RL["Rate Limiter"]
SH["Secure Headers"]
end
subgraph Backend["⚙️ Backend"]
Routes["Routes Layer<br/>(thin: parse + validate)"]
Services["Service Layer<br/>(business logic)"]
Repos["Repository Layer<br/>(persistence)"]
Engine["Deterministic<br/>Carbon Engine"]
Auth["JWT Auth<br/>+ Password Hashing"]
end
subgraph Data["💾 Data"]
DB[("SQLite default<br/>PostgreSQL unverified")]
Factors["Emission Factor Table<br/>(versioned in repo)"]
end
UI --> APIClient
APIClient -->|HTTPS + JWT| CORS
CORS --> RL
RL --> SH
SH --> Routes
Routes --> Auth
Routes --> Services
Services --> Repos
Services --> Engine
Repos --> DB
Engine --> Factors
earthshare/
├── .github/
│ └── workflows/
│ └── ci.yml # backend tests, frontend tests and build
├── backend/
│ ├── app/
│ │ ├── api/v1/ # authentication, onboarding, actions, etc.
│ │ ├── core/ # config, database, security and rate limits
│ │ ├── models/
│ │ ├── repositories/
│ │ ├── schemas/
│ │ ├── services/ # includes carbon_engine.py
│ │ └── main.py
│ ├── tests/
│ ├── pytest.ini
│ └── requirements.txt
├── frontend/
│ ├── src/
│ │ ├── app/ # Next.js routes and pages
│ │ ├── components/
│ │ └── __tests__/ # component and accessibility tests
│ ├── package.json
│ └── package-lock.json
├── docs/
│ ├── ARCHITECTURE.md
│ ├── CARBON_METHODOLOGY.md
│ └── DESIGN_NOTES.md
└── README.md
backend/app/services/carbon_engine.py.backend/app/core/.frontend/src/lib/api.ts.EarthShare — Own your carbon. Then neutralize it.
GitHub data synced 25 Oct 2026