Files
pamietnik/CLAUDE.md
2026-04-05 20:19:54 +02:00

136 lines
4.4 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
**Pamietnik** (Codename: RALPH) is a life/travel journal consisting of three components:
- `app/` — Android app (Kotlin + Jetpack Compose)
- `backend/` — Go REST API + server-side rendered Web UI
- `README.md` — single source of truth for architecture, requirements, and backlog
## Backend (`backend/`)
**Stack:** Go, chi router, pgx/v5 (PostgreSQL), golang-migrate, Argon2id
**Run locally:**
```bash
cd backend
docker-compose up -d # starts PostgreSQL + API on :8080
./start.sh # alternative start script
```
**Run only PostgreSQL and server manually:**
```bash
docker-compose up -d postgres
go run ./cmd/migrate # run DB migrations
go run ./cmd/server # starts API on :8080 (default)
```
**Env vars** (with defaults):
- `DATABASE_URL``postgres://ralph:ralph@localhost:5432/ralph?sslmode=disable`
- `LISTEN_ADDR``:8080`
- `UPLOAD_DIR``./uploads`
**Tests:**
```bash
go test ./... # all tests
go test ./internal/api/... # handler tests only
```
**Create a user:**
```bash
go run ./cmd/createuser
```
**DB migrations** live in `migrations/` and are applied via `cmd/migrate`.
### Backend Architecture
```
cmd/
server/ entry point: wires stores → router → http.Server
migrate/ runs golang-migrate against DATABASE_URL
createuser/ CLI to create users with Argon2id-hashed passwords
internal/
domain/ shared model types (Trackpoint, Stop, Suggestion, …)
db/ pgx store implementations (trackpoints, stops, suggestions, journal)
auth/ session store (Postgres-backed), Argon2id hashing
api/
router.go chi router wiring + middleware
middleware.go session auth middleware
ingest.go POST /v1/trackpoints, POST /v1/trackpoints:batch
query.go GET /v1/days, /v1/trackpoints, /v1/stops, /v1/suggestions
webui.go server-side rendered web UI (login, /days, /days/{date})
journal.go journal entry endpoints
response.go shared response helpers
```
Key invariants:
- Idempotency via unique `(device_id, event_id)` — duplicate inserts return 200 OK
- Geocoding is event-driven (per Stop only), never bulk/periodic
- Sessions are stored in PostgreSQL (invalidatable on logout)
- OpenAPI spec must be kept current (`openapi.yaml`); changes only via PR + CI validation
## Android App (`app/`)
**Stack:** Kotlin, Jetpack Compose, Room (SQLite), WorkManager, MapLibre
**Build:**
```bash
cd app
./gradlew assembleDebug
./gradlew installDebug # install on connected device/emulator
```
**Tests:**
```bash
./gradlew test # JVM unit tests
./gradlew connectedAndroidTest # instrumentation tests (device required)
./gradlew :app:testDebugUnitTest # single module unit tests
```
### Android Architecture
```
de.jacek.reisejournal/
domain/ Trackpoint domain model
data/ Room entities, DAOs, local DB
service/ Background location foreground service
worker/ WorkManager upload worker
ui/
home/ HomeScreen (Compose) + HomeViewModel
navigation/ NavGraph
theme/ Compose theme
```
Key invariants:
- Offline-first: every point persisted to Room before any upload attempt
- All points carry a client-generated `event_id` (UUID) for server-side idempotency
- `source` field distinguishes `"gps"` vs `"manual"` trackpoints
- Upload worker uses `NetworkConnected` constraint + retry/backoff
- No DB or network access directly in Composables — always via ViewModel
## Project Decisions (from README)
| Decision | Choice |
|----------|--------|
| Android UI | Jetpack Compose |
| Local DB | Room / SQLite |
| Backend DB | PostgreSQL |
| Maps | MapLibre + OpenStreetMap tiles (configurable source) |
| Geocoding | Nominatim (OSM), cached, provider-swappable via config |
| Auth (Web UI) | Session Cookie (Postgres-backed) |
| Password hashing | Argon2id |
| API spec | OpenAPI 3.1 (`openapi.yaml`) |
## Open Decisions (TBD)
- `timestamp` format: `epochMillis` vs RFC3339
- Android upload auth: X-API-Key vs Bearer/JWT
- HTTP payload: JSON vs Protobuf
- Batch limits (max items / max bytes)
- Retention policy for trackpoints
- Stop detection parameters (min duration, radius)
- Geocoding provider: Nominatim public vs self-hosted vs alternative