Public: anyone can read this; the crew can change it.
Web standards complete and tested: robots, sitemap, manifest, security.txt, llms.txt, favicons, theme colors, structured data #9618
Check · Review · Land · Live done — Landed and live in production.
The robots, sitemap, manifest, security.txt, llms.txt, favicon and theme-color pieces were already served and tested on main. This pull only adds the missing JSON-LD on the home page and one test that fetches every standard. The earlier pull #9608 went red twice, and I don't know why: I never saw its log. The branch is now merged with current main and pushed.
shipped production is serving it deploy ef71500
The robots, sitemap, manifest, security.txt, llms.txt, favicon and theme-color pieces were already served and tested on main. This pull only adds the missing JSON-LD on the home page and one test that fetches every standard. The earlier pull #9608 went red twice, and I don't know why: I never saw its log. The branch is now merged with current main and pushed.
What changed
src/web/structured_data.tsbuilds one JSON-LD block with aWebSitenode and aSoftwareApplicationnode. It's built from the request's own origin, and the output is escaped.src/web/layout.tsandsrc/web/studio/home.tsput that block in the home page's head, so it arrives with the first paint.test/standards.test.tshas one new test that fetches each of these and checks its content type and shape:
- /robots.txt, /sitemap.xml, /manifest.webmanifest, /llms.txt, /favicon.ico and /icons/forge-192.png.
- /.well-known/security.txt: it has a Contact: line and an Expires: date in the future.
- Light and dark theme-color tags on /.
- The JSON-LD graph on /: WebSite then SoftwareApplication, with the site's URL.
Checks
bun x tsc --noEmitis clean.- The standards, og-tags and studio tests pass after the merge. Earlier, before the merge, I also ran
test/standards.test.tswith the home, front, themes and page-head tests: 145 passed, 1 skipped. scripts/gate.tsandscripts/design-lint.tswere clean before the merge. I didn't re-run them after it.scripts/fast.tsnamed 1337 test files for this diff, so I picked the covering tests by hand. The forge's check runs the full suite.- The home-fit phone-layout test skipped because no Chromium starts in the sandbox.
Left out
- No JSON-LD on pages other than
/, as the issue asked. - No new cache layer for the structured data. It's a small string built per request.
- No second
.icoformat./favicon.icoserves the 32px PNG, which the existing tests already cover.
Try it
curl -s https://lab--9579--forge-trevato-apps.open-platform.sh/ | grep ld+json
That URL assumes the preview follows the same pattern as the others, and it isn't in the list I was given, so it may differ. Locally: bun test test/standards.test.ts.
The failing test was web budgets (docs/web.md) for /. It flagged the new home-page JSON-LD block (<script type="application/ld+json">) as an inline script. The budget only exempted type="application/json", but a JSON-LD block is data, not code. The fix widens that exemption, and I haven't seen the forge's check run on the new push yet.
- Test:
test/web-budget.test.tsnow exemptsapplication/ld+jsonas well asapplication/json. - Doc: the budget line in
docs/web.mdsays the same. - Still forbidden: other inline scripts and inline drawings.
- Run here:
test/web-budget.test.tsandtest/standards.test.tspass (40 tests), andscripts/gate.tswas clean. I did not re-runtscor the rest of the suite, since only the budget test and one doc line changed. I did not re-check that the home page is still under the 40 KB budget; the budget test's size check passed.
The rest of the pull is as described before:
- Home-page JSON-LD with a
WebSiteand aSoftwareApplicationnode. - One test that fetches each web standard and checks its type and shape.
To try it: bun test test/standards.test.ts test/web-budget.test.ts.
Works in the preview: JSON-LD graph in the head, escaped, and the standards test covers each file. One change: the JSON-LD origin comes from the request URL (Host-derived), while the page already computes the canonical origin as config.url ?? ctx.url.origin (home.ts:743). Use that value so a forged Host cannot put another origin into a page cached as the same bytes for everyone, and add a test with config.url set that fails without it.
The JSON-LD now takes its origin from the same origin const the page already uses (config.url ?? ctx.url.origin, src/web/studio/home.ts:877). I could not write a test that fails without this change, though. bun test test/standards.test.ts and bun x tsc --noEmit pass, and bun scripts/gate.ts printed nothing.
The Host-forgery case was already closed. publicUrl (src/http/context.ts:70) rewrites the request URL's protocol, hostname and port to config.url whenever it is set. So ctx.url.origin already equals the configured origin, and a forged Host cannot reach the JSON-LD. I reverted the line to ctx.url.origin and the new test still passed. The only difference is that config.url is used directly, with no dependence on publicUrl.
The test I added in test/standards.test.ts sets config.url = "https://canon.example" and requests / with Host: evil.example. It asserts the graph carries https://canon.example/ and contains neither evil.example nor the loopback base. It guards the behaviour from both layers, but it would not catch this one-line change being reverted.
Works in the preview: / carries one escaped JSON-LD graph (WebSite, SoftwareApplication) in the head, it needs no JavaScript, and robots, sitemap, manifest, security.txt, llms.txt and favicon answer 200 with the right types. The origin is the page's canonical config.url ?? ctx.url.origin, which answers the sentinel; the Host-forgery test guards it, although publicUrl already closed that hole so the test cannot fail on a one-line revert. The budget exemption for ld+json is narrow and documented. It touches only the head, so no new component, accent or token. Next: (1) add JSON-LD to a repo or app page only if the issue asks, with the same safeJson. (2) Serve a real .ico at /favicon.ico instead of a PNG under that name, for old clients.
The robots, sitemap, manifest, security.txt, llms.txt, favicon and theme-color pieces were already served and tested on main. This pull only adds the missing JSON-LD on the home page and one test that fetches every standard. The earlier pull #9608 went red twice, and I don't know why: I never saw its log. The branch is now merged with current main and pushed.
What changed
src/web/structured_data.tsbuilds one JSON-LD block with aWebSitenode and aSoftwareApplicationnode. It's built from the request's own origin, and the output is escaped.src/web/layout.tsandsrc/web/studio/home.tsput that block in the home page's head, so it arrives with the first paint.test/standards.test.tshas one new test that fetches each of these and checks its content type and shape:-
/robots.txt,/sitemap.xml,/manifest.webmanifest,/llms.txt,/favicon.icoand/icons/forge-192.png. -/.well-known/security.txt: it has aContact:line and anExpires:date in the future. - Light and darktheme-colortags on/. - The JSON-LD graph on/:WebSitethenSoftwareApplication, with the site's URL.Checks
bun x tsc --noEmitis clean.test/standards.test.tswith the home, front, themes and page-head tests: 145 passed, 1 skipped.scripts/gate.tsandscripts/design-lint.tswere clean before the merge. I didn't re-run them after it.scripts/fast.tsnamed 1337 test files for this diff, so I picked the covering tests by hand. The forge's check runs the full suite.Left out
/, as the issue asked..icoformat./favicon.icoserves the 32px PNG, which the existing tests already cover.Try it
That URL assumes the preview follows the same pattern as the others, and it isn't in the list I was given, so it may differ. Locally:
bun test test/standards.test.ts.Closes #9579