Discovery files, structured data and headers from the AEO audit - #15
Merged
Conversation
The three actions were referenced by tag. A tag is mutable, and moving one is exactly how tj-actions/changed-files was turned against every workflow that used it. Each is now pinned to the commit its v4 tag pointed at, with the tag kept as a comment so Dependabot and a reader both know what it is. The workflow also declares `permissions: contents: read`. Nothing in it pushes, comments or publishes, so nothing in it should be able to. Both were flagged by the Vu1nz scan in the 2026-09-03 AEO audit. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019WE33zuAHXQoHKL8jsHQiN
… About page An AEO audit of tsbb.dev (fifteen engines, 2026-09-03) agreed on one thing: the board is perfectly crawlable and says nothing about itself. No robots.txt, no sitemap, no llms.txt, no structured data, no <h1> on the front page, a four-character <title>, and every trailing-slash URL a 404. This is the union of what the engines asked for, generated from settings and the forum tree so it stays true as the board changes. Discovery, all generated, all guest-visible only: - /robots.txt names the sitemap, closes the personal and administrative paths, and welcomes the AI crawlers by name in one group. - /sitemap.xml is an index: /sitemaps/pages.xml for the fixed pages, docs and forums, and /sitemaps/topics-YYYY-MM.xml per month a topic was started, so a past month is skipped on <lastmod> alone. - /llms.txt follows llmstxt.org; /llms-full.txt is every guide as one markdown file; /skill.md tells an agent how to connect over MCP or REST. - /.well-known/security.txt (RFC 9116) with a Contact from the new board.contactEmail setting, falling back to the sending address. Structured data and social meta, in the layout: - WebSite (with a SearchAction) and its publisher Organization on every page; DiscussionForumPosting with the replies as comments on a thread. The JSON is serialised through jsonForHtml, which escapes "<" so a post containing </script> cannot break out of the data block. A data block is not a script, so the CSP that forbids inline script does not apply. - og:image and the twitter:* tags, and a front-page <title> of the board name plus the tagline's first clause. The front page gets a hero: the board name as its one <h1>, the tagline, and for a guest the way in (Join, About, Docs). /about answers what the board is, how to join, how to read it without a browser and who runs it, with question headings, and the footer links to it. The copyright line now reads board.operator instead of a hard-coded name. Headers and paths: - Strict-Transport-Security on every response when the board is served over https; X-Frame-Options and Permissions-Policy on pages. - Cache-Control on pages: a minute, public, for a guest; private and no-cache the moment somebody is signed in; Vary: Cookie either way. - A trailing slash redirects (301) to the slash-less address, query kept. The link checker had counted 67 broken links, all this. Not done, deliberately: the audit's other findings are DNS (DMARC is p=none) or content (word count, testimonials, pricing), neither of which belongs in this repository. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019WE33zuAHXQoHKL8jsHQiN
ralyodio
marked this pull request as ready for review
September 4, 2026 08:57
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes from the 2026-09-03 multi-engine AEO audit of tsbb.dev (average score 40/100). The engines agreed the board was crawlable but silent about itself. This is the union of their fixes, generated from settings and the forum tree so every install gets them and none of it goes stale.
What changes on a running board
/robots.txt404 (every engine)/sitemap.xml404 (every engine)/sitemaps/pages.xmlplus one/sitemaps/topics-YYYY-MM.xmlper month, guest-visible topics only./llms.txt,/llms-full.txt,/skill.md404docs/*.md./.well-known/security.txtmissingContactcomes from the newboard.contactEmailsetting, falling back to the sending address.WebSite+SearchAction+ publisherOrganizationon every page,DiscussionForumPostingwith comments on threads. Serialised throughjsonForHtml, which escapes<so a post containing</script>stays inert.<h1>, 4-character<title><h1>and the tagline;<title>is name plus the tagline's first clause. Guests get Join / About / Docs buttons.og:image, Twitter tags/aboutwith question headings: what it is, how to join, how to read it without a browser, who runs it. Linked from the footer.public, max-age=60for a guest andprivate, no-cacheonce signed in, withVary: Cookie.pnpm/action-setup@v4, nopermissionsblockcontents: read.Two new settings under Admin → Board settings → Identity:
board.operator(defaults to the name the footer already showed) andboard.contactEmail.Not in this PR
p=none. tsbb.dev sends mail, so by the house convention it belongs in thep=rejecttier, but that needs a Forward Email report address and is a DNS change, not code.Cache-Controlhelps a CDN, not the origin.Verification
pnpm typecheckandpnpm test: 192 pass.test/discovery.test.tscovers every file above, the headers, the redirect, the<h1>, and that a</script>in a post cannot escape the JSON-LD block.🤖 Generated with Claude Code
https://claude.ai/code/session_019WE33zuAHXQoHKL8jsHQiN