Skip to content

Docs - Redirect dead docs URLs and fix in-repo links that point at them - #5916

Open
krisajenkins wants to merge 2 commits into
masterfrom
docs/legacy-url-redirects
Open

Docs - Redirect dead docs URLs and fix in-repo links that point at them#5916
krisajenkins wants to merge 2 commits into
masterfrom
docs/legacy-url-redirects

Conversation

@krisajenkins

Copy link
Copy Markdown
Contributor

Description of Changes

Old links into the docs are broken in two ways, and this PR fixes both. Links from outside the repo get redirects; links inside the repo are corrected to point at the real page.

1. Redirect the docs URLs the Docusaurus migration left behind

Follow an old link into the docs (a blog post, a bookmark, a search result) and you get raw S3 XML (NoSuchKey), not even a 404 page. Two families of URL are dead:

  • Legacy flat URLs from the pre-Docusaurus site (/docs/unity/part-1, /docs/sdks/rust, /docs/spacetimeauth/create-project, …), gone since the migration (Docusaurus migration #3343).
  • Folder-shaped paths such as /docs/intro/tutorials/chat-app. Nearly every doc sets a slug that flattens its folder out of the URL, so the path you'd guess from the source tree 404s.

@docusaurus/plugin-client-redirects was already a dependency but never configured. This wires it up with docs/redirects.ts:

  • a hand-mapped legacy list, taken from the old docs/nav.ts and cross-checked against the Internet Archive;
  • folder-path → slug redirects generated from the docs tree, so new docs get them for free.

The S3 website endpoint serves directory indexes, so each generated …/index.html stub is reached and followed.

It also fixes the slug typo in parts 3 and 4 of the Godot tutorial (/tutorials/Godot/). The capitalised URLs can't be redirected, because on a case-insensitive filesystem the redirect and the page are the same file. If anyone adds a redirect that differs only by case, redirects.ts fails the build with an explanation.

2. Point in-repo links at real pages

https://spacetimedb.com/templates/astro-ts renders the template's README, and its "Chat App Tutorial" link goes to /docs/intro/tutorials/chat-app, which 404s. The same broken links are in 19 template READMEs.

The cause is tools/templates/generate-template-readmes.ts, which had two bugs:

  • It built URLs from file paths and ignored slug.
  • (\.\.\/)* keeps only its last repeat, so ../../ resolved as ../. That's where the stray /intro/ came from.

It never opened the target file, so neither bug raised an error. Both are fixed, and a link to a missing doc now fails the run.

Hand-written READMEs, Rust doc comments and C# codegen output also used pre-migration paths (/sdks/c-sharp, /modules/rust/quickstart, /sql, /docs/#client). Docusaurus's broken-link check can't see a URL written out in full outside the docs site. These links now point straight at the real page instead of relying on redirects.

Notes for review:

  • Template READMEs: only the links changed. Rerunning the generator would also pull in content drift from the quickstarts and leak MDX (<Tabs>, :::warning) into basic-cs. That's a separate problem, left alone here.

  • C# SQL link: fixed in crates/codegen/src/csharp.rs, its snapshot, and every checked-in SpacetimeDBClient.g.cs, so the generated files still match codegen.

  • Judgement calls:

    • /docs/#client and #host/intro/key-architecture#client and #host.
    • The C# "module library reference" (/modules/c-sharp) → /core-concepts, since there's no per-language page any more.
  • Extra redirects: 7 more, for URLs this repo published but the site never served:

    • /intro/core-concepts/clients/*-reference
    • /reference/cli-reference
    • /reference/sql-reference
    • /sdks/csharp/quickstart
    • /installhttps://spacetimedb.com/install

    Projects created from a template keep their own copy of the README, so those links will stick around.

API and ABI breaking changes

None.

Rollback safety impact

n/a

Expected complexity level and risk

  1. This is mostly links and docs config. The risk is in the docs build:
  • Folder-path redirects are generated at build time, so moving a page updates them automatically.
  • The legacy redirects are hand-mapped. The plugin fails the build if a redirect target isn't a real page, so moving a page one of them targets will break the docs build until the entry is updated. That's the intended safety net.

Testing

These checks were run before rebasing onto current master.

  • The docs build passes with the plugin enabled, which proves every internal redirect target exists. I checked the generated stubs, including the external /install target.
  • I checked all 116 distinct spacetimedb.com/docs URLs in the repo against the build output. Every one is a real page (not a redirect stub), and every #anchor exists.
  • cargo test -p spacetimedb-codegen --test codegen test_codegen_csharp passes. submodule_reducer_wire_name_is_qualified_once failed locally because the TypeScript SDK's npm dependencies weren't installed. It's unrelated to this change.
  • Prettier is clean on the changed TypeScript.
  • After deploy, confirm a legacy URL (e.g. /docs/unity/part-1) and a folder-shaped URL (e.g. /docs/intro/tutorials/chat-app) redirect on the live S3 endpoint.
  • Confirm the templates page picks up the fixed links (e.g. "Chat App Tutorial" on /templates/astro-ts).

Follow an old link into the docs — from a blog post, a bookmark, a search
result — and you do not get a 404 page. You get raw XML from S3:

    Code: NoSuchKey
    Key: docs/godot/part-1
    An Error Occurred While Attempting to Retrieve a Custom Error Document
    Key: 404.html

The bucket has no 404.html either, so the reader gets Amazon's internals and
no way back into the documentation.

Until October 2025 the marketing site rendered the docs itself, serving one
flat URL per entry in `docs/nav.ts`: `/docs/unity/part-1`, `/docs/sdks/rust`,
`/docs/spacetimeauth/create-project`. The Docusaurus migration (#3343) deleted
that file, the reorganisation that followed moved every page, and `/docs/*`
became a static bucket. Every one of those URLs has been dead since, and
nothing redirects them.

A second family breaks for a subtler reason. Nearly every doc sets an explicit
`slug`, which flattens the numbered folder structure out of its URL, so
`docs/00100-intro/00300-tutorials/00100-chat-app.md` is served at
`/docs/tutorials/chat-app`. The folder-shaped path is still what the document
id looks like, it is what `_category_.json` entries point at, and it is what
anyone reading the source tree will reasonably guess — but
`/docs/intro/tutorials/chat-app` 404s exactly like the legacy URLs do.

None of this surfaces in CI. `onBrokenLinks: 'throw'` only checks the links
the site makes to itself, and those were all updated when the pages moved, so
the docs are internally consistent and build clean. Nothing in the repo records
what the URLs used to be, and a reader who lands on the XML has no reason to
report it as a documentation bug.

`@docusaurus/plugin-client-redirects` has been a dependency since #3494 but was
never configured; a redirect list was written and then dropped in b777be7 with
the note "we cannot do redirections". It does work. The S3 website endpoint
serves directory indexes, so a generated page at `docs/godot/part-1/index.html`
is reached and followed. Wire the plugin up and feed it 148 redirects from two
sources:

- The legacy flat URLs, mapped by hand. The list is `docs/nav.ts` as it stood
  at the migration commit's parent, cross-checked against the Internet
  Archive's record of what was actually live before 2025-10-24.
- Folder-shaped path to slug, generated by walking the docs tree and
  reproducing the document ids Docusaurus derives from filenames, so new docs
  get their redirect for free.

The plugin refuses to build a redirect pointing at a route that does not exist,
so a green build proves all 148 destinations resolve.

This also fixes a related typo. Parts 3 and 4 of the Godot tutorial set their
slug as `/tutorials/Godot/`, so the lowercase URL that parts 1 and 2 use 404s,
and `llms.txt` published the capitalised form to every agent reading it. The
capitalised paths cannot themselves be redirected: they differ from the real
page only by case, so on a case-insensitive filesystem the redirect file and
the page are the same file, and the build refuses to overwrite it.
Someone browsing https://spacetimedb.com/templates/astro-ts reads to the
bottom of the page and clicks "Chat App Tutorial". That page is the
template's README.md, rendered, and the link reads:

    - See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example

The tutorial is served at /docs/tutorials/chat-app, with no /intro/ in
it, so the reader lands on a 404. The TypeScript reference link on the
next line, /docs/intro/core-concepts/clients/typescript-reference, is a
404 too, and the same links are in 19 template READMEs.

Those READMEs come from tools/templates/generate-template-readmes.ts,
which turns the quickstarts' relative links into absolute URLs. It had
two bugs. It built each URL from the target's file path with the
ordering prefixes stripped, ignoring the `slug:` front matter that
nearly every doc sets and that Docusaurus actually serves the page at.
And it captured parent references with `(\.\.\/)*`, which keeps only
the last repetition, so `../../00200-core-concepts/...` resolved as
`../00200-core-concepts/...` from inside 00100-intro/. That is where the
stray /intro/ came from. The generator never opened the file it pointed
at, so neither bug raised an error.

The generated READMEs aren't the only offenders. Hand-written READMEs,
Rust doc comments and the C# codegen output still use paths from the
pre-Docusaurus site: /sdks/c-sharp, /modules/rust/quickstart,
/unity/part-1, /sql, /docs/#client. None of this is caught because
Docusaurus only fails the build on broken links between docs pages. A
URL spelled out as https://spacetimedb.com/docs/... anywhere else in
the repo is invisible to it. The legacy redirects in the parent change
rescue most of these links, but source should point at the page itself,
and several of these URLs had no redirect at all.

The generator now uses the target's slug, falling back to the
prefix-stripped path only for the few docs without one, and captures
every parent reference. Because it reads the target, a link to a
missing doc now fails the run. Every other link was rewritten by hand to
the page it now lives at. All 116 distinct spacetimedb.com/docs URLs in
the repo were checked against a fresh docs build: each resolves to a
real page, not a redirect stub, and every #anchor exists.

- Template READMEs get only their links fixed. Re-running the generator
  also pulls in content drift from the quickstarts and leaks MDX (Tabs
  imports, :::warning) into basic-cs, which is a separate problem.
- The SQL reference link in C# codegen output is fixed in
  crates/codegen/src/csharp.rs, its snapshot, and every checked-in
  SpacetimeDBClient.g.cs, so generated files still match codegen.
- /docs/#client and #host now point at the matching sections of
  /intro/key-architecture, and the C# "module library reference"
  (formerly /modules/c-sharp) at /core-concepts.
- Redirects added for URLs that were published but never served: the
  three /intro/core-concepts/clients/*-reference paths,
  /reference/cli-reference, /reference/sql-reference,
  /sdks/csharp/quickstart, and /install (to spacetimedb.com/install).
  Every project created from a template keeps its own copy of the
  README, so these links outlive the fix.
@krisajenkins
krisajenkins marked this pull request as ready for review September 10, 2026 11:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant