|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +Guidance for working on this repo (an mdBook site deployed to help.loomio.com via GitHub Pages). |
| 4 | + |
| 5 | +## Commit hygiene |
| 6 | + |
| 7 | +- No self-promotion or marketing in commits: don't add "Co-Authored-By" |
| 8 | + lines or similar credit/attribution for AI tooling to commit messages. |
| 9 | +- If documenting AI-agent guidance in a file, use the standard filename |
| 10 | + `AGENTS.md` (this file) rather than tool-specific names like `CLAUDE.md`. |
| 11 | + |
| 12 | +## Deploy structure — the "/en nesting" footgun |
| 13 | + |
| 14 | +`.github/workflows/gh-pages.yml` builds the book and assembles the deployed |
| 15 | +site like this: |
| 16 | + |
| 17 | +``` |
| 18 | +mdbook build en # -> en/book/* (real content, e.g. en/book/user_manual/foo/index.html) |
| 19 | +cp -R static/* ./public/ # -> public/* (top-level static files, e.g. favicon, robots.txt) |
| 20 | +mv ./en/book/* ./public/en/ # -> public/en/* (nests ALL book content one level under /en) |
| 21 | +``` |
| 22 | + |
| 23 | +So on disk, book content lives at `en/book/user_manual/...` (no `en/` |
| 24 | +segment), but on the live site it's served at `/en/user_manual/...`. Two |
| 25 | +consequences that have caused real bugs: |
| 26 | + |
| 27 | +1. **Redirect `from` keys in `en/book.toml` must NOT start with `/en/`.** |
| 28 | + mdBook writes a redirect stub file literally at `book_dir/<from>`. If |
| 29 | + `from` already starts with `/en/`, deploy nests it *again*, producing |
| 30 | + `/en/en/...` — a path nothing ever requests, so the redirect silently |
| 31 | + 404s. Correct form: `"/user_manual/groups/foo/index.html" = "/en/user_manual/bar/index.html"` |
| 32 | + — no `/en` on the left (from), full `/en/...` path on the right (to, |
| 33 | + since that's the real browser-facing URL used in the meta-refresh/canonical tag). |
| 34 | +2. **Internal markdown links must include the `/en/` prefix**, e.g. |
| 35 | + `/en/user_manual/groups/settings/`, not `/user_manual/groups/settings/`. |
| 36 | + A link missing `/en/` can *look* fine when checked against the local |
| 37 | + `en/book/` directory (the relative path happens to exist there), but on |
| 38 | + the live site paths without `/en/` only resolve against top-level |
| 39 | + `static/*` content — so it 404s in production despite passing a naive |
| 40 | + local check. This exact bug shipped and was only caught by crawling the |
| 41 | + live site (see below). |
| 42 | + |
| 43 | +Any time you touch `book.toml` redirects or add/edit internal links, keep |
| 44 | +this nesting model in mind — it's the single most common source of "works |
| 45 | +locally, 404s live" bugs in this repo. |
| 46 | + |
| 47 | +## Link style convention |
| 48 | + |
| 49 | +Internal links to pages use a **trailing slash** (`/en/user_manual/groups/settings/`), |
| 50 | +not `/index.html` (`/en/user_manual/groups/settings/index.html`) and not a |
| 51 | +bare path with neither (`/en/user_manual/groups/settings`). All three |
| 52 | +technically resolve on GitHub Pages, but the bare form costs an extra |
| 53 | +301 round-trip (GH Pages redirects `/foo` → `/foo/` before serving |
| 54 | +`index.html`), and it's also the shape that's easiest to typo into a |
| 55 | +missing-`/en/`-prefix bug. Prefer trailing slash when writing or editing |
| 56 | +links in `en/src/**/*.md`. |
| 57 | + |
| 58 | +## Checking scripts |
| 59 | + |
| 60 | +Two scripts validate the built book before deploy, and are wired into |
| 61 | +`.github/workflows/gh-pages.yml` right after `mdbook build en`: |
| 62 | + |
| 63 | +- `check-redirects.sh` — for every `[output.html.redirect]` entry in |
| 64 | + `en/book.toml`, verifies the target page actually exists in the built |
| 65 | + book, and flags any `from` key that starts with `/en/` (the double-nest |
| 66 | + bug above). |
| 67 | +- `check-links.sh` — walks every built HTML page, extracts every `<a href>` |
| 68 | + and `<img src>`, and verifies the target resolves — correctly modeling |
| 69 | + the `/en` nesting split between `en/book/` and `static/`, and accepting |
| 70 | + GitHub Pages' directory-index resolution (`/foo/` or `/foo/index.html` |
| 71 | + both count as valid, matching real server behavior). |
| 72 | + |
| 73 | +Run both locally after `mdbook build en` before pushing changes that touch |
| 74 | +redirects or links: |
| 75 | + |
| 76 | +``` |
| 77 | +mdbook build en |
| 78 | +./check-redirects.sh |
| 79 | +./check-links.sh |
| 80 | +``` |
| 81 | + |
| 82 | +Neither script catches everything, though — they only validate against the |
| 83 | +locally built tree. The redirect-nesting bug above shipped once already |
| 84 | +despite `check-redirects.sh` passing, because the script checked "does the |
| 85 | +target file exist" but not "does the `from` path actually reach that file |
| 86 | +once deployed." If you suspect something is broken only in production, |
| 87 | +crawl the live site directly: |
| 88 | + |
| 89 | +```bash |
| 90 | +curl -s https://help.loomio.com/sitemap.xml | grep -oE '<loc>[^<]+</loc>' | sed -E 's/<\/?loc>//g' |
| 91 | +# then fetch each page, extract internal <a>/<img> targets, HEAD each one |
| 92 | +``` |
| 93 | + |
| 94 | +This is slow (real HTTP round-trips) but is ground truth — it's what |
| 95 | +actually caught both the redirect-nesting bug and three markdown links |
| 96 | +that were missing their `/en/` prefix. |
| 97 | + |
| 98 | +## mdBook behavior notes |
| 99 | + |
| 100 | +- mdBook auto-rewrites `.md` links (even absolute ones like |
| 101 | + `/en/user_manual/foo/bar.md`) to `.html` at build time — this is normal |
| 102 | + and expected, don't "fix" these. |
| 103 | +- `SUMMARY.md` is the source of truth for what actually gets built into a |
| 104 | + page. A `.md` file can exist under `en/src/` with real content and still |
| 105 | + never be built into HTML if it isn't referenced from `SUMMARY.md` — this |
| 106 | + caused an orphaned page (`engaging_with_discussions`) whose old redirect |
| 107 | + target silently never existed. |
0 commit comments