4.0 KiB
4.0 KiB
AGENTS.md
Safety Rules
- Dev branch naming:
{feat|fix|docs|chore}/{branch-name}(e.g.feat/file-tag-done,fix/tree-render). - Before
git commit: rungit branch --show-current. If onmaster, do NOT commit — ask user for a branch name (suggest one based on the changes), create it, commit there. - Every user-visible change gets a changelog entry: WebUI changes (files under
frontend/) →docs/CHANGELOG_web.md, everything else →docs/CHANGELOG.md; never duplicate an entry across both. Higher versions on top. - CHANGELOG entry format: same entry has English line then Chinese line on consecutive lines (no blank line between them); different entries are separated by a blank line.
docs/README.mdanddocs/README_zh.mdstay content-equivalent; update them in the same change.
Docker deployment (dev & release)
- dev =
deploy/docker-compose.dev.yml: source bind-mounted (../backend:/app,../frontend:/appwith an anonymous volume on/app/node_modules),target: devimages; api runsgo mod download && dlv debug ./cmd/webui(delve on 2345), web runsnpm run dev(hot reload, no rebuild needed); infra ports exposed to host (postgres 5432, redis 6379); startup gated on healthchecks. - release =
deploy/docker-compose.yml: multi-stage*.prodDockerfiles (target: runner) with compiled binaries, no source mounts; infra ports stay on the internal network only. - Persisted state lives only in named volumes
booklib_{postgres,redis}_data— same names in both files, so dev and release see the same data. Onlydown -vwipes them. - Books on disk: host
deploy/api/storageis mounted as/data/books(BOOKS_DIR); uploads land there and the scanner picks them up. - Rendered configs
deploy/nginx/nginx.conf,deploy/nginx/conf.d/default.conf,deploy/redis/redis.conf(mounted:ro) come from their*.tplviadeploy/prepare.sh— edit the template, rerunprepare.sh, restart; stale files in a container mean you forgot to rerun. Host logs underdeploy/logs/. - Tear down with
down, notrm, or the web image's anonymousnode_modulesvolume gets orphaned.
Project structure
Root: docs (docs + changelogs), backend (Go webui service), frontend (node app, served via nginx in release), deploy (compose stacks, rendered configs, host logs). Actual layout is visible via ls; only rules not derivable from it are listed here.
backend
cmd/: each subdir is exactly onemainpackage;main.goonly bootstraps (load config, wire deps, serve, graceful shutdown) — no business logic, and nothing outsidecmdimportscmd.cmd/webui/apiis the single source of truth for the endpoint contract; the frontend aligns with it.- Handlers stay thin (bind/validate, call
internal, map errors) — never touch the DB or implement domain rules; SQL and business rules live behindinternalboundaries. - Business code defaults to
internal/;pkg/is opt-in public surface shared with other repos — keep it small, never leakinternaltypes through it.
frontend
- Talks to the backend only over the HTTP APIs in
backend/cmd/webui/api— no direct infra access (DB, redis) from the browser app. - Build output (
dist/) is disposable and git-ignored; onlysrc/publicare committed. - Dev runs from the source mount with
node_modulesprovided by the image — install new deps inside the container and commit the lockfile. - TypeScript runs side-by-side (
frontend/package.json):typescript= TS 6.0.2 JS API for tooling (typescript-eslint doesn't support TS 7 yet),@typescript/native= native 7.0.2 providingtsc. Do not re-aliastypescriptto 7.x until typescript-eslint ships TS 7 support. Plainnpm installneeds--legacy-peer-deps(also pinned infrontend/.npmrc);npm ciis unaffected.
deploy
- Only config templates/examples are tracked by git; rendered
*.confandlogs/are git-ignored. - Service-specific host dirs (storage, config) go under
deploy/{$service_name}/, never loose at the repo root.