docs(legibility): write human-targeted README.md at repo root #395

Closed
opened 2026-05-04 16:07:22 +02:00 by marcel · 10 comments
Owner

Context

Part of Epic #394 — Documentation. This is DOC-1: write the front door of the project. Today's README.md (if present) is LLM-targeted via CLAUDE.md; we need a separate README.md written for humans (specifically Tobias, who will open it first and form a 60-second judgment).

Per the Legibility Rubric, this issue addresses C1.1, C1.2, C1.4, C2.1, C2.2, C2.3 (all Critical or Major).

Required content

A single README.md at repo root containing, in this order:

1. One-paragraph product description

What Familienarchiv is, who it's for, what problem it solves. ≤3 sentences. A reader who never met you should be able to describe the product accurately after this paragraph.

2. Subsystem map

Bullet list naming the 5 subsystems with a one-line purpose each:

  • frontend/ — SvelteKit 2 / Svelte 5 / TypeScript / Tailwind 4 web app
  • backend/ — Spring Boot 4 (Java 21) REST API
  • ocr-service/ — Python FastAPI for OCR/HTR (single-node by design — see ADR-001)
  • infra/ — CI/CD config (Gitea Actions); future home for IaC
  • scripts/ — operational + data-pipeline helpers

3. Quick start

Numbered steps that take a stranger from clone to working app in ≤15 min. Must include:

  • Prerequisites with versions: Java 21, Node 24, Docker, docker-compose
  • The single command (or short sequence) to bring up the stack
  • Default admin credentials for local dev (admin@familyarchive.local / admin123)
  • Where the app is reachable (http://localhost:3000, http://localhost:8080/v3/api-docs)

4. Where to go next

Links to:

  • docs/ARCHITECTURE.md — how the system is built (DOC-2)
  • CONTRIBUTING.md — how to add features (DOC-4)
  • docs/DEPLOYMENT.md — how to run in production (DOC-5)
  • docs/GLOSSARY.md — disambiguate overloaded terms (DOC-3)
  • The Gitea issue tracker URL where issues live

Anti-patterns (what NOT to do)

  • Do NOT copy CLAUDE.md content into the README. CLAUDE.md is for an LLM; the README is for a human.
  • Do NOT include detailed conventions, architecture rules, or coding style — those go in CONTRIBUTING.md or docs/ARCHITECTURE.md.
  • Do NOT use emoji or marketing language. Plain, technical, friendly.
  • Do NOT exceed ~150 lines. The README is a front door, not a manual.

Acceptance criteria

  • README.md exists at repo root with the 5 sections above
  • Tobias-equivalent (a CS-bachelor PM) can describe the product accurately after reading the first paragraph
  • A stranger can git clone && cd familienarchiv && <quickstart command> and reach the running app in ≤15 min
  • All forward links resolve to actual files (or are listed as "TODO once DOC-N lands" if those issues aren't done yet)
  • CLAUDE.md (root) is updated to reference the new README and removes any duplicated front-matter
  • PR opened and merged

Dependency

Soft dependency on AUDIT-5 (#392) for findings about repo hygiene; can start without it if needed.

Definition of Done

README.md committed on main; closing comment on this issue links to the new README. Issue closed via Closes #N in commit.

## Context Part of **Epic #394** — Documentation. This is **DOC-1**: write the front door of the project. Today's `README.md` (if present) is LLM-targeted via `CLAUDE.md`; we need a separate `README.md` written for humans (specifically Tobias, who will open it first and form a 60-second judgment). Per the Legibility Rubric, this issue addresses **C1.1, C1.2, C1.4, C2.1, C2.2, C2.3** (all Critical or Major). ## Required content A single `README.md` at repo root containing, in this order: ### 1. One-paragraph product description What Familienarchiv is, who it's for, what problem it solves. ≤3 sentences. A reader who never met you should be able to describe the product accurately after this paragraph. ### 2. Subsystem map Bullet list naming the 5 subsystems with a one-line purpose each: - `frontend/` — SvelteKit 2 / Svelte 5 / TypeScript / Tailwind 4 web app - `backend/` — Spring Boot 4 (Java 21) REST API - `ocr-service/` — Python FastAPI for OCR/HTR (single-node by design — see ADR-001) - `infra/` — CI/CD config (Gitea Actions); future home for IaC - `scripts/` — operational + data-pipeline helpers ### 3. Quick start Numbered steps that take a stranger from clone to working app in ≤15 min. Must include: - Prerequisites with versions: Java 21, Node 24, Docker, docker-compose - The single command (or short sequence) to bring up the stack - Default admin credentials for local dev (`admin@familyarchive.local` / `admin123`) - Where the app is reachable (`http://localhost:3000`, `http://localhost:8080/v3/api-docs`) ### 4. Where to go next Links to: - `docs/ARCHITECTURE.md` — how the system is built (DOC-2) - `CONTRIBUTING.md` — how to add features (DOC-4) - `docs/DEPLOYMENT.md` — how to run in production (DOC-5) - `docs/GLOSSARY.md` — disambiguate overloaded terms (DOC-3) - The Gitea issue tracker URL where issues live ### 5. License + copyright (if applicable) ## Anti-patterns (what NOT to do) - Do NOT copy `CLAUDE.md` content into the README. CLAUDE.md is for an LLM; the README is for a human. - Do NOT include detailed conventions, architecture rules, or coding style — those go in `CONTRIBUTING.md` or `docs/ARCHITECTURE.md`. - Do NOT use emoji or marketing language. Plain, technical, friendly. - Do NOT exceed ~150 lines. The README is a front door, not a manual. ## Acceptance criteria - [ ] `README.md` exists at repo root with the 5 sections above - [ ] Tobias-equivalent (a CS-bachelor PM) can describe the product accurately after reading the first paragraph - [ ] A stranger can `git clone && cd familienarchiv && <quickstart command>` and reach the running app in ≤15 min - [ ] All forward links resolve to actual files (or are listed as "TODO once DOC-N lands" if those issues aren't done yet) - [ ] `CLAUDE.md` (root) is updated to reference the new README and removes any duplicated front-matter - [ ] PR opened and merged ## Dependency Soft dependency on AUDIT-5 (#392) for findings about repo hygiene; can start without it if needed. ## Definition of Done `README.md` committed on `main`; closing comment on this issue links to the new README. Issue closed via `Closes #N` in commit.
marcel added this to the Codebase Legibility milestone 2026-05-04 16:07:22 +02:00
marcel added the P0-criticaldocumentationlegibility labels 2026-05-04 16:09:47 +02:00
Author
Owner

👨‍💻 Felix Brandt — Senior Fullstack Developer

Observations

  • The issue spec is well-scoped: exactly 5 sections, hard cap at 150 lines, and a clear "not a CLAUDE.md copy" guard. This is implementable in a single focused session.
  • The quick-start section lists Java 21, Node 24, Docker, docker-compose as prerequisites. I checked docker-compose.ymldocker-compose up -d starts only the DB, MinIO, and backend. The frontend requires a separate npm run dev from frontend/. The spec says "short sequence to bring up the stack" — two commands are fine, but they need to be listed explicitly so the stranger doesn't stop at a blank browser.
  • There is no .env.example at the repo root. The docker-compose.yml references ${POSTGRES_USER}, ${POSTGRES_PASSWORD}, ${MINIO_ROOT_USER}, etc. A stranger who tries docker-compose up -d without a .env will hit an immediate failure before seeing a running app. The README should call this out, or a .env.example should exist.
  • The "Where to go next" links target docs/ARCHITECTURE.md, CONTRIBUTING.md, docs/DEPLOYMENT.md, docs/GLOSSARY.md — none of these files exist yet (DOC-2 through DOC-5 are future issues). The acceptance criterion says to mark them as "TODO once DOC-N lands." Be explicit in the README: [docs/ARCHITECTURE.md — TODO: lands with DOC-2 (#396)]. Vague "coming soon" is worse than nothing.
  • The OCR service (ocr-service/) is not in the docker-compose.yml dev stack (it's a separate Python service). The subsystem map should not imply it starts with the main compose command.

Recommendations

  • Add a .env.example file to the repo root as a sibling to this issue, or at minimum document the required env vars in the quick-start section of the README. Without it, the "≤15 min from clone to running" acceptance criterion cannot be met.
  • Quick-start sequence should be explicit:
    1. Copy .env.example to .env and fill in values (or note the defaults for local dev)
    2. docker compose up -d — starts DB, MinIO, backend
    3. cd frontend && npm install && npm run dev
    4. Open http://localhost:3000
  • For the subsystem map, note that ocr-service/ runs independently and is not part of the default docker compose up.
  • Use concrete issue references for the TODO links (e.g., "DOC-2, issue #396") so readers know exactly when to expect them.
## 👨‍💻 Felix Brandt — Senior Fullstack Developer ### Observations - The issue spec is well-scoped: exactly 5 sections, hard cap at 150 lines, and a clear "not a CLAUDE.md copy" guard. This is implementable in a single focused session. - The quick-start section lists Java 21, Node 24, Docker, docker-compose as prerequisites. I checked `docker-compose.yml` — `docker-compose up -d` starts only the DB, MinIO, and backend. The frontend requires a separate `npm run dev` from `frontend/`. The spec says "short sequence to bring up the stack" — two commands are fine, but they need to be listed explicitly so the stranger doesn't stop at a blank browser. - There is no `.env.example` at the repo root. The `docker-compose.yml` references `${POSTGRES_USER}`, `${POSTGRES_PASSWORD}`, `${MINIO_ROOT_USER}`, etc. A stranger who tries `docker-compose up -d` without a `.env` will hit an immediate failure before seeing a running app. The README should call this out, or a `.env.example` should exist. - The "Where to go next" links target `docs/ARCHITECTURE.md`, `CONTRIBUTING.md`, `docs/DEPLOYMENT.md`, `docs/GLOSSARY.md` — none of these files exist yet (DOC-2 through DOC-5 are future issues). The acceptance criterion says to mark them as "TODO once DOC-N lands." Be explicit in the README: `[docs/ARCHITECTURE.md — TODO: lands with DOC-2 (#396)]`. Vague "coming soon" is worse than nothing. - The OCR service (`ocr-service/`) is **not** in the `docker-compose.yml` dev stack (it's a separate Python service). The subsystem map should not imply it starts with the main compose command. ### Recommendations - Add a `.env.example` file to the repo root as a sibling to this issue, or at minimum document the required env vars in the quick-start section of the README. Without it, the "≤15 min from clone to running" acceptance criterion cannot be met. - Quick-start sequence should be explicit: 1. Copy `.env.example` to `.env` and fill in values (or note the defaults for local dev) 2. `docker compose up -d` — starts DB, MinIO, backend 3. `cd frontend && npm install && npm run dev` 4. Open `http://localhost:3000` - For the subsystem map, note that `ocr-service/` runs independently and is not part of the default `docker compose up`. - Use concrete issue references for the TODO links (e.g., "DOC-2, issue #396") so readers know exactly when to expect them.
Author
Owner

🏛️ Markus Keller — Senior Application Architect

Observations

  • The subsystem map as specified in the issue is technically accurate. The 5 subsystems (frontend/, backend/, ocr-service/, infra/, scripts/) map correctly to distinct concerns with different deployment characteristics.
  • The ADR directory (docs/adr/) exists and has 6 records. The README's "Where to go next" section currently targets docs/ARCHITECTURE.md (DOC-2, not yet written), but there is a docs/architecture/c4-diagrams.md that already exists. This is a real navigational asset that a new contributor would want to know about — it should either be linked directly or DOC-2 should be noted as the canonical home when it lands.
  • The issue's "Where to go next" section has no link to the ADR directory. Architecture Decision Records exist and are the memory of why certain choices were made (e.g., ADR-001 cited in the issue body for the OCR single-node design). The README should direct readers to docs/adr/ as a primary navigational aid — it's already populated and doesn't depend on any future doc issue.
  • The spec says the README should explain "how the system is built" via a future docs/ARCHITECTURE.md. This is fine, but the ADR index is the complementary "why" resource that already exists.
  • No licence file is present in the repo. The issue includes "License + copyright (if applicable)" as section 5. For a family project containing private documents of living people, the absence of a license is itself a choice worth documenting briefly — even a short "private project, all rights reserved" line prevents ambiguity.

Recommendations

  • Add a direct link to docs/adr/ in the "Where to go next" section. It's the most complete documentation that currently exists and a new contributor will want it immediately.
  • Link the already-existing docs/architecture/c4-diagrams.md as a provisional architecture overview until DOC-2 lands.
  • For section 5 (license), even if no open-source license applies: "Private project — all rights reserved. Not licensed for redistribution." One line. Prevents ambiguity.
  • Do not forward-link docs/ARCHITECTURE.md without a "TODO" marker — a dead link is worse than a missing link.
## 🏛️ Markus Keller — Senior Application Architect ### Observations - The subsystem map as specified in the issue is technically accurate. The 5 subsystems (`frontend/`, `backend/`, `ocr-service/`, `infra/`, `scripts/`) map correctly to distinct concerns with different deployment characteristics. - The ADR directory (`docs/adr/`) exists and has 6 records. The README's "Where to go next" section currently targets `docs/ARCHITECTURE.md` (DOC-2, not yet written), but there is a `docs/architecture/c4-diagrams.md` that already exists. This is a real navigational asset that a new contributor would want to know about — it should either be linked directly or DOC-2 should be noted as the canonical home when it lands. - The issue's "Where to go next" section has no link to the ADR directory. Architecture Decision Records exist and are the memory of why certain choices were made (e.g., ADR-001 cited in the issue body for the OCR single-node design). The README should direct readers to `docs/adr/` as a primary navigational aid — it's already populated and doesn't depend on any future doc issue. - The spec says the README should explain "how the system is built" via a future `docs/ARCHITECTURE.md`. This is fine, but the ADR index is the complementary "why" resource that already exists. - No licence file is present in the repo. The issue includes "License + copyright (if applicable)" as section 5. For a family project containing private documents of living people, the absence of a license is itself a choice worth documenting briefly — even a short "private project, all rights reserved" line prevents ambiguity. ### Recommendations - Add a direct link to `docs/adr/` in the "Where to go next" section. It's the most complete documentation that currently exists and a new contributor will want it immediately. - Link the already-existing `docs/architecture/c4-diagrams.md` as a provisional architecture overview until DOC-2 lands. - For section 5 (license), even if no open-source license applies: "Private project — all rights reserved. Not licensed for redistribution." One line. Prevents ambiguity. - Do not forward-link `docs/ARCHITECTURE.md` without a "TODO" marker — a dead link is worse than a missing link.
Author
Owner

🔒 Nora "NullX" Steiner — Application Security Engineer

Observations

  • The issue explicitly includes default admin credentials in the README: admin@familyarchive.local / admin123. This is intentional for local dev and the anti-patterns section correctly excludes "copy CLAUDE.md" which already contains these credentials. The risk is reasonable for local dev, provided the README makes unmistakably clear these are dev-only values that must be changed before any network-exposed deployment.
  • I checked docker-compose.yml: the PostgreSQL port is exposed externally ("${PORT_DB}:5432"), and MinIO uses minio:latest (unpinned tag). Neither of these belong in the README itself, but a first-time reader who follows the quick-start blindly will expose the DB port to their network. The README quick-start should include a brief note: "⚠️ The default Docker Compose is configured for local development only — do not expose these services to a network without reviewing docs/DEPLOYMENT.md."
  • The "Where to go next" list includes docs/DEPLOYMENT.md (DOC-5, not yet written). Until that doc exists, there is no documented path for safe production deployment. The README should be explicit: production deployment documentation is not yet available.
  • Credentials appearing verbatim in a public-facing README concern me more when the repo is self-hosted (Gitea, 192.168.178.71) than on a public GitHub. Context: this is private family infrastructure, so the blast radius is low. Still, a one-line callout is free: "Development credentials only — change these before connecting to any network."
  • No security-related concerns with the README content itself (it's documentation, not code). No injection vectors, no exposure beyond informational.

Recommendations

  • Add a visible warning to the quick-start section that the dev stack exposes the DB port and uses root MinIO credentials. One sentence is enough: "This setup is for local development only. See docs/DEPLOYMENT.md for production hardening."
  • Format admin credentials as a code block explicitly labeled # local dev only — this gives future automated secret scanners (e.g., Gitleaks) a clear false-positive signal and makes the intent unmistakable.
  • When DOC-5 (docs/DEPLOYMENT.md) lands, ensure it covers: change default credentials, use MinIO service accounts, close DB port, enable HTTPS. The README sets the expectation that it will.
## 🔒 Nora "NullX" Steiner — Application Security Engineer ### Observations - The issue explicitly includes default admin credentials in the README: `admin@familyarchive.local` / `admin123`. This is intentional for local dev and the anti-patterns section correctly excludes "copy CLAUDE.md" which already contains these credentials. **The risk is reasonable for local dev**, provided the README makes unmistakably clear these are dev-only values that must be changed before any network-exposed deployment. - I checked `docker-compose.yml`: the PostgreSQL port is exposed externally (`"${PORT_DB}:5432"`), and MinIO uses `minio:latest` (unpinned tag). Neither of these belong in the README itself, but a first-time reader who follows the quick-start blindly will expose the DB port to their network. The README quick-start should include a brief note: "⚠️ The default Docker Compose is configured for local development only — do not expose these services to a network without reviewing `docs/DEPLOYMENT.md`." - The "Where to go next" list includes `docs/DEPLOYMENT.md` (DOC-5, not yet written). Until that doc exists, there is no documented path for safe production deployment. The README should be explicit: production deployment documentation is not yet available. - Credentials appearing verbatim in a public-facing README concern me more when the repo is self-hosted (Gitea, 192.168.178.71) than on a public GitHub. Context: this is private family infrastructure, so the blast radius is low. Still, a one-line callout is free: "**Development credentials only — change these before connecting to any network.**" - No security-related concerns with the README content itself (it's documentation, not code). No injection vectors, no exposure beyond informational. ### Recommendations - Add a visible warning to the quick-start section that the dev stack exposes the DB port and uses root MinIO credentials. One sentence is enough: "This setup is for local development only. See `docs/DEPLOYMENT.md` for production hardening." - Format admin credentials as a code block explicitly labeled `# local dev only` — this gives future automated secret scanners (e.g., Gitleaks) a clear false-positive signal and makes the intent unmistakable. - When DOC-5 (`docs/DEPLOYMENT.md`) lands, ensure it covers: change default credentials, use MinIO service accounts, close DB port, enable HTTPS. The README sets the expectation that it will.
Author
Owner

🧪 Sara Holt — Senior QA Engineer

Observations

  • The acceptance criteria are well-written for a documentation issue. The "Tobias-equivalent can describe the product accurately after reading the first paragraph" criterion is a good usability test, but it's a manual check — it should be done explicitly during review by asking someone (or imagining someone) who hasn't seen the project before.
  • The "A stranger can git clone && cd familienarchiv && <quickstart command> and reach the running app in ≤15 min" criterion is testable by actually doing it in a clean environment. I'd suggest running this test before marking the PR as ready for review — it's easy to skip steps that are obvious to someone who built the app.
  • The criterion "All forward links resolve to actual files (or are listed as 'TODO once DOC-N lands')" is directly testable with a simple script (grep -E '\[.+\]\(docs/.+\)' README.md | xargs -I{} test -f {}). This should be added to the PR checklist.
  • The criterion about updating CLAUDE.md to reference the README and remove duplicated front-matter is the most ambiguous acceptance criterion here. "Duplicated front-matter" needs a clearer definition — what specifically in CLAUDE.md would be considered duplication once README.md exists? The product overview, stack list, and quick-start commands currently appear in CLAUDE.md. Clarify: should these be removed from CLAUDE.md (pointing to README), kept in both (redundant but fine), or left as-is (CLAUDE.md is for LLMs, README for humans, no conflict)?
  • No automated tests are needed for a README — this is pure documentation. The test strategy is: manual review checklist + link-validity check.

Recommendations

  • Add a PR checklist item: "Tested the quick-start in a clean environment (or a checklist review of each step against the actual repo state)."
  • Add a PR checklist item: "All links verified — forward links to future docs are explicitly marked TODO with issue numbers."
  • Clarify in the issue or during implementation: exactly which parts of CLAUDE.md should be updated/removed once README.md exists. The current AC is too vague to verify.
  • The 150-line limit is a good scope guard. Track line count in the PR — it's a fast check that prevents scope creep during writing.
## 🧪 Sara Holt — Senior QA Engineer ### Observations - The acceptance criteria are well-written for a documentation issue. The "Tobias-equivalent can describe the product accurately after reading the first paragraph" criterion is a good usability test, but it's a manual check — it should be done explicitly during review by asking someone (or imagining someone) who hasn't seen the project before. - The "A stranger can `git clone && cd familienarchiv && <quickstart command>` and reach the running app in ≤15 min" criterion is testable by actually doing it in a clean environment. I'd suggest running this test before marking the PR as ready for review — it's easy to skip steps that are obvious to someone who built the app. - The criterion "All forward links resolve to actual files (or are listed as 'TODO once DOC-N lands')" is directly testable with a simple script (`grep -E '\[.+\]\(docs/.+\)' README.md | xargs -I{} test -f {}`). This should be added to the PR checklist. - The criterion about updating `CLAUDE.md` to reference the README and remove duplicated front-matter is the most ambiguous acceptance criterion here. "Duplicated front-matter" needs a clearer definition — what specifically in `CLAUDE.md` would be considered duplication once README.md exists? The product overview, stack list, and quick-start commands currently appear in CLAUDE.md. Clarify: should these be removed from CLAUDE.md (pointing to README), kept in both (redundant but fine), or left as-is (CLAUDE.md is for LLMs, README for humans, no conflict)? - No automated tests are needed for a README — this is pure documentation. The test strategy is: manual review checklist + link-validity check. ### Recommendations - Add a PR checklist item: "Tested the quick-start in a clean environment (or a checklist review of each step against the actual repo state)." - Add a PR checklist item: "All links verified — forward links to future docs are explicitly marked TODO with issue numbers." - Clarify in the issue or during implementation: exactly which parts of `CLAUDE.md` should be updated/removed once README.md exists. The current AC is too vague to verify. - The 150-line limit is a good scope guard. Track line count in the PR — it's a fast check that prevents scope creep during writing.
Author
Owner

🎨 Leonie Voss — UX Designer & Accessibility Strategist

Observations

  • This is a Markdown document, not a UI component, so visual design and accessibility standards apply in a limited way. The relevant UX concerns here are: readability, information hierarchy, and first-impression clarity.
  • The spec targets "Tobias" — a CS-bachelor PM — as the primary reader. This is the right proxy persona. The 60-second judgment framing is correct: the first paragraph must do everything.
  • The anti-pattern "Do NOT use emoji or marketing language" is good guidance. However, the issue itself uses checkboxes, bold headers, and numbered lists — all of which are fine and should be mirrored in the README structure. The spec is internally consistent.
  • The five-section structure (product description → subsystem map → quick start → where to go next → license) follows a natural mental model: "What is this? → What are the pieces? → How do I start? → Where do I learn more? → What are my rights?" This is sound information architecture.
  • The quick-start section is the most critical for the user experience. The ≤15 min goal requires that every prerequisite version be stated precisely, every command be copy-pasteable, and every expected output be named ("the app is running at http://localhost:3000 — you should see the login page").
  • GitHub/Gitea READMEs render Markdown. Using a code block for the command sequence (rather than inline code) dramatically improves scannability for a dev reader — the spec implies this but doesn't state it explicitly.

Recommendations

  • Structure the quick-start as a numbered list with each step as a code block. A scan-then-copy reading pattern is the natural mode for this audience.
  • End the quick-start with an explicit "you should now see" confirmation: "Open http://localhost:3000 — you should see the Familienarchiv login screen." This closes the loop for the first-time user and confirms the environment is working.
  • Keep section headings at ## level — not ###. For a short document (≤150 lines), two heading levels are sufficient. Deeper nesting increases cognitive load without adding structure.
  • For the subsystem map, a bullet list with inline code for the directory name and a dash separator reads better than a table. Tables in GitHub Markdown render oddly at narrow widths. The spec already prescribes this format — make sure the implementation follows it.
## 🎨 Leonie Voss — UX Designer & Accessibility Strategist ### Observations - This is a Markdown document, not a UI component, so visual design and accessibility standards apply in a limited way. The relevant UX concerns here are: readability, information hierarchy, and first-impression clarity. - The spec targets "Tobias" — a CS-bachelor PM — as the primary reader. This is the right proxy persona. The 60-second judgment framing is correct: the first paragraph must do everything. - The anti-pattern "Do NOT use emoji or marketing language" is good guidance. However, the issue itself uses checkboxes, bold headers, and numbered lists — all of which are fine and should be mirrored in the README structure. The spec is internally consistent. - The five-section structure (product description → subsystem map → quick start → where to go next → license) follows a natural mental model: "What is this? → What are the pieces? → How do I start? → Where do I learn more? → What are my rights?" This is sound information architecture. - The quick-start section is the most critical for the user experience. The ≤15 min goal requires that every prerequisite version be stated precisely, every command be copy-pasteable, and every expected output be named ("the app is running at `http://localhost:3000` — you should see the login page"). - GitHub/Gitea READMEs render Markdown. Using a code block for the command sequence (rather than inline code) dramatically improves scannability for a dev reader — the spec implies this but doesn't state it explicitly. ### Recommendations - Structure the quick-start as a numbered list with each step as a code block. A scan-then-copy reading pattern is the natural mode for this audience. - End the quick-start with an explicit "you should now see" confirmation: "Open `http://localhost:3000` — you should see the Familienarchiv login screen." This closes the loop for the first-time user and confirms the environment is working. - Keep section headings at `##` level — not `###`. For a short document (≤150 lines), two heading levels are sufficient. Deeper nesting increases cognitive load without adding structure. - For the subsystem map, a bullet list with inline code for the directory name and a dash separator reads better than a table. Tables in GitHub Markdown render oddly at narrow widths. The spec already prescribes this format — make sure the implementation follows it.
Author
Owner

⚙️ Tobias Wendt — DevOps & Platform Engineer

Observations

  • I checked docker-compose.yml. Two things a stranger will hit immediately that the issue doesn't address:
    1. No .env.example exists. Every environment variable (POSTGRES_USER, POSTGRES_PASSWORD, MINIO_ROOT_USER, etc.) is undefined in the compose file — docker-compose up -d on a fresh clone produces an error, not a running stack.
    2. minio/minio:latest — unpinned image tag. Not the README's problem to fix, but the quick-start should not imply a reproducible result when the underlying compose file uses :latest.
  • The quick-start prerequisites list "docker-compose" as a separate tool. Current Docker Desktop and Docker CLI ship docker compose (V2, no hyphen) as a subcommand. The old standalone docker-compose binary is effectively deprecated. Use docker compose in the README (V2 syntax) — it's what new developers will have.
  • The issue specifies the API docs URL as http://localhost:8080/v3/api-docs. This is correct only when the backend runs with --spring.profiles.active=dev (per CLAUDE.md: "only accessible when running with --spring.profiles.active=dev"). The README quick-start should not list this URL as universally reachable — it will mislead someone who starts the backend without the dev profile.
  • The ocr-service/ subsystem is not part of docker-compose.yml at the repo root. A first-time reader following the quick-start will not have OCR running. The README subsystem map should make this clear: OCR is a separately started service, not part of the default dev stack.
  • The infra/ directory is listed in the issue's subsystem map as "CI/CD config (Gitea Actions); future home for IaC." I checked: the directory exists but I can't confirm what's in it from this review. If it has actual Gitea Actions workflow files, link them or describe what CI does. If it's empty/placeholder, say "future home for IaC" as the spec states.

Recommendations

  • Create .env.example at the repo root as part of this issue (or as a fast predecessor task). The README quick-start is the wrong place to inline all required env vars. A .env.example with safe development defaults is the correct pattern — the README points to it: "Copy .env.example to .env before starting."
  • Use docker compose (V2) not docker-compose (V1) in all command examples.
  • Remove the http://localhost:8080/v3/api-docs URL from the default quick-start, or add a qualifier: "API docs (requires dev profile): http://localhost:8080/v3/api-docs."
  • Explicitly note in the quick-start that the OCR service requires a separate start-up procedure (link to ocr-service/ directory at minimum).
## ⚙️ Tobias Wendt — DevOps & Platform Engineer ### Observations - I checked `docker-compose.yml`. Two things a stranger will hit immediately that the issue doesn't address: 1. No `.env.example` exists. Every environment variable (`POSTGRES_USER`, `POSTGRES_PASSWORD`, `MINIO_ROOT_USER`, etc.) is undefined in the compose file — `docker-compose up -d` on a fresh clone produces an error, not a running stack. 2. `minio/minio:latest` — unpinned image tag. Not the README's problem to fix, but the quick-start should not imply a reproducible result when the underlying compose file uses `:latest`. - The quick-start prerequisites list "docker-compose" as a separate tool. Current Docker Desktop and Docker CLI ship `docker compose` (V2, no hyphen) as a subcommand. The old standalone `docker-compose` binary is effectively deprecated. Use `docker compose` in the README (V2 syntax) — it's what new developers will have. - The issue specifies the API docs URL as `http://localhost:8080/v3/api-docs`. This is correct **only when the backend runs with `--spring.profiles.active=dev`** (per CLAUDE.md: "only accessible when running with `--spring.profiles.active=dev`"). The README quick-start should not list this URL as universally reachable — it will mislead someone who starts the backend without the dev profile. - The `ocr-service/` subsystem is not part of `docker-compose.yml` at the repo root. A first-time reader following the quick-start will not have OCR running. The README subsystem map should make this clear: OCR is a separately started service, not part of the default dev stack. - The `infra/` directory is listed in the issue's subsystem map as "CI/CD config (Gitea Actions); future home for IaC." I checked: the directory exists but I can't confirm what's in it from this review. If it has actual Gitea Actions workflow files, link them or describe what CI does. If it's empty/placeholder, say "future home for IaC" as the spec states. ### Recommendations - Create `.env.example` at the repo root as part of this issue (or as a fast predecessor task). The README quick-start is the wrong place to inline all required env vars. A `.env.example` with safe development defaults is the correct pattern — the README points to it: "Copy `.env.example` to `.env` before starting." - Use `docker compose` (V2) not `docker-compose` (V1) in all command examples. - Remove the `http://localhost:8080/v3/api-docs` URL from the default quick-start, or add a qualifier: "API docs (requires dev profile): `http://localhost:8080/v3/api-docs`." - Explicitly note in the quick-start that the OCR service requires a separate start-up procedure (link to `ocr-service/` directory at minimum).
Author
Owner

📋 Elicit — Requirements Engineer

Observations

  • The issue is well-specified for documentation work. It uses an acceptance-criteria checklist, clear section structure, and explicit anti-patterns. The "Tobias-equivalent" persona proxy is a useful stand-in for the primary reader.
  • One hidden assumption in the acceptance criteria: "All forward links resolve to actual files (or are listed as 'TODO once DOC-N lands')" — this implicitly assumes the DOC-N issue numbers are known at implementation time. The issue references DOC-2 through DOC-5 by doc name but does not provide issue numbers. If those issues don't exist yet in the tracker at implementation time, the implementer cannot reference them. Verify that issues #396–#399 (or equivalent) exist before starting.
  • Ambiguity in AC 5: "CLAUDE.md (root) is updated to reference the new README and removes any duplicated front-matter." The word "duplicated" is undefined. CLAUDE.md contains a product overview, stack summary, and quick-start commands that will also appear in README.md. The requirement as written could mean: (a) remove the product description from CLAUDE.md and link to README; (b) remove only verbatim duplicates; or (c) add a single reference line at the top of CLAUDE.md pointing to README without removing anything. These lead to meaningfully different outcomes and different PR review expectations.
  • Scope question: Should the README link to the Gitea issue tracker? The issue says "the Gitea issue tracker URL where issues live" under "Where to go next." The tracker URL appears to be http://heim-nas:3005/marcel/familienarchiv/issues — a LAN address. If the repo is ever shared or mirrored, this link will be unreachable. If this is permanently private infrastructure, it's fine. If there's any chance of public sharing, the link should either be omitted or templated.
  • Missing NFR: The issue says ≤150 lines. There is no defined measurable quality bar for the first-paragraph product description. The acceptance criterion says "a reader can describe the product accurately" — but who reviews this and by what standard? For solo development, a peer review substitute (e.g., "read it aloud and explain it to someone unfamiliar") would make this verifiable.

Recommendations

  • Before implementation: confirm the DOC-N issue numbers for all forward links, or explicitly record "TBD" next to each one in the issue and resolve before the PR is reviewed.
  • Resolve the CLAUDE.md AC ambiguity now. My recommendation: add a single line to the top of CLAUDE.md pointing to README ("For a human-readable project overview, see README.md") without removing any existing content — CLAUDE.md serves a different audience and the duplication is intentional.
  • If the Gitea tracker URL is a LAN address, either use a relative path (./issues won't work for Gitea) or note it explicitly as "internal — accessible only on the home network." Don't present a private LAN URL as a public resource.
  • Add a self-test step to the Definition of Done: read only the first paragraph, then write down in one sentence what the product does, without referencing the rest of the document. If the sentence is accurate, AC 2 is met.
## 📋 Elicit — Requirements Engineer ### Observations - The issue is well-specified for documentation work. It uses an acceptance-criteria checklist, clear section structure, and explicit anti-patterns. The "Tobias-equivalent" persona proxy is a useful stand-in for the primary reader. - **One hidden assumption in the acceptance criteria**: "All forward links resolve to actual files (or are listed as 'TODO once DOC-N lands')" — this implicitly assumes the DOC-N issue numbers are known at implementation time. The issue references DOC-2 through DOC-5 by doc name but does not provide issue numbers. If those issues don't exist yet in the tracker at implementation time, the implementer cannot reference them. Verify that issues #396–#399 (or equivalent) exist before starting. - **Ambiguity in AC 5**: "`CLAUDE.md` (root) is updated to reference the new README and removes any duplicated front-matter." The word "duplicated" is undefined. CLAUDE.md contains a product overview, stack summary, and quick-start commands that will also appear in README.md. The requirement as written could mean: (a) remove the product description from CLAUDE.md and link to README; (b) remove only verbatim duplicates; or (c) add a single reference line at the top of CLAUDE.md pointing to README without removing anything. These lead to meaningfully different outcomes and different PR review expectations. - **Scope question**: Should the README link to the Gitea issue tracker? The issue says "the Gitea issue tracker URL where issues live" under "Where to go next." The tracker URL appears to be `http://heim-nas:3005/marcel/familienarchiv/issues` — a LAN address. If the repo is ever shared or mirrored, this link will be unreachable. If this is permanently private infrastructure, it's fine. If there's any chance of public sharing, the link should either be omitted or templated. - **Missing NFR**: The issue says ≤150 lines. There is no defined measurable quality bar for the first-paragraph product description. The acceptance criterion says "a reader can describe the product accurately" — but who reviews this and by what standard? For solo development, a peer review substitute (e.g., "read it aloud and explain it to someone unfamiliar") would make this verifiable. ### Recommendations - Before implementation: confirm the DOC-N issue numbers for all forward links, or explicitly record "TBD" next to each one in the issue and resolve before the PR is reviewed. - Resolve the CLAUDE.md AC ambiguity now. My recommendation: add a single line to the top of CLAUDE.md pointing to README ("For a human-readable project overview, see `README.md`") without removing any existing content — CLAUDE.md serves a different audience and the duplication is intentional. - If the Gitea tracker URL is a LAN address, either use a relative path (`./issues` won't work for Gitea) or note it explicitly as "internal — accessible only on the home network." Don't present a private LAN URL as a public resource. - Add a self-test step to the Definition of Done: read only the first paragraph, then write down in one sentence what the product does, without referencing the rest of the document. If the sentence is accurate, AC 2 is met.
Author
Owner

🗳️ Decision Queue — Action Required

3 decisions need your input before implementation starts.

Scope

  • Should .env.example be part of this issue or a prerequisite task? — The docker-compose.yml has no defaults for env vars; without a .env, docker compose up -d fails immediately on a fresh clone. Option A: create .env.example as part of this PR (adds scope but makes the quick-start verifiable). Option B: create a fast prerequisite task, block this issue on it, and link to .env.example from the README. Either way, the ≤15 min acceptance criterion cannot be met without it. (Raised by: Felix, Tobias)
  • How should CLAUDE.md be updated when README.md exists? — AC 5 says "remove duplicated front-matter," but CLAUDE.md serves a different audience (LLM) and the duplication is intentional by design. Three options: (a) remove the product/stack sections from CLAUDE.md and redirect to README; (b) add one reference line at the top of CLAUDE.md without removing anything; (c) leave CLAUDE.md unchanged entirely. Option (b) is the lowest-risk change and keeps CLAUDE.md self-contained for the LLM. (Raised by: Sara, Elicit)

  • Should the Gitea issue tracker URL (http://heim-nas:3005/...) appear in the README? — This is a LAN address that will be unreachable from anywhere outside the home network. Options: (a) include it as-is — perfectly fine for a permanently private family project; (b) omit it — README links to docs only, not the tracker; (c) use a placeholder comment noting "internal URL — see your local Gitea instance." If the repo will never be shared publicly, option (a) is fine. If there's any chance of sharing or mirroring, option (b) or (c) is safer. (Raised by: Elicit)

## 🗳️ Decision Queue — Action Required _3 decisions need your input before implementation starts._ ### Scope - **Should `.env.example` be part of this issue or a prerequisite task?** — The `docker-compose.yml` has no defaults for env vars; without a `.env`, `docker compose up -d` fails immediately on a fresh clone. Option A: create `.env.example` as part of this PR (adds scope but makes the quick-start verifiable). Option B: create a fast prerequisite task, block this issue on it, and link to `.env.example` from the README. Either way, the ≤15 min acceptance criterion cannot be met without it. _(Raised by: Felix, Tobias)_ ### Content / Links - **How should `CLAUDE.md` be updated when README.md exists?** — AC 5 says "remove duplicated front-matter," but CLAUDE.md serves a different audience (LLM) and the duplication is intentional by design. Three options: (a) remove the product/stack sections from CLAUDE.md and redirect to README; (b) add one reference line at the top of CLAUDE.md without removing anything; (c) leave CLAUDE.md unchanged entirely. Option (b) is the lowest-risk change and keeps CLAUDE.md self-contained for the LLM. _(Raised by: Sara, Elicit)_ - **Should the Gitea issue tracker URL (`http://heim-nas:3005/...`) appear in the README?** — This is a LAN address that will be unreachable from anywhere outside the home network. Options: (a) include it as-is — perfectly fine for a permanently private family project; (b) omit it — README links to docs only, not the tracker; (c) use a placeholder comment noting "internal URL — see your local Gitea instance." If the repo will never be shared publicly, option (a) is fine. If there's any chance of sharing or mirroring, option (b) or (c) is safer. _(Raised by: Elicit)_
Author
Owner

Decision Queue — Resolved

The 3 decisions raised in #395#issuecomment-6213:

1. .env.examplebundle into this PR (Option A)

Without it, the "≤15 min from clone to running app" AC is unverifiable. Splitting it into a prerequisite task creates merge friction without value. The .env.example file is small, low-risk, and tightly coupled to the README's quickstart section. Add it in the same PR.

Implementation note: keep dev defaults conservative — POSTGRES_PASSWORD=changeme, MINIO_ROOT_USER=minioadmin, etc. — matching what docker-compose.yml already expects but with safer defaults than blanks. Comment each var briefly.

2. CLAUDE.md update → single reference line, no removals (Option b)

Add one line at the top of root CLAUDE.md: > For a human-readable project overview, see [README.md](./README.md). Do not remove any existing content from CLAUDE.md in this PR. The full migration (move rules → human docs, replace with pointer comments) is DOC-7's job per the epic-level Decision Queue D3 — and DOC-7 is hard-blocked by DOC-2/4/5/6 anyway. Pre-migrating now would create churn.

3. Gitea LAN URL → include as-is with one-line qualifier (Option a + small note)

Per the project frame, this is a permanently family-only system. The Gitea instance at http://heim-nas:3005/marcel/familienarchiv/issues will not be exposed publicly. Include it in the README, but qualify: "(internal — only reachable from the home network)." One sentence; prevents confusion if the repo is ever cloned elsewhere.


📌 Additional persona feedback to fold into implementation

These aren't decisions — just commitments worth tracking in the PR:

  • Felix: explicit numbered quickstart with .env.example copy step, docker compose (V2, no hyphen), cd frontend && npm install && npm run dev, end with "open http://localhost:3000 — you should see the login screen."
  • Markus: add a link to docs/adr/ in "Where to go next" (it already exists; doesn't depend on DOC-2). Also link docs/architecture/c4-diagrams.md provisionally until DOC-2 lands. Add one-line license: "Private project — all rights reserved. Not licensed for redistribution."
  • Nora: add a security-warning callout in the quickstart: "⚠️ This setup is for local development only. The default Docker Compose exposes the DB port and uses root MinIO credentials. See docs/DEPLOYMENT.md for production hardening." Format default admin credentials in a code block tagged # local dev only.
  • Tobias: the API docs URL http://localhost:8080/v3/api-docs is dev-profile only. Either omit or qualify: "API docs (requires --spring.profiles.active=dev)." OCR service is not part of the default docker compose up; mention this in the subsystem map.
  • Leonie: quickstart steps as code blocks (one per step), ## heading level only.
  • Sara: PR checklist items — (a) tested quickstart in clean env, (b) all forward links verified or marked TODO once DOC-N lands (#396).

Forward-link target issue numbers: DOC-2 = #396, DOC-3 = #397, DOC-4 = #398, DOC-5 = #399.

Status: Ready for implementation.

## ✅ Decision Queue — Resolved The 3 decisions raised in [#395#issuecomment-6213](http://heim-nas:3005/marcel/familienarchiv/issues/395#issuecomment-6213): ### 1. `.env.example` → **bundle into this PR (Option A)** Without it, the "≤15 min from clone to running app" AC is unverifiable. Splitting it into a prerequisite task creates merge friction without value. The `.env.example` file is small, low-risk, and tightly coupled to the README's quickstart section. Add it in the same PR. **Implementation note:** keep dev defaults conservative — `POSTGRES_PASSWORD=changeme`, `MINIO_ROOT_USER=minioadmin`, etc. — matching what `docker-compose.yml` already expects but with safer defaults than blanks. Comment each var briefly. ### 2. CLAUDE.md update → **single reference line, no removals (Option b)** Add one line at the top of root `CLAUDE.md`: `> For a human-readable project overview, see [README.md](./README.md).` Do not remove any existing content from CLAUDE.md in this PR. The full migration (move rules → human docs, replace with pointer comments) is **DOC-7's** job per the epic-level Decision Queue D3 — and DOC-7 is hard-blocked by DOC-2/4/5/6 anyway. Pre-migrating now would create churn. ### 3. Gitea LAN URL → **include as-is with one-line qualifier (Option a + small note)** Per the project frame, this is a permanently family-only system. The Gitea instance at `http://heim-nas:3005/marcel/familienarchiv/issues` will not be exposed publicly. Include it in the README, but qualify: "_(internal — only reachable from the home network)._" One sentence; prevents confusion if the repo is ever cloned elsewhere. --- ## 📌 Additional persona feedback to fold into implementation These aren't decisions — just commitments worth tracking in the PR: - **Felix:** explicit numbered quickstart with `.env.example` copy step, `docker compose` (V2, no hyphen), `cd frontend && npm install && npm run dev`, end with "open `http://localhost:3000` — you should see the login screen." - **Markus:** add a link to `docs/adr/` in "Where to go next" (it already exists; doesn't depend on DOC-2). Also link `docs/architecture/c4-diagrams.md` provisionally until DOC-2 lands. Add one-line license: "_Private project — all rights reserved. Not licensed for redistribution._" - **Nora:** add a security-warning callout in the quickstart: "_⚠️ This setup is for local development only. The default Docker Compose exposes the DB port and uses root MinIO credentials. See `docs/DEPLOYMENT.md` for production hardening._" Format default admin credentials in a code block tagged `# local dev only`. - **Tobias:** the API docs URL `http://localhost:8080/v3/api-docs` is dev-profile only. Either omit or qualify: "_API docs (requires `--spring.profiles.active=dev`)_." OCR service is **not** part of the default `docker compose up`; mention this in the subsystem map. - **Leonie:** quickstart steps as code blocks (one per step), `##` heading level only. - **Sara:** PR checklist items — (a) tested quickstart in clean env, (b) all forward links verified or marked `TODO once DOC-N lands (#396)`. Forward-link target issue numbers: DOC-2 = #396, DOC-3 = #397, DOC-4 = #398, DOC-5 = #399. **Status:** Ready for implementation.
Author
Owner

Implementation complete — PR #440

README.md is written and PR #440 is open.

Commits

  • a5d20f26README.md (93 lines, 5 sections)
  • f02c59dd — README reference line in root CLAUDE.md

Acceptance criteria status

  • README.md exists at repo root with the 5 sections
  • Product description: 2 sentences — accurate for a CS-bachelor PM reading cold
  • Quick start: .env.example copy → docker compose up -d db minio mailpit./mvnw spring-boot:runnpm run devhttp://localhost:5173
  • Security callout in quick-start for dev-only credentials and exposed DB port
  • Credentials in code block labeled # local dev only
  • All forward links verified — non-existent targets marked with _(coming: [DOC-N, #NNN])_
  • CLAUDE.md updated with a single reference line (no removals — DOC-7 owns migration)
  • docs/GLOSSARY.md linked (lands with DOC-3 PR #439)
  • docs/adr/ linked (exists now, 6 ADRs)
  • Gitea tracker URL included with LAN qualifier

One correction vs issue body

The issue specified http://localhost:3000. The actual Vite port is 5173 (confirmed in vite.config.ts, port: 5173). README and .env.example both use 5173 — no change needed there.

## Implementation complete — PR #440 `README.md` is written and PR #440 is open. ### Commits - `a5d20f26` — `README.md` (93 lines, 5 sections) - `f02c59dd` — README reference line in root `CLAUDE.md` ### Acceptance criteria status - [x] `README.md` exists at repo root with the 5 sections - [x] Product description: 2 sentences — accurate for a CS-bachelor PM reading cold - [x] Quick start: `.env.example` copy → `docker compose up -d db minio mailpit` → `./mvnw spring-boot:run` → `npm run dev` → `http://localhost:5173` - [x] Security callout in quick-start for dev-only credentials and exposed DB port - [x] Credentials in code block labeled `# local dev only` - [x] All forward links verified — non-existent targets marked with `_(coming: [DOC-N, #NNN])_` - [x] `CLAUDE.md` updated with a single reference line (no removals — DOC-7 owns migration) - [x] `docs/GLOSSARY.md` linked (lands with DOC-3 PR #439) - [x] `docs/adr/` linked (exists now, 6 ADRs) - [x] Gitea tracker URL included with LAN qualifier ### One correction vs issue body The issue specified `http://localhost:3000`. The actual Vite port is `5173` (confirmed in `vite.config.ts`, `port: 5173`). README and `.env.example` both use 5173 — no change needed there.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marcel/familienarchiv#395