# Onboarding — becoming a full contributor to Thermograph

This is the developer onboarding path for the `emi/thermograph` monorepo: what
the product is, how the code is shaped, how to run it, what will break silently
if you get it wrong, and how a change actually travels from your editor to
`thermograph.org`.

**Scope.** This covers *working in this repo*. Cross-cutting architecture
decision records and operator runbooks live in the separate `thermograph-docs`
repo (reachable through Centralis's `docs_search`) — this set links out rather
than duplicating them. Where a fact is owned by a `CLAUDE.md`, that file stays
the source of truth and this set explains the context around it.

## Reading order

| # | Doc | Read it when |
|---|-----|--------------|
| 1 | [Orientation](01-orientation.md) | First. What the product actually claims, the estate, the four non-negotiable rules. |
| 2 | [Local setup](02-setup.md) | Before you touch anything. Toolchain, verified run/test recipes for every service. |
| 3 | [Repo map](03-repo-map.md) | To find things. Every domain and directory, and which files matter. |
| 4 | [Backend deep dive](04-backend.md) | Before your first backend change. Data pipeline, grading, caching, roles, daemon. |
| 5 | [Frontend deep dive](05-frontend.md) | Before your first frontend change. The Go SSR service, static assets, design system. |
| 6 | [Cross-service contracts](06-contracts.md) | **Before any change that touches both.** These break silently and in production. |
| 7 | [CI and release](07-ci-and-release.md) | Before you open a PR. Nine workflows, three branches, three environments. |
| 8 | [Infra and secrets](08-infra-secrets.md) | Before you touch deploy, compose, or a secret. |
| 9 | [Observability](09-observability.md) | When something is wrong and you need to see it. |
| 10 | [Recipes](10-recipes.md) | Task-shaped walkthroughs for the things you'll actually do. |
| 11 | [Traps and stale docs](11-traps.md) | **Skim early, re-read often.** Which docs in this repo currently lie, and why. |

## The short version

Thermograph grades how unusual today's weather is at any point on Earth against
~45 years of that exact location's own history. Percentiles, never thermometer
readings.

- **`backend/`** — Python 3.12 / FastAPI. Owns all climate data, grading, the
  API, accounts, notifications, plus a Go daemon (`backend/daemon/`) that owns
  the Discord gateway and recurring timers. Ships as `emi/thermograph/backend`.
- **`frontend/`** — **Go** SSR service (`frontend/server/`) plus every static
  asset. No climate data, no database, no compute. Ships as
  `emi/thermograph/frontend`. (The Python implementation at `frontend/*.py` is
  the superseded original — see [traps](11-traps.md).)
- **`infra/`** — compose and Swarm files, deploy scripts, the SOPS secrets
  vault, Terraform, ops query tooling.
- **`observability/`** — Loki + Grafana on vps1, an Alloy agent per node.

Branches stage environments: PR → `dev` (vps1, mesh-only) → `main` (beta, vps2)
→ `release` (prod, vps2). The two app domains build and deploy
**independently** — that independence is the whole reason the split-then-reunify
history exists, and [contracts](06-contracts.md) is the list of things that
keep it safe.

## Your first day

1. Read [Orientation](01-orientation.md) and [Traps](11-traps.md).
2. Work through [Local setup](02-setup.md) until `make test` is green in both
   `backend/` and `frontend/server/`.
3. Read [Repo map](03-repo-map.md) with the tree open beside it.
4. Pick something small in the domain you're least afraid of, and follow
   [Recipes](10-recipes.md) end to end — including opening the PR.

## Your first week

- Read [Contracts](06-contracts.md) properly. Every item on that list has
  already cost someone a production incident somewhere in this project's
  history; that's why each one is written down.
- Get Centralis wired up (see [Local setup](02-setup.md)) and ask it
  `fleet_status`, `logs_overview`, `deployed_version`. You cannot debug this
  estate blind, and the boxes are not reachable from a laptop off the
  WireGuard mesh.
- Read the `CLAUDE.md` for each domain. They are terse, current, and binding.
