A personal operating system that answers one question: "What should I focus on today?"
Recommendations over dashboards — see CLAUDE.md for principles, docs/architecture.md for the design, docs/mvp.md for scope, and docs/epics.md for the plan.
| Layer | Tech |
|---|---|
| Frontend | Next.js (App Router), TypeScript, Tailwind v4, shadcn/ui |
| Backend | FastAPI (Python 3.12+), managed with uv |
| Database | PostgreSQL 16 + pgvector |
| Cache/Jobs | Redis (arq) |
| Agents | LangGraph (E5) |
| Local dev | Docker Compose |
pnpm install # JS workspace deps
pnpm local # compose up (postgres, redis, api, worker) + web dev server
pnpm seed # optional: demo data (local owner user + one event)Then open http://localhost:3000. The dashboard shows the live API status
and recent events — if the status says ok and the seeded event renders,
the whole skeleton (web → api, web → db, migrations) is wired. No accounts,
no sign-up, no .env file needed. The api container runs
alembic upgrade head before serving, so the schema is always current.
Local-first (E1): this is a single-user app that lives on your machine.
AUTH_MODE=local (the default) means no login; the API and web ports bind to
127.0.0.1 only, and local mode refuses to run with ENV=production. The
full Clerk auth flow (sign-in wall, owner-email allowlist, JWT verification)
is built, tested, and dormant — setting Clerk keys turns it on if the app
ever moves to the web (docs/setup-deploy.md).
Configuration: defaults work out of the box; no .env needed. To override,
each app loads its own file (a repo-root .env is read by neither app):
apps/api/.env— FastAPI/worker settings (see.env.examplefor variables)apps/web/.env.local— Next.js (e.g.API_URL)
Fully dockerized web (slower on Windows; the native pnpm dev flow above is
recommended): docker compose --profile full up
cd apps/api
uv sync # creates .venv with dev tools
uv run alembic upgrade head # apply migrations (needs compose postgres)
uv run uvicorn app.main:app --reload # api on :8000
uv run pytest # tests (DB tests skip unless RUN_DB_TESTS=1)
uv run ruff check . ; uv run mypy # lint + typespackages/contracts holds the OpenAPI spec exported from FastAPI and the TS
types generated from it — the only place the two languages meet. After any
API surface change:
pnpm contracts # re-export openapi.json + regenerate TS typesCommit the result; CI fails on drift (generated files stale vs. the API).
Schema changes go through Alembic — never edit tables by hand:
cd apps/api
uv run alembic revision --autogenerate -m "describe change" # then review it!
uv run alembic upgrade headDB-backed tests (migration cycle, upsert idempotency) run when
RUN_DB_TESTS=1 and a Postgres is reachable; CI provides one, locally use
the compose postgres. Fair warning: the migration test rebuilds the schema
from scratch — dev data is disposable (pnpm seed restores the demo data).
apps/
web/ Next.js app — dashboard UI (local mode; dormant Clerk auth)
lib/ api.ts (typed contracts client), db.ts (read-only RSC reads)
api/ FastAPI app + worker (one Docker image, two entrypoints)
src/app/ Python package: app.main, app.worker, app.seed, app.core.*
(config, db), app.modules.auth, app.modules.domain (models,
event upserts)
migrations/ Alembic migrations (schema v1: users, connected_accounts,
events, calendar_events, tasks, recommendations, agent_runs)
packages/
contracts/ openapi.json (exported from FastAPI) + generated TS types —
the ONLY bridge between the Python and TS worlds
infra/ Dockerfiles and deploy config (Railway config-as-code, dormant)
docs/ Architecture, MVP scope, epics, deploy setup
compose.yaml Local full-stack: postgres+pgvector, redis, api (auto-migrates),
worker, web*
* web runs in compose only under --profile full.
Note: the Python package lives at
apps/api/src/app/(imported asapp.*), a deliberate deviation from the baresrc/sketch in the architecture doc — top-level modules namedcore/moduleswould be an import-collision hazard.
- web:
eslint,tsc --noEmit,vitest,next build(both auth modes) - api:
ruff check,ruff format --check,mypy --strict,pytest(incl. migration-cycle + upsert-idempotency tests against a pgvector service container) - contracts: regenerate openapi.json + TS types; fail on drift
E2 (data foundation & contracts) complete: schema v1 under Alembic with the
idempotency constraint on events, auto-migration on api start, the
OpenAPI→TS contracts bridge with a CI drift check, and the RSC read path
rendering seeded data. E1 note: the app is local-first (owner decision,
2026-07-04) — no login (AUTH_MODE=local), loopback-only ports; the Clerk +
Vercel/Railway path is built but dormant
(docs/setup-deploy.md). Next: E3 — calendar
connector (needs Google Cloud setup) and/or E4 — manual tasks (no external
dependencies). See docs/epics.md for the full sequence.