thermograph/docs/onboarding
Emi Griffith 4dcd6775c4
All checks were successful
secrets-guard / encrypted (pull_request) Successful in 5s
shell-lint / shellcheck (pull_request) Successful in 7s
PR build (required check) / changes (pull_request) Successful in 19s
PR build (required check) / build-backend (pull_request) Has been skipped
PR build (required check) / build-frontend (pull_request) Has been skipped
PR build (required check) / validate-observability (pull_request) Has been skipped
PR build (required check) / gate (pull_request) Successful in 1s
Sync infra to hosts / sync-beta (push) Has been skipped
Sync infra to hosts / sync-prod (push) Has been skipped
Sync infra to hosts / sync-centralis (push) Has been skipped
secrets-guard / encrypted (push) Successful in 6s
Sync infra to hosts / sync-dev (push) Successful in 12s
shell-lint / shellcheck (push) Successful in 8s
make: add root install/up/down for the local stack
A fresh checkout had no working path to the stack locally. Neither compose
file carries a `build:` for backend or frontend -- each ships as its own
registry image -- so with no image present `make dev-up` fell through to
pulling the `:local` tag, which nothing publishes, and failed with 403
against a registry a laptop has no login for.

`install` builds both images from backend/Dockerfile and frontend/Dockerfile
under exactly the tag the compose files default to; `up` verifies they exist
and says what to run instead of retrying the pull. Image names are read back
from `docker compose config --images` rather than restated here, so an org
rename cannot leave this file building a tag nothing runs.

infra's dev-up/dev-down now set COMPOSE_PROJECT_NAME=thermograph-dev, which
matches deploy/deploy-dev.sh and what the root CLAUDE.md already described;
a local run previously landed in the prod-shaped `thermograph` project. Drop
dev-up's `--build`, a no-op since the Dockerfiles moved out of infra, and
correct the comment claiming a 0.0.0.0 default -- the overlay has published
on loopback since dev moved to a public VPS.
2026-08-01 13:14:32 -07:00
..
01-orientation.md infra: split the estate into vps1/vps2 — beta joins prod, dev gets a home (#103) 2026-07-26 06:56:38 +00:00
02-setup.md make: add root install/up/down for the local stack 2026-08-01 13:14:32 -07:00
03-repo-map.md registry: move image and repo references to the Jinemi namespace 2026-08-01 09:25:02 -07:00
04-backend.md infra: split the estate into vps1/vps2 — beta joins prod, dev gets a home (#103) 2026-07-26 06:56:38 +00:00
05-frontend.md infra: split the estate into vps1/vps2 — beta joins prod, dev gets a home (#103) 2026-07-26 06:56:38 +00:00
06-contracts.md frontend: fix the three inconsistencies the onboarding guide found (#99) 2026-07-25 21:11:32 +00:00
07-ci-and-release.md registry: move image and repo references to the Jinemi namespace 2026-08-01 09:25:02 -07:00
08-infra-secrets.md infra: split the estate into vps1/vps2 — beta joins prod, dev gets a home (#103) 2026-07-26 06:56:38 +00:00
09-observability.md registry: move image and repo references to the Jinemi namespace 2026-08-01 09:25:02 -07:00
10-recipes.md infra: split the estate into vps1/vps2 — beta joins prod, dev gets a home (#103) 2026-07-26 06:56:38 +00:00
11-traps.md registry: move image and repo references to the Jinemi namespace 2026-08-01 09:25:02 -07:00
README.md registry: move image and repo references to the Jinemi namespace 2026-08-01 09:25:02 -07:00

Onboarding — becoming a full contributor to Thermograph

This is the developer onboarding path for the Jinemi/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 First. What the product actually claims, the estate, the four non-negotiable rules.
2 Local setup Before you touch anything. Toolchain, verified run/test recipes for every service.
3 Repo map To find things. Every domain and directory, and which files matter.
4 Backend deep dive Before your first backend change. Data pipeline, grading, caching, roles, daemon.
5 Frontend deep dive Before your first frontend change. The Go SSR service, static assets, design system.
6 Cross-service contracts Before any change that touches both. These break silently and in production.
7 CI and release Before you open a PR. Nine workflows, three branches, three environments.
8 Infra and secrets Before you touch deploy, compose, or a secret.
9 Observability When something is wrong and you need to see it.
10 Recipes Task-shaped walkthroughs for the things you'll actually do.
11 Traps and stale docs 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 jinemi/thermograph/backend.
  • frontend/Go SSR service (frontend/server/) plus every static asset. No climate data, no database, no compute. Ships as jinemi/thermograph/frontend. (The Python implementation at frontend/*.py is the superseded original — see traps.)
  • 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 is the list of things that keep it safe.

Your first day

  1. Read Orientation and Traps.
  2. Work through Local setup until make test is green in both backend/ and frontend/server/.
  3. Read Repo map with the tree open beside it.
  4. Pick something small in the domain you're least afraid of, and follow Recipes end to end — including opening the PR.

Your first week

  • Read Contracts 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) 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.