01b4267964
Point mcma-backend + mcma-webui at their sloppyslop tips (lyrics, transcoding, admin/storage/maintenance/instance UI, batch metadata, NowPlaying+lyrics). Includes the CORS note in .env.example, TODO/ ignore, and the project CLAUDE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
104 lines
5.1 KiB
Markdown
104 lines
5.1 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## What this repo is
|
|
|
|
`mcma-compose` is the **dev-orchestration superproject** for *mycoolmusicapp* — a self-hosted music
|
|
app. It contains no application code of its own: `docker-compose.yml`, `nginx.conf`, `Makefile`, and
|
|
`.env.example`. The actual code lives in two **git submodules**:
|
|
|
|
- `mcma-backend/` — Python / FastAPI (async), arq background workers, Alembic migrations.
|
|
- `mcma-webui/` — TypeScript / React, built with Rsbuild.
|
|
|
|
Both submodules are pulled from `ssh://git@git.ollyhearn.ru:49239` (see `.gitmodules`). **They may be
|
|
empty** — clone with `git clone --recurse-submodules`, or run `git submodule update --init` in an
|
|
existing checkout, before you can touch or build app code.
|
|
|
|
## The stack
|
|
|
|
`make up` builds and starts six services (see `docker-compose.yml`):
|
|
|
|
| Service | Image / context | Role |
|
|
|----------|-------------------|------|
|
|
| `db` | postgres:16-alpine | PostgreSQL, data in `./data/pgdata` |
|
|
| `redis` | redis:7-alpine | arq broker + cache, data in `./data/redisdata` |
|
|
| `api` | `mcma-backend` | FastAPI via `uvicorn --reload` |
|
|
| `worker` | `mcma-backend` | `arq app.workers.arq_worker.WorkerSettings` background jobs |
|
|
| `webui` | `mcma-webui` | Rsbuild dev server with HMR |
|
|
| `nginx` | nginx:1.27-alpine | **single entrypoint**, reverse proxy |
|
|
|
|
Key architectural points that span multiple files:
|
|
|
|
- **nginx is the only public port.** It routes `/api/` and `/health` → `api:8000`, everything else
|
|
(including the `/rsbuild-hmr` websocket) → `webui:3000`. The browser never talks to webui directly;
|
|
HMR is proxied through nginx, which is why compose sets `RSBUILD_HMR_CLIENT_PORT` to `NGINX_PORT`.
|
|
- **The entrypoint is `http://localhost:8881`**, not `:80`. Compose maps `${NGINX_PORT:-8881}:80`
|
|
(README says `:80`, but the `.env.example` default is `8881`). `api:8000` is also exposed directly
|
|
for docs/debugging (`/docs`).
|
|
- **Source is bind-mounted** into `api`, `worker`, and `webui`, so edits in the submodules hot-reload
|
|
with no rebuild. Named-volume mounts (`/app/.venv`, `/app/node_modules`) shadow the host dir to
|
|
preserve the image's installed deps — if you change dependencies you must rebuild (`make build`).
|
|
- **`api` and `worker` share the same image** and both need `db` + `redis` healthy before starting.
|
|
- **`DATABASE_URL` / `REDIS_URL` are overridden inside compose** to use service names
|
|
(`db`, `redis`). The localhost values in `.env` are only the fallback for host-run processes.
|
|
- **Persistent state and media live under `./data/`** (gitignored): `pgdata`, `redisdata`, `media`,
|
|
`transcode-cache`, and `youtube` (drop a yt-dlp `cookies.txt` here — optional).
|
|
|
|
## Commands
|
|
|
|
Everything runs **inside the containers** via the `Makefile`, which wraps `docker compose exec`.
|
|
The stack must be up (`make up`) before `test`/`lint`/`migrate`/shell targets work. Run `make help`
|
|
for the full list.
|
|
|
|
```bash
|
|
make up # create .env from .env.example, build images, start the whole stack
|
|
make build # rebuild images (with cache); needed after dependency changes
|
|
make rebuild # rebuild with --no-cache
|
|
make down # stop + remove containers
|
|
make clean # down -v — DESTROYS db/redis volumes
|
|
make logs-api # tail a single service's logs (also logs, logs-webui)
|
|
make sh-api # bash into api (also sh-webui, db-shell, redis-cli)
|
|
```
|
|
|
|
Migrations (Alembic, run in the `api` container):
|
|
|
|
```bash
|
|
make migrate # alembic upgrade head
|
|
make makemigration m="add_tracks" # autogenerate a revision
|
|
make downgrade # roll back one
|
|
```
|
|
|
|
Quality — these shell out to the tools inside each container:
|
|
|
|
```bash
|
|
make test # test-api (pytest) + test-webui (npm test)
|
|
make test-api # pytest — for a single test: make sh-api, then `pytest path::test`
|
|
make test-webui # npm test
|
|
make lint # ruff check . (api) + npm run lint (webui)
|
|
make fmt # ruff format . (api) + npm run format (webui)
|
|
```
|
|
|
|
There is **no dev docker-compose for prod**. Prod images are built straight from each submodule's
|
|
`dockerfiles/Dockerfile.prod`:
|
|
|
|
```bash
|
|
make prod-build # builds mcma-backend:prod and mcma-webui:prod
|
|
```
|
|
|
|
## Environment
|
|
|
|
`.env` is a single combined file at the repo root, created from `.env.example` by `make env` /
|
|
`make up` (never committed; it's gitignored). It is injected into `api`, `worker`, and `webui`.
|
|
Backend features degrade gracefully when optional keys are unset:
|
|
|
|
- `ACOUSTID_API_KEY` + `MUSICBRAINZ_OWNER_EMAIL` — enable AcoustID/MusicBrainz metadata enrichment.
|
|
- `YOUTUBE_ENABLED` / `YOUTUBE_COOKIES_PATH` — YouTube Music source via yt-dlp.
|
|
- `ALLOW_REGISTRATION` (backend) must be kept in sync with `PUBLIC_ENABLE_REGISTRATION` (frontend).
|
|
|
|
## Working across submodules
|
|
|
|
When a change touches app behavior, the code is in `mcma-backend/` or `mcma-webui/` — commit there
|
|
first, then the superproject records the new submodule commit. Recent superproject history is mostly
|
|
`chore: bump mcma-backend/mcma-webui` commits that pin updated submodule SHAs.
|