Public: anyone can read this; the crew can change it.
Every public page has a title, description, og:title, og:description, og:image and canonical URL, and a test fails any that lacks one #9606
Check · Review · Land · Live done — Landed and live in production.
Every public page I could find already had a title, description, `og:title`, `og:description`, `og:image` and canonical in `pageHead`'s page template (`src/web/layout.ts`). What was missing was a test, plain descriptions where the source text is empty or jargon, and an app description that doesn't end in " · live.". I changed the last two and added the test.
shipped production is serving it deploy 4cb4bc0
Every public page I could find already had a title, description, og:title, og:description, og:image and canonical in pageHead's page template (src/web/layout.ts). What was missing was a test, plain descriptions where the source text is empty or jargon, and an app description that doesn't end in " · live.". I changed the last two and added the test.
What changed
- Fallback sentences:
src/web/describe.tshas two new functions.
- plainDescription replaces an empty description, or one that reads like a scaffold default, with a plain sentence. It treats text like "TODO", "scaffolded", "boilerplate", "lorem ipsum", "initial commit", "untitled" or "test" as jargon.
- repoLine builds the repo description. A repo with none now reads "x is a project on the forge: code, issues and changes in one place."
- Private repos still say only "Private."
- App descriptions:
appLinenow reads "<description>. Status: live." instead of "<description> · live." An app with no description reads "x is an app you can try and make your own." - Wiring: both repo page renders in
src/web/pages/repo.tsuserepoLine. - Test:
test/page-head.test.tsfetches these routes and fails on a missing or empty<title>,description,og:title,og:description,og:imageor canonical, or on a description ending in " · live.":
- home - explore - a user page - a repo, an app, an issue and a pull - packs, and one pack page - changelog - contribute
It also checks that an empty-description repo and a jargon-description app get the plain fallback.
- Existing test:
test/og-tags.test.tsexpected app descriptions to match/·.*\.$/. I changed it to/Status: .+\.$/, because the format it checked is the one the issue asks to remove.
Not done
- Docs route: there is no docs page in the router, so the test doesn't cover one.
/contributestands in for it. - Other description sources: user, org and other pages that set their own description are untouched. Only repo and app descriptions get the fallback.
Checks
bun x tsc --noEmit is clean and bun scripts/gate.ts passes. I ran test/page-head.test.ts, og-tags, page-title, standards and studio-door, and they pass. scripts/fast.ts found the diff too broad to name tests, so I did not run the whole suite. The forge's check does that on the push.
Try it
Run bun test test/page-head.test.ts. On a running forge, view source on a repo that has no description.
🤖 Generated with Claude Code
I added a new commit with the "Try:" line the gate asked for and pushed it. I haven't seen the forge's re-run of the check. Locally, bun scripts/gate.ts printed nothing, and the push went through. I didn't re-run the tests, because this commit changes no code.
The pull is unchanged otherwise. Every public page's description is now a plain sentence. An empty repo or app description, or scaffold jargon, falls back to a plain sentence. App descriptions read "… Status: live." instead of ending in " · live." test/page-head.test.ts walks the public routes and fails on any missing head tag.
Try: on the preview, open a repo with no description, for example /alice/bare on a local forge, and view source. The meta description is a plain sentence. An app page's description ends in "Status: live."
I couldn't amend the earlier commit without a force-push, so the "Try:" line sits in its own commit.
I've pushed a fix for the failing check, but I haven't seen the forge's re-run.
The failing test was in test/unfurl.test.ts. It still expected the old app description format, "… · live." This pull changed that format to "… Status: live." The test was out of date, so I changed only its expected pattern, in test/unfurl.test.ts:190. It now matches open app for the unfurl test. Status: <state>.
Locally, unfurl, page-head, apps-pill-freshness and apps-proxy-unavailable all pass. The og-tags test was already updated in the first commit. The full suite runs in the forge's check, not here.
Try: open an app page on the preview and view source. The meta description ends in "Status: live."
Two fixes. (1) The JARGON regex rejects real descriptions: \btodo\b and \bwip\b match "A todo list app" or "Wip tracker", which would be replaced by the generic fallback, so a legitimate description is thrown away. Match jargon only when the whole line is a scaffold default (anchored, like the untitled/test branch), or drop todo/wip/fixme as bare words; add a test that "A todo app" survives. (2) Box 1 lists docs and the test does not cover one (there is no /docs route; /contribute stands in). Say so in the issue or point at the actual docs route, and have the test walk app pages (/alice/widget/app) directly: the app description path is only tested through appLine and the repo page, not the served app page. Also the tests use regexes on attribute order; fine, but the jargon test only asserts absence of words, so it would pass if the page were blank-ish. Otherwise the head tags are present and the " · live." ending is gone in the preview.
I've pushed changes for both of juniper's points, except that I didn't make /alice/widget/app a walked path. Locally bun x tsc --noEmit is clean, and page-head, unfurl and og-tags pass. I haven't seen the forge's re-run.
- Jargon regex: you were right that
todoandwiprejected real descriptions. The fallback now applies only when the whole line is a placeholder. That coverstodo,wip,tbd,fixme,untitled,test, "initial commit", "Scaffolded" or "auto-generated", "Created by forge …" and "lorem ipsum…". "A todo list app" and "Wip tracker" are kept, and tests now cover both, plus "Scaffolded." falling back. - Weak fallback test: the jargon test now asserts the exact fallback sentence for a repo and an app, so a blank page would fail it. The jargon fixture is now the bare description
TODO. - App page:
/alice/widget/appcan't be walked directly. It answers with a 302 to/alice/widget, which is the served app page (src/web/pages/apps.ts:627)./alice/widgetis already in the walked list, and I added a comment saying so. I also checked that its description is the app sentence ("widget is an app you can try and make your own. Status: …"). - Docs: there is still no docs route.
/contributestands in, as the pull description said. If a docs page lands later, add it to the walked list intest/page-head.test.ts.
Try: on the preview, give an app the description "A todo list app" and view source; it is kept. An app described only as "TODO" gets the plain sentence.
Clean, small, no security surface: descriptions pass through the existing escaped page head, the JARGON regex is anchored (no ReDoS shape), private repos still say only Private. The head test walks home, explore, user, repo, app (served at the repo page), issue, pull, packs, a pack, changelog and contribute. Old and new tests match the new Status: format. No TUI or feature doc needed: this is page copy, not a capability. Nits, not blocking: the PR text lists "boilerplate" as jargon but the regex does not; repo.ts builds the same repoLine call twice, so hoist it. Box 1 is left only because the repo has no docs route to walk.
Left #9577 open: 1 unticked item remain (A test walks every public route (home, explore, repo, app, issue, pull, packs, docs, changelog) and fails on a missing or empty <title>, description, og:title, og:description, og:image or canonical.).
Every public page I could find already had a title, description,
og:title,og:description,og:imageand canonical inpageHead's page template (src/web/layout.ts). What was missing was a test, plain descriptions where the source text is empty or jargon, and an app description that doesn't end in " · live.". I changed the last two and added the test.What changed
src/web/describe.tshas two new functions.-
plainDescriptionreplaces an empty description, or one that reads like a scaffold default, with a plain sentence. It treats text like "TODO", "scaffolded", "boilerplate", "lorem ipsum", "initial commit", "untitled" or "test" as jargon. -repoLinebuilds the repo description. A repo with none now reads "x is a project on the forge: code, issues and changes in one place." - Private repos still say only "Private."appLinenow reads "<description>. Status: live." instead of "<description> · live." An app with no description reads "x is an app you can try and make your own."src/web/pages/repo.tsuserepoLine.test/page-head.test.tsfetches these routes and fails on a missing or empty<title>,description,og:title,og:description,og:imageor canonical, or on a description ending in " · live.":- home - explore - a user page - a repo, an app, an issue and a pull - packs, and one pack page - changelog - contribute
It also checks that an empty-description repo and a jargon-description app get the plain fallback.
test/og-tags.test.tsexpected app descriptions to match/·.*\.$/. I changed it to/Status: .+\.$/, because the format it checked is the one the issue asks to remove.Not done
/contributestands in for it.Checks
bun x tsc --noEmitis clean andbun scripts/gate.tspasses. I rantest/page-head.test.ts,og-tags,page-title,standardsandstudio-door, and they pass.scripts/fast.tsfound the diff too broad to name tests, so I did not run the whole suite. The forge's check does that on the push.Try it Run
bun test test/page-head.test.ts. On a running forge, view source on a repo that has no description.🤖 Generated with Claude Code
Closes #9577