Files
moments/CLAUDE.md
rob thijssen 1679153c43 docs: add CLAUDE.md and ignore .zed/
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-06 04:43:00 +03:00

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). The reshape() function in moments-core/src/presentation.rs transforms payloads into TimelineItem at request time — no re-ingestion needed to change presentation.
  • Public/private gate: events.public boolean controls API visibility. Only public = true rows are served.
  • Wire types are hand-maintained: ui/src/api/client.ts mirrors 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.