Files
oO/CLAUDE.md

4.3 KiB

oO — Project Instructions

What this is

oO is a recommendation system for personal tips. It collects signals across a user's life (tasks, habits, calendar, mood, context) to build a rich profile and deliver one perfectly-timed tip — an advice or a todo — that feels like magic.

The magic is the product. Precision + timing + minimalism. The UI shows a single black page with one tip. The complexity lives behind it.

Prime directives

  1. Modular, service-oriented from day one. Even the prototype. We will scale to mobile (iOS/Android), many integrations, multi-tenant ML. Shortcuts that bake in a monolith are not acceptable.
  2. Recommendation engine is the core. Every other service feeds it or renders its output. Design schemas, event contracts, and APIs with that in mind.
  3. Python owns ML. Everything training, features, serving for models is Python (FastAPI + PyTorch/scikit + MLflow/feast). Application services are TypeScript (Node, Next.js) unless there's a reason.
  4. OAuth-first for identity and integrations. Never ask users for passwords or raw API keys when a delegated-auth flow exists. Store provider tokens encrypted, refresh transparently.
  5. Feel-of-magic over feature count. When in doubt, ship fewer things, polished.

Architecture (high level)

apps/              user-facing clients
  web/             Next.js PWA — the first shipped client
  mobile-ios/      Swift/SwiftUI (Phase 3)
  mobile-android/  Kotlin/Compose (Phase 3)

services/          backend microservices (each independently deployable)
  gateway/         API gateway + BFF (GraphQL or tRPC)
  auth/            OAuth (Google, Apple, ...), sessions, JWT issuance
  profile/         user profile, preferences, consents
  integrations/    third-party connectors (Todoist first); token vault
  recommender/     Python; serves the "one best tip" decision
  events/          event bus ingress (Kafka/NATS) + signal store
  notifier/        push/email/web delivery of tips

packages/          shared libraries
  shared-types/    OpenAPI/proto-generated types
  sdk-js/          client SDK used by web + mobile webviews
  ui/              shared React components + design tokens

ml/                Python MLOps
  pipelines/       training / batch feature pipelines (Airflow/Prefect)
  features/        feature definitions (Feast-style)
  registry/        model registry (MLflow) integration
  experiments/     A/B testing framework + bandit policies
  serving/         online inference service (FastAPI)
  notebooks/       research only — not production

infra/             docker-compose, k8s manifests, terraform, CI
docs/              architecture notes, ADRs, API specs

Contracts between services

  • Events (Kafka/NATS) — source of truth for user signals. All integrations emit normalized events; the recommender reads them.
  • HTTP/gRPC — synchronous request/response (gateway → services).
  • Shared schemas live in packages/shared-types; generated from a single OpenAPI / proto source. Do not redefine types per service.

Conventions

  • Every service ships a README.md, a Dockerfile, and a /health endpoint.
  • One PR = one concern. Commits follow conventional-commit prefixes (feat:, fix:, chore:, docs:, refactor:).
  • ADRs go in docs/adr/NNNN-title.md for any decision that constrains future work.
  • No secrets in repo. Local dev via .env.local (gitignored), prod via the server's secret store (Vaultwarden now; k8s secrets later).

Definition of done (per feature)

  1. Code + tests merged.
  2. Service's README.md updated.
  3. If it changes a contract → shared-types regenerated + consumers updated.
  4. If it changes architecture → ADR added.
  5. Deployable via docker compose up locally.

Current phase

Phase 0 — Prototype. See README.md for the phase roadmap and docs/architecture/ for diagrams. Work is tracked as Gitea milestones + issues on alvis/oO.

What NOT to do

  • Don't copy Todoist's data into our DB. Store the OAuth token; fetch on demand.
  • Don't implement auth by hand. Use a library (NextAuth / Auth.js, Ory, or Clerk-compatible). We will self-host.
  • Don't hardwire a recommender. The "random todo" v0 must live behind the same interface the real ML model will implement (POST /recommend{tip}). Swap internals, keep contract.
  • Don't build an admin UI before the user-facing black page is polished.