Repository navigation
Docs site: reduce maintenance (single source for code, non-blocking translations, simpler CI) #456
Description
Summary
Make the docs site cheaper to maintain: one source for every fact, no build steps that block unrelated doc fixes, and fewer pages to keep in sync. Work is split into 5 phases that can land as separate PRs, in this order. Each phase has a checklist and a "Done when".
Progress — 2026-09-30
Merged #457 as 508a246.
- Phase 4 complete: removed HTTP/2 server push, JSONP, and load balancing recipes and their unused assets/dependencies; added replacement redirects across current locales, stable/next channels, and legacy Docusaurus URLs.
- Phase 3 source conversion complete: all 85 maintained cookbook pages and the ten Request Logger/Static middleware pages across five locales render Go/HTML from repository files. The include plugin supports regions, Markdown/MDX, source-aware caching, and actionable validation errors. JWT/SSE documentation drift and generated-file copies are removed; cookbook ownership checks run in CI.
- Phase 3 remains open: Prometheus package alignment, targeted recipe tests, and removal of the remaining
cookbook/http2/sample certificate/key. The server-push certificate/key were removed with that recipe. The combined compile/test checkbox remains open because the requested recipe tests have not been added. - Phases 1 and 5 remain open. Translation checks and
/next/remain in place after ci: consolidate checks and derive docs sources from Go modules #458.
Validation before merge: 22 Node tests; 18 Go tests across 30 packages; go vet ./...; stable/next production builds; 767 routes and 56,576 internal links/assets; exact checks of 440 rendered source snippets and 175 redirect destinations. Local browser QA covered desktop/mobile layouts, light/dark themes, examples across all five locales, search, copy controls, navigation, channel switching, and sampled redirects. No merge-blocking regression found.
Phase 2 complete: merged #458 as 0e7e4df. CI is consolidated; Go minimum/preferred toolchain and stable/external source versions come from the module files; both Go modules share Dependabot version/security update groups; publishing refreshes weekly; API diffs appear in the Actions summary. New routes pass with a warning to record them for future removal protection. The origin budget covers declared resources (including preloads, icons, images and embeds) while excluding navigation links/preconnects; byte-size budgets are unchanged. All six review findings were fixed and replied to. Validation: all 36 Node tests, Go vet/race checks, stable/next builds, 767 routes and 56,576 internal links/assets, workflow linting, and local browser checks passed. Final pre-merge CI passed.
Phase 3 follow-up merged: #461 merged as 9d234d5. The homepage Hello World now comes from its runnable source, and Casbin middleware/enforcer/JWT excerpts and model/policy files come from the recipe across all five locales. Both review findings were fixed: the hidden hero code is excluded from keyboard focus, and Casbin pages define the enforcer and list the JWT dependencies. All 37 Node tests, Go vet/race checks, stable/next builds, link/accessibility/performance checks, and local desktop/mobile/light/dark browser checks passed. Final head CI passed. The two corresponding Phase 3 checkboxes are complete; Phase 3 remains open for Prometheus alignment, targeted recipe tests, and the HTTP/2 sample certificate/key.
Why
- Pasted code: complete cookbook programs are pasted into every locale page: 120 blocks, about 6,100 lines. Some copies have already drifted (
cookbook/jwt.md,cookbook/sse.md). The CRUD page (cookbook(crud): handle missing users and invalid ids consistently #455) already imports its code instead. - Blocking translation checks:
translation-status.mjsandsecurity-translation-status.mjsfail the build, so an English edit can block deployment until 4 translations are updated. /next/channel: it doubles the build and the baselines, is currently one commit ahead of stable, and publishes about 305 duplicate pages withoutnoindex.- CI overlap and pins: two workflows build the site on every PR, and Go versions differ (1.25 vs 1.27). Echo is pinned in several places, and Dependabot doesn't cover Go modules.
Phase 1: Unblock deployment (~1 day)
Goal: an English doc fix can always ship.
- Make translation checks report-only:
-
site/scripts/translation-status.mjs: dropprocess.exitCode = 1and write the report to$GITHUB_STEP_SUMMARYwhen set. -
site/scripts/security-translation-status.mjs: replace thethrowwith a report, like the line above. -
site/scripts/build-site.mjs: keep running both, but never fail on them.
-
- Show readers when a translation may be stale: extend
site/src/components/VersionBanner.astroto show "This translation may be outdated. Read the English version" on pages the report flags. - Stop publishing
/next/:-
site/scripts/build-site.mjs: build only the stable channel, and removerewriteNextLinks. - Delete
site/next-source.jsonandsite/next-reference-baseline.json, and remove the next rules fromcheck-site.mjsandcheck-performance.mjs. - Redirect
/next/*to the stable URL, so existing links keep working.
-
- Add
.github/workflows/echo-master.yml, a weekly, non-required check against Echo master:-
go get github.com/labstack/echo/v5@master, thengo vet ./...andgo test ./...for the cookbook andreference/. - Run the config-field extractor and print the API diff against
site/reference-baseline.jsonin the job summary. - Open or update an issue when it fails.
-
Done when: a PR that changes only English text builds and deploys with stale translations, /next/ redirects to stable, and the weekly job runs green on Echo master.
Phase 2: One CI workflow and one Echo pin (~1 day)
Goal: a single version bump is a single PR.
- Merge
docs.yml,test.yamlandtest-deploy.yamlinto one PR workflow:go vet+go test -race ./..., then the site build and checks. Keepdeploy.yamlfor publishing. - Use
go-version-file: go.modin every workflow instead of hard-coded1.25/1.27, and drop the hard-coded Go version in thego.workwritten byprepare-echo-source.mjs. - Derive the Echo source from
go.mod: inprepare-echo-source.mjs, resolve Echo withgo mod download -json github.com/labstack/echo/v5(as external modules already are) instead of cloning a SHA. Deletesite/echo-source.json. - Derive the external module versions (
site/external-sources.json) fromgo.modtoo, or check that they match. - Add
gomodto.github/dependabot.ymlfor/and/reference, grouped into one PR. - Route baseline (
check-site.mjs): fail only on removed routes; new pages shouldn't need an accept step. - Performance check: count only scripts and stylesheets as external origins, not plain
<a href>links. -
deploy.yaml: change the daily cron (it only refreshes the star count) to weekly.
Done when: a Dependabot Go PR updates Echo in one place, and CI builds, checks and shows any API diff in one workflow.
Phase 3: Code comes from source files (~2 days)
Goal: no page contains a pasted copy of a program from the repo.
- Add a small remark plugin in
site/that reads a fenced block like```go file=cookbook/jwt/custom-claims/server.go(path from the repo root) and fills in the file's content. Support optional regions (#name, between// docs:start nameand// docs:end name) for step-by-step excerpts. Pages stay.md, with no per-locale import paths. - Convert
cookbook/crud.mdx(all locales) to the fence syntax, and remove thecopyFileSyncspecial case fromprepare-echo-source.mjs. - Replace every pasted cookbook program with a
file=fence in all locales. Script it: replace a block only when it exactly matches the source file, and review the rest by hand. - Fix the known drift while converting:
-
cookbook/jwt.mdvscookbook/jwt/custom-claims/server.go -
cookbook/sse.mdvscookbook/sse/broadcast/server.go -
middleware/prometheus.mdxandsite/external-sources.jsonuseecho-prometheus, butcookbook/prometheus/server.gousesecho-contrib/v5/echoprometheus. Pick one. -
middleware/casbin-auth.mdpastes the same middleware twice. - Render the homepage Hello World (
site/src/components/HomeHero.astro) fromcookbook/hello-world/server.go.
-
- Add a CI rule: fail if a page under
cookbook/has a bare```goblock of more than ~15 lines withoutfile=. - Every recipe compiles (
go vet ./...). Addserver_test.goonly where there is real logic (crud already has one; also jwt, cors, file-upload, timeout), using thenewServer()pattern from crud. - Delete the committed sample certificates and keys in
cookbook/http2/andcookbook/http2-server-push/(expired 2017). Generate them at run time or documentmkcert.
Done when: CI fails on a pasted program, every code block on a cookbook page comes from a compiled file, and the drift items are fixed.
Phase 4: Prune the cookbook (~½ day)
Goal: less to maintain, and no broken links.
- Remove or merge the recipes with low value and high upkeep:
-
http2-server-push: browsers removed HTTP/2 push. -
jsonp: the page itself recommends JSON with CORS. -
load-balancing: Armor/nginx configs. Also fix the page's HTTPS instructions, which don't match its plain-HTTP example.
-
- Add an explicit redirect for every removed URL in all locales (
site/src/redirects.mjscurrently derives redirects from existing files, so removals silently drop them). - Remove unused assets and Go dependencies that belonged to removed recipes (
go mod tidy).
Done when: removed pages redirect, and the link check and go vet ./... pass.
Phase 5: Translate less (~1½ days)
Goal: translation work matches what readers use.
- Decide which locales and pages stay translated, using site analytics. Suggested start is the learning path (about 11–25 pages): installation, quickstart, routing, context, request, response, binding, error handling, the middleware index, hello-world, crud.
- Don't translate security pages: a stale translated security warning is worse than English. Remove the localized copies and let Starlight fall back to English.
- Delete the other translation files, relying on Starlight's English fallback.
- Make the scripts fallback-aware:
check-source.mjsandcheck-site.mjscurrently require every page in every locale. - Keep one list of locales (it's hard-coded in about 11 files), and move component labels (for example
ConfigReference.astro) to Starlight's i18n strings withAstro.currentLocale. - Keep one staleness check covering all translated pages: merge
translation-sections.mjs,translation-status.mjsandsecurity-translation-status.mjs, with code blocks excluded from the hashes.
Done when: every page that isn't translated renders in English under each locale URL, the checks pass, and the staleness report covers all translated pages.
Out of scope
- Moving docs into
labstack/echo: echox stays a separate repo. - A separate v4 site: instead, add one "Migrating from v4" page, link pkg.go.dev for v4 APIs, and note v4 LTS support until 2026-12-31.
- Generating all API docs: the config-field extractor stays narrow, and pkg.go.dev covers the rest.
Notes
- The phases are independent PRs. 1 and 2 remove most of the recurring cost, 3 is the largest.
- Keep existing link, anchor, accessibility and asset-size checks unless a phase changes them on purpose.
Activity