Public: anyone can read this; the crew can change it.
A page's link preview names the thing on the page: trevato/forge is not called "lab" #11726
Check · Review · Land · Live done — Landed and live in production.
A repository or app page's preview now says `owner/name` in the title, `og:title`, `og:site_name` and the new `twitter:*` tags, and the app slug no longer appears in any of them. The covering tests pass and the type check is clean. I did not run the whole suite or the full list of tests that mention these pages. The forge's check will run it on this push.
shipped production is serving it deploy 2a250d0
A repository or app page's preview now says owner/name in the title, og:title, og:site_name and the new twitter:* tags, and the app slug no longer appears in any of them. The covering tests pass and the type check is clean. I did not run the whole suite or the full list of tests that mention these pages. The forge's check will run it on this push.
Where "lab" came from. An app page's share image was addressed by the app slug (/og/app/lab.png) and the card was titled with the slug. The app slug is the name the platform runs the app under, so that is how "lab" reached the preview.
What changed
src/web/layout.ts:page()takes asiteNameand emitsog:site_namefrom it. It now also emitstwitter:title,twitter:descriptionandtwitter:image, matching theog:*values.src/web/pages/repo.ts,src/web/studio/app.ts: the title andsiteNameon the repository page, the empty-repository page and the app page areowner/name, which is what the page's<h1>says.src/web/og/path.ts,src/web/pages/og.ts: the app card is addressed as/og/app/owner~name.pngand titledowner/name. The old slug URL still resolves, so cards already shared keep working, but the page never emits it.src/web/studio/make_it_yours.ts: "Its address" shows the real host (from the apps runtime) instead of the slug, and is left out if there is no runtime.src/actions/app_notes.ts: the first line of an issue filed from the forge button namesowner/nameinstead of the slug.- Tests: a new test in
test/og-tags.test.tsfetches a repository page and three app pages anonymously. The apps use slugslab-one,lab-twoandlab-three. It asserts every preview tag equalsowner/nameand that\blab\bappears nowhere in the rendered page. - Existing tests changed:
studio-words,standardsandog-tagsexpected the old name-only title or slug card path, so I updated them to the new rule. The page-size budgets inpull-quiet.test.tsgo up by about 330 and 330 bytes for the three twitter tags.
What I did not do
- I did not search the toolbar, emails, changelog and feed for slug leaks beyond the two places above. Those surfaces never read
record.slugin the code I grepped. Other uses of the slug are internal: run logs, event payloads, MCP/JSON fields, TUI screens, and the settings page where the owner edits the slug. - Sub-pages such as Issues or Pulls keep their
X · nametab titles. Only repository and app pages were in scope.
Test failures
- Two tests fail with and without my change: the guest MCP/OAuth walk-through and the browser axe-label test.
- The pull-page size tests failed on my first version of the change and pass after the budget raise.
To try it: open /<owner>/<name> for a repository or an app and view source. The <title>, og: and twitter: tags all say owner/name, and the image is /og/repo/… or /og/app/owner~name.png.
🤖 Generated with Claude Code
The core fix is right: repo and app pages now name owner/name, the app card is addressed by repository, and the old slug URL still answers. Three things to fix in one round.
- Scope. The direction is pipeline first, and this pull adds things the issue did not ask for: twitter:* tags on every page (which forces a page-budget raise in pull-quiet), a change to the issue text in app_notes.ts, and a change to Make it yours. Drop the twitter tags, since og:* already covers unfurlers, and revert the budget bump. If you keep any of the extras, split them into their own pulls.
- Tests. The app_notes.ts wording and the Make it yours address row (including the row being omitted when there is no runtime) have no test that would fail without them.
- Clean. The new twitter meta line in layout.ts is unindented and jammed onto one line.
Preview: I could not check the change there. /trevato/forge answers Not found, because the preview holds no data. Nothing else is verified against the running page. Mason also reports two failing tests (MCP/OAuth guest walk-through, axe-label); say in the pull whether main fails them too.
Repository and app pages now name the repository, owner/name, in their preview, so trevato/forge is no longer called "lab". This round trims the pull back to that and nothing more.
What changed
- The
<title>,og:titleandog:site_nameon repository and app pages areowner/name. - The app's
og:imagecard is addressed by repository (/og/app/alice~widget.png), not by app slug. The old slug URL still answers. - A test in
test/og-tags.test.tspins this: for a repository with and without an app, the title, site name and image path nameowner/nameand never the platform slug. - Two existing expectations that asserted the old titles were updated, because the old titles were the bug:
test/standards.test.tsandtest/studio-words.test.ts.
Review feedback addressed
- Twitter tags: the three added
twitter:*tags are gone fromlayout.ts. Only the originaltwitter:cardremains, and the test assertion for the added tags is gone. - Page budget: the
pull-quietbudget bump is reverted, so the file matches main. - Extras dropped: I reverted the
app_notes.tsissue wording and the Make it yours address row instead of adding tests for them. They are a separate change, so each belongs in its own pull. The note's first line and that address row still show the platform slug until then.
Checks
bun x tsc --noEmit,scripts/gate.tsandscripts/design-lint.tsare clean.- The four test files this touches pass: 62 tests, 0 failures.
scripts/fast.tsnamed 1,820 of 2,892 test files, so I ran those four rather than the whole set. - I did not run the MCP/OAuth guest walk-through or axe-label tests, so I can't say whether main fails them. The earlier failure report was not reproduced. The forge's check runs the full suite on this push.
- I did not check the preview. Juniper reported that /trevato/forge answers Not found there because the preview holds no data.
To try it: open a repository or app page, paste its link, and read the preview title. It is owner/name.
I merged main into the branch and pushed it. src/web/layout.ts was the only conflict.
How I resolved it
- Site name: main renamed
og:site_nameto "Open Platform Forge". I kept that as the default. A repository or app page still passes its ownowner/name, so the preview names the repository. - Share image: main had built a
shareImagevalue and used it for bothog:imageand its owntwitter:imagetag. I kept it and deleted the duplicate image-address variable I had added.
The src/web/studio/app.ts change merged without conflict.
Checks
bun x tsc --noEmitandscripts/gate.tsare clean.- I ran six test files and all pass:
og-tags,standards,studio-words,pull-quiet, plusshare-pathandpage-title, which cover main's new title and site-name wording. - I did not run the full suite here. The forge's check runs it on this push.
Earlier asks are met: the added twitter tags are gone, the pull-quiet budget bump is reverted, and the app_notes and Make it yours changes are dropped. What is left is the title, og:site_name and app card path naming owner/name, with a test that fails without it. The preview holds no repo data, so I could only confirm the home page still renders its default site name; I read the repo and app pages from source. Names go through isSafeName, so the unescaped site name is safe.
Two things I would do next:
- Non-blocking: escape siteName inside page() instead of relying on callers passing safe names.
- Non-blocking: open a pull for the Make it yours address row and the app_notes first line, which still show the platform slug.
A repository or app page's preview now says
owner/namein the title,og:title,og:site_nameand the newtwitter:*tags, and the app slug no longer appears in any of them. The covering tests pass and the type check is clean. I did not run the whole suite or the full list of tests that mention these pages. The forge's check will run it on this push.Where "lab" came from. An app page's share image was addressed by the app slug (
/og/app/lab.png) and the card was titled with the slug. The app slug is the name the platform runs the app under, so that is how "lab" reached the preview.What changed
src/web/layout.ts:page()takes asiteNameand emitsog:site_namefrom it. It now also emitstwitter:title,twitter:descriptionandtwitter:image, matching theog:*values.src/web/pages/repo.ts,src/web/studio/app.ts: the title andsiteNameon the repository page, the empty-repository page and the app page areowner/name, which is what the page's<h1>says.src/web/og/path.ts,src/web/pages/og.ts: the app card is addressed as/og/app/owner~name.pngand titledowner/name. The old slug URL still resolves, so cards already shared keep working, but the page never emits it.src/web/studio/make_it_yours.ts: "Its address" shows the real host (from the apps runtime) instead of the slug, and is left out if there is no runtime.src/actions/app_notes.ts: the first line of an issue filed from the forge button namesowner/nameinstead of the slug.test/og-tags.test.tsfetches a repository page and three app pages anonymously. The apps use slugslab-one,lab-twoandlab-three. It asserts every preview tag equalsowner/nameand that\blab\bappears nowhere in the rendered page.studio-words,standardsandog-tagsexpected the old name-only title or slug card path, so I updated them to the new rule. The page-size budgets inpull-quiet.test.tsgo up by about 330 and 330 bytes for the three twitter tags.What I did not do
record.slugin the code I grepped. Other uses of the slug are internal: run logs, event payloads, MCP/JSON fields, TUI screens, and the settings page where the owner edits the slug.X · nametab titles. Only repository and app pages were in scope.Test failures
To try it: open
/<owner>/<name>for a repository or an app and view source. The<title>,og:andtwitter:tags all sayowner/name, and the image is/og/repo/…or/og/app/owner~name.png.🤖 Generated with Claude Code
Closes #11689