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
The documentation lives at docs.webjs.dev, a separate subdomain. Two costs.
SEO. Google treats a subdomain as a semi-separate entity, so the docs (the largest
body of indexable content the project has, 45 routes) build authority for docs.webjs.dev instead of for webjs.dev. A path on a strong domain beats a subdomain
of it. This is the same principle that led to dropping a planned GitHub Pages site in #1088: consolidate signals on one domain rather than splitting them.
The subdomain also currently serves no robots.txt and no sitemap.xml (both 404,
verified), so it is likely thinly indexed today. That is the good news: there is little
accumulated equity to disturb, which makes NOW the cheapest this migration will ever be.
Design drift. The docs site has its own layout, nav, and footer, diverging from the
marketing site. A reader crossing from webjs.dev to the docs leaves one design system
and enters another.
Design / approach
Serve the docs at webjs.dev/docs, sharing the marketing site's chrome.
Simplify the docs design to fit the existing webjs.dev shell. The docs should use
the SAME top navbar and footer as /what-is-webjs, /why-webjs, /compare, and /blog,
not a parallel set. The only docs-specific chrome is the sidebar nav for the page tree.
Everything else (header, footer, type scale, tokens, code-block styling) comes from the
marketing site so the docs read as part of one site rather than a bolted-on subdomain.
Two viable implementations, pick during the work:
Merge into the website/ app as website/app/docs/**. Cleanest result (literally
one app, one chrome, one sitemap, no proxy) and the shared layout comes free. Cost is a
real refactor of 45 routes plus the docs content pipeline.
Keep docs/ a separate service and set webjs.basePath = '/docs' (Support basePath/assetPrefix for sub-path deployments #256, built for
exactly this), with a routing layer in front of Railway sending /docs/* to that
service. Less code motion, but the chrome must then be duplicated or extracted into a
shared package, which risks exactly the drift this issue is meant to end.
Recommendation: option 1. The stated goal is design consistency, and option 2 keeps
two layouts alive. Option 1 also collapses the sitemap and robots story into the one that
already works on webjs.dev.
docs.webjs.dev must keep resolving forever, as a redirect-only host. Path-preserving
301s (docs.webjs.dev/docs/x to webjs.dev/docs/x). Framework error messages in SHIPPED
npm packages point at docs.webjs.dev (see below), so old installed versions will keep
sending users there indefinitely.
Implementation notes (for the implementing agent)
Where to edit:
Source app:docs/ (its own WebJs app, 45 page.ts routes under docs/app/docs/**,
plus docs/app/docs/layout.ts which holds the sidebar). Content is mostly in-page
TypeScript, with only 4 .md files, so the migration is route-by-route rather than a
content pipeline port.
Target:website/app/docs/** if taking option 1.
Shared chrome:website/app/layout.ts (the NAV array and the root shell) and website/lib/site-footer.ts. The docs must reuse these, not copy them. Note the footer
is rendered from the ROOT LAYOUT on every page (feat(website): render site footer from the root layout on every page #1082), so a merged docs route gets it
automatically.
Design tokens:website/public/input.css (the @theme block). The docs app has its
own copy that must be dropped, not merged, or the two drift again.
Sitemap:website/app/sitemap.ts, add the docs routes. It already reads live content
queries, so follow that pattern rather than hardcoding 45 paths.
Redirects:docs.webjs.dev needs path-preserving 301s. Either a Cloudflare rule or a
tiny redirect-only service on Railway.
Hardcoded URLs in SHIPPED packages (update for future releases, but they can never be
retroactively fixed in already-published versions):
packages/core/src/component.js L579
packages/server/src/actions.js L270
packages/cli/lib/create.js L1295, L1366, L1500
packages/cli/bin/webjs.js L878
Docs surfaces referencing the subdomain:AGENTS.md, README.md, .agents/skills/webjs/**, packages/cli/templates/**, and website/lib/links.ts
(DOCS_URL).
Landmines / gotchas:
Do NOT add sitemap.ts / robots.ts to docs.webjs.dev first. Getting the
subdomain properly indexed immediately before moving it maximizes migration cost. Migrate,
then let the webjs.dev sitemap cover the new paths.
Sequence this BEFORE any Search Console reindex request, or a reindex cycle is spent
on URLs that are about to move.
website/lib/links.ts reads DOCS_URL from env with a production fallback. Every
in-repo app and the Railway env vars set DOCS_URL, so changing the shape means touching
the Railway service variables too (DOCS_URL is set on the website service).
The docs app has its own llms.txt AND llms-full.txt routes
(docs/app/llms.txt/route.ts, docs/app/llms-full.txt/route.ts). The website has its own llms.txt. Decide the merged story deliberately rather than ending up with two.
The prose hook (.claude/hooks/block-prose-punctuation.sh) blocks em-dashes, space-hyphen
and space-semicolon pauses, and enforces WebJs capitalization. It also fires on shell ;
separators in Bash tool calls.
Invariant 8: only the ROOT layout may write <!doctype> / <html> / <head> / <body>.
A merged docs layout is a NON-root layout and must not.
Invariant 9: no backticks inside html template bodies. The docs are full of code
samples, so route every one through the existing highlight helper on a plain string.
Invariants to respect: AGENTS.md invariants 8, 9, 11.
Tests + docs surfaces:
SSR tests for the migrated routes under website/test/ssr/, mirroring the existing
page-level tests.
A test asserting the docs routes render the SHARED nav and footer (the whole point of the
redesign), which fails if someone reintroduces a docs-specific shell.
A test asserting the sitemap includes docs routes.
A counterfactual proving each new assertion fires.
Update AGENTS.md, README.md, the skill references, and the scaffold templates for the
new URL.
Acceptance criteria
Documentation is served at webjs.dev/docs/**
Docs pages render the SAME top navbar and footer as /what-is-webjs and /why-webjs
Docs pages use the marketing site's design tokens, with no duplicate @theme block
The only docs-specific chrome is the page-tree sidebar
docs.webjs.dev/** path-preservingly 301s to webjs.dev/docs/**
docs.webjs.dev remains resolvable indefinitely (shipped packages link to it)
Docs routes appear in webjs.dev/sitemap.xml
Hardcoded docs URLs in packages/** updated for future releases
AGENTS.md, README.md, skill references, and scaffold templates updated
A counterfactual proves the shared-chrome test actually fires
Verified against a locally rebuilt stylesheet, not production
Problem
The documentation lives at
docs.webjs.dev, a separate subdomain. Two costs.SEO. Google treats a subdomain as a semi-separate entity, so the docs (the largest
body of indexable content the project has, 45 routes) build authority for
docs.webjs.devinstead of forwebjs.dev. A path on a strong domain beats a subdomainof it. This is the same principle that led to dropping a planned GitHub Pages site in
#1088: consolidate signals on one domain rather than splitting them.
The subdomain also currently serves no
robots.txtand nositemap.xml(both 404,verified), so it is likely thinly indexed today. That is the good news: there is little
accumulated equity to disturb, which makes NOW the cheapest this migration will ever be.
Design drift. The docs site has its own layout, nav, and footer, diverging from the
marketing site. A reader crossing from
webjs.devto the docs leaves one design systemand enters another.
Design / approach
Serve the docs at
webjs.dev/docs, sharing the marketing site's chrome.Simplify the docs design to fit the existing
webjs.devshell. The docs should usethe SAME top navbar and footer as
/what-is-webjs,/why-webjs,/compare, and/blog,not a parallel set. The only docs-specific chrome is the sidebar nav for the page tree.
Everything else (header, footer, type scale, tokens, code-block styling) comes from the
marketing site so the docs read as part of one site rather than a bolted-on subdomain.
Two viable implementations, pick during the work:
website/app aswebsite/app/docs/**. Cleanest result (literallyone app, one chrome, one sitemap, no proxy) and the shared layout comes free. Cost is a
real refactor of 45 routes plus the docs content pipeline.
docs/a separate service and setwebjs.basePath = '/docs'(Support basePath/assetPrefix for sub-path deployments #256, built forexactly this), with a routing layer in front of Railway sending
/docs/*to thatservice. Less code motion, but the chrome must then be duplicated or extracted into a
shared package, which risks exactly the drift this issue is meant to end.
Recommendation: option 1. The stated goal is design consistency, and option 2 keeps
two layouts alive. Option 1 also collapses the sitemap and robots story into the one that
already works on
webjs.dev.docs.webjs.devmust keep resolving forever, as a redirect-only host. Path-preserving301s (
docs.webjs.dev/docs/xtowebjs.dev/docs/x). Framework error messages in SHIPPEDnpm packages point at
docs.webjs.dev(see below), so old installed versions will keepsending users there indefinitely.
Implementation notes (for the implementing agent)
Where to edit:
docs/(its own WebJs app, 45page.tsroutes underdocs/app/docs/**,plus
docs/app/docs/layout.tswhich holds the sidebar). Content is mostly in-pageTypeScript, with only 4
.mdfiles, so the migration is route-by-route rather than acontent pipeline port.
website/app/docs/**if taking option 1.website/app/layout.ts(theNAVarray and the root shell) andwebsite/lib/site-footer.ts. The docs must reuse these, not copy them. Note the footeris rendered from the ROOT LAYOUT on every page (feat(website): render site footer from the root layout on every page #1082), so a merged docs route gets it
automatically.
website/public/input.css(the@themeblock). The docs app has itsown copy that must be dropped, not merged, or the two drift again.
website/app/sitemap.ts, add the docs routes. It already reads live contentqueries, so follow that pattern rather than hardcoding 45 paths.
docs.webjs.devneeds path-preserving 301s. Either a Cloudflare rule or atiny redirect-only service on Railway.
retroactively fixed in already-published versions):
packages/core/src/component.jsL579packages/server/src/actions.jsL270packages/cli/lib/create.jsL1295, L1366, L1500packages/cli/bin/webjs.jsL878AGENTS.md,README.md,.agents/skills/webjs/**,packages/cli/templates/**, andwebsite/lib/links.ts(
DOCS_URL).Landmines / gotchas:
sitemap.ts/robots.tstodocs.webjs.devfirst. Getting thesubdomain properly indexed immediately before moving it maximizes migration cost. Migrate,
then let the
webjs.devsitemap cover the new paths.on URLs that are about to move.
website/lib/links.tsreadsDOCS_URLfrom env with a production fallback. Everyin-repo app and the Railway env vars set
DOCS_URL, so changing the shape means touchingthe Railway service variables too (
DOCS_URLis set on the website service).llms.txtANDllms-full.txtroutes(
docs/app/llms.txt/route.ts,docs/app/llms-full.txt/route.ts). The website has its ownllms.txt. Decide the merged story deliberately rather than ending up with two..claude/hooks/block-prose-punctuation.sh) blocks em-dashes, space-hyphenand space-semicolon pauses, and enforces
WebJscapitalization. It also fires on shell;separators in Bash tool calls.
<!doctype>/<html>/<head>/<body>.A merged docs layout is a NON-root layout and must not.
htmltemplate bodies. The docs are full of codesamples, so route every one through the existing highlight helper on a plain string.
webjs.devis behind Cloudflare. A?v-lesstailwind.cssgoes stale at the edge acrossa deploy (fix: fingerprint author-written asset links so a deploy busts the CDN copy #1095), so verify the merged docs against a locally rebuilt stylesheet, never
against production.
Invariants to respect: AGENTS.md invariants 8, 9, 11.
Tests + docs surfaces:
website/test/ssr/, mirroring the existingpage-level tests.
redesign), which fails if someone reintroduces a docs-specific shell.
AGENTS.md,README.md, the skill references, and the scaffold templates for thenew URL.
Acceptance criteria
webjs.dev/docs/**/what-is-webjsand/why-webjs@themeblockdocs.webjs.dev/**path-preservingly 301s towebjs.dev/docs/**docs.webjs.devremains resolvable indefinitely (shipped packages link to it)webjs.dev/sitemap.xmlpackages/**updated for future releasesAGENTS.md,README.md, skill references, and scaffold templates updated