You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
/docs/auth and /docs/authentication are two separate doc pages that both declare title: 'Authentication | WebJs', both render <h1>Authentication</h1>, and open by contradicting each other:
/docs/auth: "WebJs provides NextAuth-style authentication with OAuth providers, credentials login, and JWT sessions. No external auth library needed."
/docs/authentication: "WebJs doesn't ship an auth library. It provides the primitives you need to build session-based authentication cleanly."
The sidebar labels them "Auth (Providers)" and "Authentication", so neither entry matches the heading a reader lands on. A reader arriving from search has no way to tell which one answers their question, and the two answers disagree about whether the framework ships auth at all.
This is pre-existing content, but #1098 changed its consequences. docs.webjs.dev served no sitemap.xml at all, so the pair was only thinly indexed. Both pages are now submitted to search engines from webjs.dev/sitemap.xml and listed as two identically-titled entries in /llms.txt, on the domain that migration exists to consolidate authority onto. Two same-titled, mutually contradictory pages competing for the same query is the exact duplication problem the move was meant to reduce.
Design / approach
Decide what the two pages are actually for, then make the titles say it. The likely split, judging by content, is:
/docs/auth documents the built-in createAuth() surface (providers, JWT sessions, the OAuth flow). Title it for that, e.g. "Auth providers (createAuth)".
/docs/authentication documents rolling your own session auth on the framework primitives, which is what the blog example does. Title it for that, e.g. "Building your own authentication".
Then reconcile the opening claims: one of them is wrong as written. WebJs does ship createAuth() (packages/server/src/auth.js), so "doesn't ship an auth library" needs qualifying rather than stating flatly, and "no external auth library needed" needs to not read as if the other page does not exist. Each page should link the other in its first paragraph and say when to reach for which.
Merging them into one page is the other legitimate option, and is worth considering: it removes the ranking competition entirely rather than managing it. Judge that against how long the combined page would be.
The sidebar labels are in website/app/docs/layout.ts, in the Infrastructure and Data & BackendNAV_SECTIONS entries. Keep the sidebar label and the page <h1> consistent with each other; they currently are not.
If the pages merge, delete the folder AND its NAV_SECTIONS entry, and add a webjs.redirects entry in website/package.json so the retired URL 301s to the survivor rather than 404ing (it has been linked from the docs for a while).
Landmines / gotchas:
website/app/sitemap.ts and website/lib/docs-llms.server.ts both enumerate topics from disk, so deleting a page removes it from the sitemap and /llms.txt automatically. That is the right behaviour, but it means a deleted page needs the redirect above or external links break silently.
website/test/ssr/docs-links.test.ts asserts every doc page on disk has a sidebar entry and that every internal /docs link resolves. A merge that leaves a link pointing at the deleted slug fails there, which is what you want.
Invariant 9: no backticks inside the html template body, including inside comments. This has bitten repeatedly in these page files.
Invariant 11 (the prose hook) applies to the page copy: no em-dashes, no space-hyphen pauses, and WebJs capitalized in prose.
Invariants to respect: AGENTS.md invariants 9 and 11.
Tests + docs surfaces:
website/test/ssr/docs-links.test.ts already covers link and nav integrity; extend it with an assertion that no two doc pages declare the same metadata.title, which is the guard that would have caught this.
If the auth surface description changes, check .agents/skills/webjs/references/auth-and-sessions.md still agrees.
Acceptance criteria
No two doc pages share a metadata.title
Each page's <h1> matches its sidebar label
The two pages no longer contradict each other about whether WebJs ships auth
Each links the other and says when to use which (or they are merged into one)
If a page is removed, its URL 301s rather than 404ing
A test asserts the no-duplicate-title rule, with a counterfactual proving it fires
Problem
/docs/authand/docs/authenticationare two separate doc pages that both declaretitle: 'Authentication | WebJs', both render<h1>Authentication</h1>, and open by contradicting each other:/docs/auth: "WebJs provides NextAuth-style authentication with OAuth providers, credentials login, and JWT sessions. No external auth library needed."/docs/authentication: "WebJs doesn't ship an auth library. It provides the primitives you need to build session-based authentication cleanly."The sidebar labels them "Auth (Providers)" and "Authentication", so neither entry matches the heading a reader lands on. A reader arriving from search has no way to tell which one answers their question, and the two answers disagree about whether the framework ships auth at all.
This is pre-existing content, but #1098 changed its consequences.
docs.webjs.devserved nositemap.xmlat all, so the pair was only thinly indexed. Both pages are now submitted to search engines fromwebjs.dev/sitemap.xmland listed as two identically-titled entries in/llms.txt, on the domain that migration exists to consolidate authority onto. Two same-titled, mutually contradictory pages competing for the same query is the exact duplication problem the move was meant to reduce.Design / approach
Decide what the two pages are actually for, then make the titles say it. The likely split, judging by content, is:
/docs/authdocuments the built-increateAuth()surface (providers, JWT sessions, the OAuth flow). Title it for that, e.g. "Auth providers (createAuth)"./docs/authenticationdocuments rolling your own session auth on the framework primitives, which is what the blog example does. Title it for that, e.g. "Building your own authentication".Then reconcile the opening claims: one of them is wrong as written. WebJs does ship
createAuth()(packages/server/src/auth.js), so "doesn't ship an auth library" needs qualifying rather than stating flatly, and "no external auth library needed" needs to not read as if the other page does not exist. Each page should link the other in its first paragraph and say when to reach for which.Merging them into one page is the other legitimate option, and is worth considering: it removes the ranking competition entirely rather than managing it. Judge that against how long the combined page would be.
Implementation notes (for the implementing agent)
Where to edit:
website/app/docs/auth/page.tsandwebsite/app/docs/authentication/page.ts(both moved fromdocs/app/docs/by seo: serve the docs at webjs.dev/docs with the marketing site chrome #1098). The duplicate title is line 3 of each; the contradictory claims are the first<p>of each.website/app/docs/layout.ts, in theInfrastructureandData & BackendNAV_SECTIONSentries. Keep the sidebar label and the page<h1>consistent with each other; they currently are not.NAV_SECTIONSentry, and add awebjs.redirectsentry inwebsite/package.jsonso the retired URL 301s to the survivor rather than 404ing (it has been linked from the docs for a while).Landmines / gotchas:
website/app/sitemap.tsandwebsite/lib/docs-llms.server.tsboth enumerate topics from disk, so deleting a page removes it from the sitemap and/llms.txtautomatically. That is the right behaviour, but it means a deleted page needs the redirect above or external links break silently.website/test/ssr/docs-links.test.tsasserts every doc page on disk has a sidebar entry and that every internal/docslink resolves. A merge that leaves a link pointing at the deleted slug fails there, which is what you want.htmltemplate body, including inside comments. This has bitten repeatedly in these page files.WebJscapitalized in prose.Invariants to respect: AGENTS.md invariants 9 and 11.
Tests + docs surfaces:
website/test/ssr/docs-links.test.tsalready covers link and nav integrity; extend it with an assertion that no two doc pages declare the samemetadata.title, which is the guard that would have caught this..agents/skills/webjs/references/auth-and-sessions.mdstill agrees.Acceptance criteria
metadata.title<h1>matches its sidebar label