Add CLAUDE.md
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1b1b0898ed
commit
6a896304de
1 file changed
+41
@@ -0,0 +1,41 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Overview
|
||||
|
||||
Lunchtime is a self-hosted group lunch ordering app: FastAPI + SQLite backend (Python 3.12), React 18 + TypeScript + Vite + Ant Design frontend, nginx in front. All app code lives under `src/`. There are no tests and no linter configured.
|
||||
|
||||
## Commands
|
||||
|
||||
Full dev stack (backend with `--reload`, Vite HMR, nginx, Mailpit); also what the devcontainer starts:
|
||||
|
||||
```bash
|
||||
cd src && docker compose up -d # app at http://localhost:8020, Mailpit at http://localhost:8025
|
||||
```
|
||||
|
||||
Without Docker:
|
||||
|
||||
```bash
|
||||
cd src/backend && pip install -r requirements.txt && DB_PATH=./.data uvicorn app.main:app --reload --port 5000
|
||||
cd src/frontend && npm install && npm run dev # Vite on :3000
|
||||
cd src/frontend && npm run build # tsc is not run by build; use `npx tsc --noEmit` for type checking
|
||||
```
|
||||
|
||||
`nginx.conf` (repo root) expects `backend:5000` and `frontend:8000`, so running outside Compose needs your own proxy for `/api`.
|
||||
|
||||
CI (`.gitea/workflows/build-and-push-images.yaml`) builds and pushes backend/frontend images with Kaniko on changes to `src/**`.
|
||||
|
||||
## Architecture
|
||||
|
||||
**Backend** (`src/backend/app/`): almost every route is in the single `main.py` (~1300 lines), with Pydantic request models at the top. `services/` holds helpers (accounts/tokens, email, per-order file storage, submissions, config loading); `db.py` creates the schema inline in `init_db()` (`CREATE TABLE IF NOT EXISTS` plus ad-hoc `ALTER TABLE` migrations — there is no migration tool) and maps rows to dicts.
|
||||
|
||||
**Auth model:** there are no passwords or sessions. The client generates a user ID and sends it in the `X-User-Id` header (`get_existing_user_id` dependency). Per-order access is via tokens stored in `user_order_tokens` (`admin_token` = order owner, `submission_token` = participant); routes under `/api/orders/{id}/admin/...` check the caller's admin token. Email confirmation, user-ID change, email change and account migration flows use `account_confirmation_tokens` and send mail through `email_service`.
|
||||
|
||||
**Storage is split:** SQLite (`burger_orders.db` in `DB_PATH`) holds orders, submissions, user profiles and tokens. Per-order content is stored as files under `data/` next to the app, **keyed by the order's `admin_token`**: `configs/<token>.json` (menu/form definition), `descriptions/<token>.md`, `templates/`, `payments/`, and uploaded `images/` (served at `/api/images`). Deleting an order must also delete these files (see `delete_order` in `main.py`).
|
||||
|
||||
**App config:** `config.yaml` (mounted read-only at `/app/config.yaml`) controls `public_base_url`, SMTP settings and UI announcements; loaded by `services/config_service.py` and exposed via `GET /api/config`.
|
||||
|
||||
**Frontend** (`src/frontend/src/`): no router library — `lib/routing.ts` parses `window.location` into `home | create | order | admin` routes and `App.tsx` switches between the four `views/`. `lib/api.ts` wraps `fetch` (adds `X-User-Id`, clears the stored ID on "invalid user id" 401s); `lib/services/*` are typed per-domain API clients; `hooks/useApiRequest.ts` and `components/utils/AsyncContent.tsx` handle loading/error state. `lib/orderTemplating.ts` and `lib/orderFormatting.ts` render submissions into the text that is shared/exported from the form config. `TODO.md` tracks planned admin-view work.
|
||||
|
||||
Dev note: Compose mounts only `backend/app` and selected frontend source into the containers, so changes to `requirements.txt`/`package.json` need a rebuild. `src/frontend/dist/` is committed build output.
|
||||
Reference in new issue
Block a user