docs: add AGENTS.md for repo, backend and frontend
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
# Chitai
|
||||
|
||||
Self-hosted eBook library manager. Users organise eBook files into **libraries**, which contain
|
||||
**books** (one book = one metadata record + one or more files on disk). Books carry authors,
|
||||
publishers, tags, series and identifiers, can be grouped into per-user **bookshelves**, and are read
|
||||
in-browser through built-in EPUB and PDF readers with reading-progress tracking. The catalogue is
|
||||
also exposed as an **OPDS** feed for e-reader apps, and progress syncs with **KOReader** devices via
|
||||
a KOSync-compatible endpoint.
|
||||
|
||||
## Layout
|
||||
|
||||
| Path | What |
|
||||
| --- | --- |
|
||||
| `backend/` | Litestar REST API + PostgreSQL. See `backend/AGENTS.md`. |
|
||||
| `frontend/` | SvelteKit SSR web app. See `frontend/AGENTS.md`. |
|
||||
| `docker-compose.yml` | Production stack: `db` (postgres:17), `backend`, `frontend`. |
|
||||
| `docs/screenshots/` | Images used by `README.md`. |
|
||||
| `shell.nix` | Root dev shell; composes the two sub-shells. |
|
||||
|
||||
## Development environment
|
||||
|
||||
`nix-shell` from the repo root is the intended entry point. It pulls in both
|
||||
`backend/shell.nix` and `frontend/shell.nix`, whose `shellHook`s do real work as a side effect:
|
||||
|
||||
- **backend** — `uv venv` + `uv sync`, then `initdb` / `pg_ctl start` into `backend/.postgres/`
|
||||
(socket dir, not TCP), `createdb chitai`, and finally applies migrations with
|
||||
`alchemy --config chitai.database.config.config upgrade --no-prompt`.
|
||||
`exitHook` stops PostgreSQL on shell exit.
|
||||
- **frontend** — `pnpm install`.
|
||||
|
||||
So entering the shell gives you a running database with an up-to-date schema; you do not need to
|
||||
start Postgres yourself. Both hooks `cd` around, which can be surprising in scripts.
|
||||
|
||||
Without Nix you need: Python 3.13 + `uv`, Node 24 + `pnpm`, and PostgreSQL 17 with the `pg_trgm`
|
||||
extension available.
|
||||
|
||||
## Configuration
|
||||
|
||||
All backend settings are read by `backend/src/chitai/config.py` (`Settings`, pydantic-settings) with
|
||||
the **`CHITAI_` prefix** from the repo-root `.env`. `.env.prod-example` is the template; copy it to
|
||||
`.env` for a fresh deployment.
|
||||
|
||||
`.env` is gitignored and contains a real `CHITAI_TOKEN_SECRET` — do not print, copy or commit it.
|
||||
|
||||
The frontend reads exactly one variable, `VITE_BACKEND_API_URL`
|
||||
(`frontend/src/lib/server/config.ts`, defaulting to `http://localhost:8000`).
|
||||
|
||||
## How a request flows
|
||||
|
||||
```
|
||||
browser
|
||||
└─ SvelteKit SSR node server
|
||||
├─ hooks.server.ts reads `authToken` cookie, validates via GET /access/me,
|
||||
│ populates locals.user / locals.api, redirects to /login otherwise
|
||||
├─ $lib/api/*.remote.ts remote functions (query/command/form) → locals.api (ApiClient)
|
||||
└─ routes/api/[...path] catch-all proxy, for browser-direct fetches (reader file streams)
|
||||
└─ Litestar backend
|
||||
└─ controllers/ → services/ → SQLAlchemy models → PostgreSQL
|
||||
```
|
||||
|
||||
The JWT the frontend holds in the `authToken` cookie is the same bearer token the backend issues
|
||||
from `POST /access/login`. The frontend never stores credentials beyond that cookie.
|
||||
|
||||
## Commands
|
||||
|
||||
Backend (from `backend/`):
|
||||
|
||||
```bash
|
||||
uv run litestar --app-dir src/chitai/ run --reload # dev server on :8000
|
||||
pytest tests/ # needs Docker (pytest-databases)
|
||||
ruff format src/
|
||||
alchemy --config chitai.database.config.config make-migrations
|
||||
alchemy --config chitai.database.config.config upgrade
|
||||
```
|
||||
|
||||
Frontend (from `frontend/`):
|
||||
|
||||
```bash
|
||||
pnpm dev # vite dev server on :5173
|
||||
pnpm build # adapter-node output in build/
|
||||
pnpm check # svelte-check — run before finishing
|
||||
pnpm lint # prettier --check + eslint
|
||||
pnpm format # prettier --write
|
||||
```
|
||||
|
||||
API docs are served by the running backend at `http://localhost:8000/schema/` (Swagger) and
|
||||
`/schema/openapi.json`.
|
||||
|
||||
## Cross-cutting rules
|
||||
|
||||
- **Keep the two schema layers in sync.** Backend request/response shapes live in
|
||||
`backend/src/chitai/schemas/` (Pydantic); the frontend mirrors them as Zod schemas in
|
||||
`frontend/src/lib/schema/`. Changing one without the other produces runtime validation failures,
|
||||
not type errors.
|
||||
- **Regenerate the OpenAPI types** after changing API shapes.
|
||||
`frontend/src/lib/schema/openapi/schema.d.ts` is generated from the backend's OpenAPI document
|
||||
with `openapi-typescript` (a devDependency; there is no `package.json` script for it, so it is run
|
||||
manually against a live backend).
|
||||
- **Migrations are mandatory.** The app runs with `create_all=False`, so a model change without a
|
||||
matching Alembic revision will not reach the database.
|
||||
- **Commit messages** follow `type: summary` — `feat:`, `fix:`, `refactor:`, `chore:`.
|
||||
- The three `README.md` files are user-facing. Agent-facing knowledge belongs in the `AGENTS.md`
|
||||
files.
|
||||
Reference in New Issue
Block a user