3.3 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
moments is a personal activity timeline and portfolio site. It ingests developer activity from multiple forges (GitHub, Gitea, Mercurial, Bugzilla), stores raw JSON payloads in PostgreSQL, and serves a React frontend showing contribution graphs, a ranked project dashboard, and a filterable activity timeline.
Architecture
Hexagonal (ports & adapters) Rust backend with a React/TypeScript frontend.
Crate Dependency Graph
moments-entities — pure types/DTOs, no DB or HTTP deps
^
moments-core — port traits (EventReader, EventWriter, EventSource, PollerStateStore)
+ presentation reshape + poller loop
^
moments-data — sole adapter: PgStore implements all core traits
+ EventSource impls (github, gitea, hg, bugzilla)
+ SQL migrations
^
moments-api — axum HTTP API binary (read-only, connects as moments_ro)
moments-worker — ingestion daemon binary (runs migrations, connects as moments_rw)
Key Design Decisions
- Raw payload storage: upstream JSON is stored verbatim in
events.payload(JSONB). Thereshape()function inmoments-core/src/presentation.rstransforms payloads intoTimelineItemat request time — no re-ingestion needed to change presentation. - Public/private gate:
events.publicboolean controls API visibility. Onlypublic = truerows are served. - Wire types are hand-maintained:
ui/src/api/client.tsmirrors Rust entity types manually. - Migrations: run automatically on worker startup via
sqlx::migrate!. The API binary never runs migrations.
Frontend
React 19 + Vite 6 (SWC) + TypeScript + Bootstrap 5. State/data via @tanstack/react-query. Package manager is pnpm.
Routes: / (dashboard), /activity (timeline), /project/:source/* (project detail), /cv (resume).
Build & Dev Commands
Rust
cargo build --workspace # build all crates
cargo build --workspace --release # release build
cargo clippy --workspace # lint
cargo fmt --check # format check
cargo test --workspace # run tests
# Run binaries (need DATABASE_URL)
DATABASE_URL=postgres://localhost/moments cargo run -p moments-api
DATABASE_URL=postgres://localhost/moments cargo run -p moments-worker
Frontend
cd ui
pnpm install # install deps
pnpm dev # dev server on :5173 (proxies /api/* to localhost:8080)
pnpm lint # tsc --noEmit type-check
pnpm build # production build (tsc -b && vite build)
Database
PostgreSQL with three migrations in crates/moments-data/migrations/. Two roles: moments_rw (worker, full access) and moments_ro (API, SELECT-only).
API Endpoints
All under /v1/: healthz, events, sources, projects, activity/daily, forge/{source}/*, og/contributions.png.
Deployment
Production uses ./script/deploy.sh. Services run under systemd with hardened units. Secrets resolved from pass store via template substitution. Nginx reverse-proxies /api/ to the API host.