Files
Khalid Abdi 7846dacd42 chore: release v0.13.0
Bump version to 0.13.0 across root/backend/frontend, add the 0.13.0 CHANGELOG
entry, and refresh stale CLAUDE.md docs (the AI chat is real and @ai-sdk/react
is installed; the signing/approval flow is built).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 21:17:55 +03:00

10 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project

temetro — an open-source clinical tool that acts as an AI middleman between clinicians and patient data. Clinicians use a natural-language AI chat to retrieve and organize patient information, displayed as rich record cards.

The distinguishing idea is a patient-owned data model. Instead of (or alongside) living in a doctor's own database, a patient's record can be stored on the patient's own device. When a clinician adds or changes data, they sign it (blockchain-style); the change is written to the patient's record and cannot be modified until the patient approves it through a companion app. temetro can also read existing patient databases and present them in the same organized card UI.

This repository is a monorepo: the frontend/ and backend/ apps live side by side in one git repository (published as temetro).

Status: the backend is built. backend/ is a TypeScript + Express + Postgres API (Drizzle ORM) with authentication and multi-tenant clinics via Better Auth, plus an org-scoped patient records API. The frontend/ chat is wired to it: real auth (login/signup/reset/onboarding), route protection, clinic switching, and patient data fetched over the API — the old in-memory fixture is gone (frontend/lib/patients.ts now calls the backend).

Now built (thin slice): a patient wallet app (~/Desktop/temetro-app, sibling repo — see "Patient wallet app" below) and an end-to-end encrypted share / patient-approval flow: clinics hold a real Ed25519 signing key (Settings → Signing, backend/src/services/signing.ts), and "Import from a patient app" on the Patients page relays an encrypted request to the wallet over the Temetro Network relay (see below), the patient approves on their phone, and the sealed record is imported (with optional temporary share + auto-delete). Clinic→wallet record-update push and QR pairing are built too. See backend/src/routes/{signing,patients-wallet}.ts.

Also built: the AI chat is real — the frontend streams from the backend's tool-using agent (POST /api/chat), not mock replies (see frontend/CLAUDE.md).

Still vision, not built: in-app record editing and cryptographic time-boxing of temporary shares. Email verification is wired but currently not enforced at sign-in (see backend/CLAUDE.md).

Patient wallet app (sibling repo ~/Desktop/temetro-app)

The patient companion app is its own git repo on the Desktop (not in this monorepo): an Expo SDK 56 app whose UI must be built with HeroUI Native (heroui-native + Uniwind/Tailwind) — a hard requirement; the one exception is the native tab bar, which uses expo-router NativeTabs. See its CLAUDE.md. It stores the patient's record encrypted on-device, the patient's identity is an Ed25519 keypair whose public key (base58check, tmw_…) is their wallet number, and it shares records by sealing them to a clinic's ephemeral key over the backend relay. The crypto wire format mirrors backend/src/lib/wallet-crypto.ts exactly. "Decentralization" here means keys + data live on the patient's device and the relay only ever forwards ciphertext — it is not a literal blockchain (records are off-chain, which is also what lets a temporary share be deleted). Commit/push that app inside its own repo, separately from this one.

Temetro Network (sibling repo/folder ~/Desktop/Temetro-network)

The relay that connects this backend to patient wallet apps. It is its own git repo on the Desktop (folder ~/Desktop/Temetro-network, pushed to github.com/temetro/temetro-network), not in this monorepo — a standalone Rust + Axum + socketioxide service meant to run always-on (e.g. on Railway). It replaces the old flaky Cloudflare quick-tunnel that used to expose the backend's embedded /wallet Socket.io namespace to phones.

It is a dumb, stateless pipe: two Socket.io namespaces — /wallet for devices (challenge/Ed25519-signature auth, room keyed by wallet number) and /hub for this backend (RELAY_TOKEN-authenticated). Devices and the backend both connect to it; it forwards sealed ciphertext verbatim and never opens bundles or touches a database. Its only crypto is verifying a device's auth signature (mirrors backend/src/lib/wallet-crypto.ts). The backend connects to it as a /hub client via backend/src/services/relay-client.ts (its sendToWallet is what emitToWallet now calls); configure with RELAY_URL + RELAY_TOKEN. Commit/push that service inside its own repo, separately from this one.

Note: in this sandbox the ~/Desktop/Temetro-network folder blocks directory enumeration (ls/getcwd/git inside it return EPERM) though plain file writes work. Develop/build/commit it in an accessible copy and mirror the tree in with tar; drive git there via GIT_DIR/GIT_WORK_TREE from an accessible cwd.

Layout

frontend/ and backend/ were previously separate per-folder git repos; they have been merged into this single monorepo with full history of both preserved.

The marketing landing page is not in this monorepo — it lives in the sibling Desktop folder ../temetro/landing-page (/Users/khalidabdi/Desktop/temetro/landing-page), right next to the ../temetro/docs site. It is its own git repository (a Next.js app with the marketing components/landing/); edit and commit it there, separately from this repo.

  • frontend/ — the Next.js product app (the AI chat UI). This is where almost all current work happens. It has its own CLAUDE.md — read frontend/CLAUDE.md for the stack, commands, architecture, and gotchas.
  • backend/ — the TypeScript + Express + Postgres API (Drizzle ORM + Better Auth). Built and Dockerised. Has its own CLAUDE.md (and README.md) — read it for the auth/schema workflow and gotchas.

frontend/ and backend/ are independent apps, each with its own package.json / node_modules. Run npm commands from inside the relevant app directory, not from this root.

Documentation (very important)

The project documentation lives outside this repo, in the sibling Desktop folder ../temetro/docs (/Users/khalidabdi/Desktop/temetro/docs) — a Fumadocs (Next.js) site with user guides (content/docs/guides/), an API reference (content/docs/api/), admin docs, and a roadmap (content/docs/roadmap.mdx). It is its own git repository.

Whenever you make a significant change here — a new feature, endpoint, page, or behavior change — update the affected docs pages in the same work session so the documentation stays accurate (e.g. a new backend route needs an content/docs/api/*.mdx entry; a UI feature belongs in the matching guide; status changes belong in the roadmap). Commit docs changes inside that repo, separately from this one.

Every release must also get a dated entry in the docs changelog (content/docs/changelog.mdx, newest first) — not just the monorepo CHANGELOG.md. When you cut a version (see "Always release after pushing"), add a matching, user-facing section to that page in the same session so ../temetro/docs never falls behind the shipped version.

Running the stack

From backend/: ensure a .env exists (cp .env.example .env, then set BETTER_AUTH_SECRET via openssl rand -base64 32), then docker compose up --build → frontend :3000, backend :4000, Postgres. Compose builds the sibling ../frontend app, which works because they remain siblings in the monorepo. See backend/README.md.

Port note: if another Postgres already holds host port 5432, set POSTGRES_PORT (e.g. 5433) in backend/.env — the app still talks to Postgres internally on db:5432; only the published host port changes.

For local dev without Docker, run npm run dev in backend/ and frontend/ separately (the frontend reads NEXT_PUBLIC_API_URL, default http://localhost:4000).

Version control (single monorepo)

This root is one git repository (temetro). The old per-folder .git repos are gone — frontend/ and backend/ are plain subdirectories now.

Commit after every change. When you finish a task, commit from the repo root (git add -A && git commit). Keep each commit focused on one logical change, and prefix the subject with the area when useful (e.g. frontend: / backend:). End commit messages with the Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> trailer.

.env files are git-ignored (only .env.example is tracked) — never commit real secrets.

Always release after pushing

When you finish a unit of work and push to main, you must also cut a release — temetro ships as prebuilt Docker images, so an un-released change never reaches a self-hosted clinic. After the push:

  1. Bump the version to the new X.Y.Z in all three package.json files (root, backend/, frontend/) — they must stay in sync (GET /api/version reports it).
  2. Update CHANGELOG.md (move Unreleased notes under a dated ## [X.Y.Z] heading).
  3. Publish the images to Docker Hub as khalidxv/temetro-backend and khalidxv/temetro-frontend, tagged X.Y.Z and latest. The tag-triggered release workflow does this automatically (git tag vX.Y.Z && git push origin main --tags).

See RELEASING.md for the full checklist. Never consider work "done and pushed" without the version bump + image publish.

Customized Next.js (frontend)

The frontend/ app runs a customized Next.js 16 whose APIs/conventions differ from public docs. Before writing Next.js code, read the relevant guide under frontend/node_modules/next/dist/docs/01-app/.

Root tooling

  • .mcp.json registers the shadcn MCP server, and the root package.json pins the shadcn CLI — used to browse/add registry components into the apps. There is nothing to build or run at this root level.