diff --git a/README.md b/README.md
index 9d44aa3685f..4ed25d9321f 100644
--- a/README.md
+++ b/README.md
@@ -243,8 +243,8 @@ Full documentation is available at **[spacetimedb.com/docs](https://spacetimedb.
- [Core concepts](https://spacetimedb.com/docs/core-concepts): tables, reducers, subscriptions, authentication
- [Tutorials](https://spacetimedb.com/docs/tutorials/chat-app): chat app, Unity multiplayer, Unreal Engine multiplayer
- [Deployment guide](https://spacetimedb.com/docs/how-to/deploy/maincloud): publishing to Maincloud
-- [CLI reference](https://spacetimedb.com/docs/reference/cli-reference)
-- [SQL reference](https://spacetimedb.com/docs/reference/sql-reference)
+- [CLI reference](https://spacetimedb.com/docs/cli-reference)
+- [SQL reference](https://spacetimedb.com/docs/reference/sql)
## License
diff --git a/crates/bindings-csharp/Codegen/README.md b/crates/bindings-csharp/Codegen/README.md
index 5e6b952d08c..739e77aa11a 100644
--- a/crates/bindings-csharp/Codegen/README.md
+++ b/crates/bindings-csharp/Codegen/README.md
@@ -2,7 +2,7 @@
>
> This project is intended for internal use only. It is **not** stable and may change without notice.
-See the [C# module library reference](https://spacetimedb.com/docs/modules/c-sharp) for stable, user-facing documentation.
+See the [C# module library reference](https://spacetimedb.com/docs/core-concepts) for stable, user-facing documentation.
## Internal documentation
diff --git a/crates/bindings-csharp/README.md b/crates/bindings-csharp/README.md
index a97596d4ec9..947f57c9a08 100644
--- a/crates/bindings-csharp/README.md
+++ b/crates/bindings-csharp/README.md
@@ -2,7 +2,7 @@
>
> The interface of this project is **not** stable and may change without notice.
-See the [C# module library reference](https://spacetimedb.com/docs/modules/c-sharp) and the [C# client SDK reference](https://spacetimedb.com/docs/sdks/c-sharp) for stable, user-facing documentation.
+See the [C# module library reference](https://spacetimedb.com/docs/core-concepts) and the [C# client SDK reference](https://spacetimedb.com/docs/clients/c-sharp) for stable, user-facing documentation.
## Internal documentation
diff --git a/crates/bindings-csharp/Runtime/Attrs.cs b/crates/bindings-csharp/Runtime/Attrs.cs
index afcfcc0688e..c8ce86aa2d9 100644
--- a/crates/bindings-csharp/Runtime/Attrs.cs
+++ b/crates/bindings-csharp/Runtime/Attrs.cs
@@ -44,7 +44,7 @@ public abstract class ColumnAttribute : Attribute
/// so that any row permitted by at least one filter is visible.
///
/// The query follows the same syntax as a subscription query.
- /// See the SQL reference for more information.
+ /// See the SQL reference for more information.
///
/// This is an experimental feature and subject to change in the future.
///
diff --git a/crates/bindings-csharp/Runtime/README.md b/crates/bindings-csharp/Runtime/README.md
index baea0bee302..e4b322c129a 100644
--- a/crates/bindings-csharp/Runtime/README.md
+++ b/crates/bindings-csharp/Runtime/README.md
@@ -4,7 +4,7 @@
# SpacetimeDB.Runtime
-This project contains the runtime bindings for SpacetimeDB WebAssembly modules. See the [C# module library reference](https://spacetimedb.com/docs/modules/c-sharp) for stable, user-facing documentation.
+This project contains the runtime bindings for SpacetimeDB WebAssembly modules. See the [C# module library reference](https://spacetimedb.com/docs/core-concepts) for stable, user-facing documentation.
SpacetimeDB modules are compiled to WebAssembly modules that expose a specific interface; see the [module ABI reference](https://spacetimedb.com/docs/webassembly-abi).
diff --git a/crates/bindings/README.md b/crates/bindings/README.md
index 5f624e163f2..160018bee26 100644
--- a/crates/bindings/README.md
+++ b/crates/bindings/README.md
@@ -42,7 +42,7 @@ Rust modules are written with the the Rust Module Library (this crate). They are
(Note: Rust can also be used to write **clients** of SpacetimeDB databases, but this requires using a different library, the SpacetimeDB Rust Client SDK. See the documentation on [clients] for more information.)
-This reference assumes you are familiar with the basics of Rust. If you aren't, check out Rust's [excellent documentation](https://www.rust-lang.org/learn). For a guided introduction to Rust Modules, see the [Rust Module Quickstart](https://spacetimedb.com/docs/modules/rust/quickstart).
+This reference assumes you are familiar with the basics of Rust. If you aren't, check out Rust's [excellent documentation](https://www.rust-lang.org/learn). For a guided introduction to Rust Modules, see the [Rust Module Quickstart](https://spacetimedb.com/docs/quickstarts/rust).
## Overview
@@ -334,7 +334,7 @@ pub struct LootItem {
(Note that, when run by the module owner, the `spacetime sql ` command can also read private tables. This is for debugging convenience. Only the module owner can see these tables. This is determined by the `Identity` stored by the `spacetime login` command. Run `spacetime login show` to print your current logged-in `Identity`.)
-To learn how to subscribe to a public table, see the [client SDK documentation](https://spacetimedb.com/docs/sdks).
+To learn how to subscribe to a public table, see the [client SDK documentation](https://spacetimedb.com/docs/clients).
#### Unique and Primary Key Columns
@@ -697,8 +697,8 @@ Currently, manual migration support is limited. The `spacetime publish --delete-
[macro library]: https://github.com/clockworklabs/SpacetimeDB/tree/master/crates/bindings-macro
[module library]: https://github.com/clockworklabs/SpacetimeDB/tree/master/crates/lib
[demo]: /#demo
-[client]: https://spacetimedb.com/docs/#client
-[clients]: https://spacetimedb.com/docs/#client
-[client SDK documentation]: https://spacetimedb.com/docs/#client
-[host]: https://spacetimedb.com/docs/#host
-[SEQUENCE]: https://spacetimedb.com/docs/appendix#sequence
+[client]: https://spacetimedb.com/docs/intro/key-architecture#client
+[clients]: https://spacetimedb.com/docs/intro/key-architecture#client
+[client SDK documentation]: https://spacetimedb.com/docs/clients
+[host]: https://spacetimedb.com/docs/intro/key-architecture#host
+[SEQUENCE]: https://spacetimedb.com/docs/tables/auto-increment#sequences
diff --git a/crates/bindings/src/lib.rs b/crates/bindings/src/lib.rs
index 190065c5e1f..6c897bc333d 100644
--- a/crates/bindings/src/lib.rs
+++ b/crates/bindings/src/lib.rs
@@ -707,7 +707,7 @@ pub use spacetimedb_bindings_macro::table;
///
///
/// [`&ReducerContext`]: `ReducerContext`
-/// [clients]: https://spacetimedb.com/docs/#client
+/// [clients]: https://spacetimedb.com/docs/intro/key-architecture#client
#[doc(inline)]
pub use spacetimedb_bindings_macro::reducer;
@@ -777,7 +777,7 @@ pub use spacetimedb_bindings_macro::reducer;
/// Scheduled procedures are called on a best-effort basis and may be slightly delayed in their execution
/// when a database is under heavy load.
///
-/// [clients]: https://spacetimedb.com/docs/#client
+/// [clients]: https://spacetimedb.com/docs/intro/key-architecture#client
// TODO(procedure-async): update docs and examples with `async`-ness.
#[doc(inline)]
pub use spacetimedb_bindings_macro::procedure;
diff --git a/crates/codegen/src/csharp.rs b/crates/codegen/src/csharp.rs
index edc372a14e0..931bf205484 100644
--- a/crates/codegen/src/csharp.rs
+++ b/crates/codegen/src/csharp.rs
@@ -457,7 +457,7 @@ const REDUCER_EVENTS: &str = r#"
/// Data from all the provided queries will be returned at the same time.
///
/// See the SpacetimeDB SQL docs for more information on SQL syntax:
- /// https://spacetimedb.com/docs/sql
+ /// https://spacetimedb.com/docs/reference/sql
///
public SubscriptionHandle Subscribe(
string[] querySqls
diff --git a/crates/codegen/tests/snapshots/codegen__codegen_csharp.snap b/crates/codegen/tests/snapshots/codegen__codegen_csharp.snap
index 21fe014ee8d..2a5bb2b6943 100644
--- a/crates/codegen/tests/snapshots/codegen__codegen_csharp.snap
+++ b/crates/codegen/tests/snapshots/codegen__codegen_csharp.snap
@@ -1685,7 +1685,7 @@ namespace SpacetimeDB
/// Data from all the provided queries will be returned at the same time.
///
/// See the SpacetimeDB SQL docs for more information on SQL syntax:
- /// https://spacetimedb.com/docs/sql
+ /// https://spacetimedb.com/docs/reference/sql
///
public SubscriptionHandle Subscribe(
string[] querySqls
diff --git a/demo/Blackholio/README.md b/demo/Blackholio/README.md
index 85635e9059e..fe505cd2a13 100644
--- a/demo/Blackholio/README.md
+++ b/demo/Blackholio/README.md
@@ -25,7 +25,7 @@ Need help with the tutorial? [Join our Discord server](https://discord.gg/spacet
---
### **Getting Started**
-If you want to follow a more structured tutorial where it shows you how to set everything up, start with our [Blackholio Tutorial](https://spacetimedb.com/docs/unity/part-1).
+If you want to follow a more structured tutorial where it shows you how to set everything up, start with our [Blackholio Tutorial](https://spacetimedb.com/docs/tutorials/unity/part-1).
If you just want to checkout the final project and play around a bit, follow these steps:
@@ -79,7 +79,7 @@ Blackholio/
### **Requirements**
- **Unity**: Version `2021.2` or newer.
- **Rust**: Version `1.65.0` or later (for the SpacetimeDB server module).
-- **SpacetimeDB CLI**: Installed via [SpacetimeDB installation guide](https://spacetimedb.com/docs/install).
+- **SpacetimeDB CLI**: Installed via [SpacetimeDB installation guide](https://spacetimedb.com/install).
---
diff --git a/demo/Blackholio/client-godot/module_bindings/SpacetimeDBClient.g.cs b/demo/Blackholio/client-godot/module_bindings/SpacetimeDBClient.g.cs
index 44743e2dfab..4ffcdc13fb4 100644
--- a/demo/Blackholio/client-godot/module_bindings/SpacetimeDBClient.g.cs
+++ b/demo/Blackholio/client-godot/module_bindings/SpacetimeDBClient.g.cs
@@ -482,7 +482,7 @@ public TypedSubscriptionBuilder AddQuery(
/// Data from all the provided queries will be returned at the same time.
///
/// See the SpacetimeDB SQL docs for more information on SQL syntax:
- /// https://spacetimedb.com/docs/sql
+ /// https://spacetimedb.com/docs/reference/sql
///
public SubscriptionHandle Subscribe(
string[] querySqls
diff --git a/demo/Blackholio/client-unity/Assets/Scripts/autogen/SpacetimeDBClient.g.cs b/demo/Blackholio/client-unity/Assets/Scripts/autogen/SpacetimeDBClient.g.cs
index e7febb6fa13..3ef7b17d6e7 100644
--- a/demo/Blackholio/client-unity/Assets/Scripts/autogen/SpacetimeDBClient.g.cs
+++ b/demo/Blackholio/client-unity/Assets/Scripts/autogen/SpacetimeDBClient.g.cs
@@ -482,7 +482,7 @@ public TypedSubscriptionBuilder AddQuery(
/// Data from all the provided queries will be returned at the same time.
///
/// See the SpacetimeDB SQL docs for more information on SQL syntax:
- /// https://spacetimedb.com/docs/sql
+ /// https://spacetimedb.com/docs/reference/sql
///
public SubscriptionHandle Subscribe(
string[] querySqls
diff --git a/docs/docs/00100-intro/00300-tutorials/00500-godot-tutorial/00400-part-3.md b/docs/docs/00100-intro/00300-tutorials/00500-godot-tutorial/00400-part-3.md
index 46291fe7202..5ba7f4ff074 100644
--- a/docs/docs/00100-intro/00300-tutorials/00500-godot-tutorial/00400-part-3.md
+++ b/docs/docs/00100-intro/00300-tutorials/00500-godot-tutorial/00400-part-3.md
@@ -1,6 +1,6 @@
---
title: 3 - Gameplay
-slug: /tutorials/Godot/part-3
+slug: /tutorials/godot/part-3
---
import Tabs from '@theme/Tabs';
diff --git a/docs/docs/00100-intro/00300-tutorials/00500-godot-tutorial/00500-part-4.md b/docs/docs/00100-intro/00300-tutorials/00500-godot-tutorial/00500-part-4.md
index 71eff102a9c..b470aaf22ca 100644
--- a/docs/docs/00100-intro/00300-tutorials/00500-godot-tutorial/00500-part-4.md
+++ b/docs/docs/00100-intro/00300-tutorials/00500-godot-tutorial/00500-part-4.md
@@ -1,6 +1,6 @@
---
title: 4 - Moving and Colliding
-slug: /tutorials/Godot/part-4
+slug: /tutorials/godot/part-4
---
import Tabs from '@theme/Tabs';
diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts
index accf916617a..62539135aa9 100644
--- a/docs/docusaurus.config.ts
+++ b/docs/docusaurus.config.ts
@@ -21,6 +21,7 @@ import systemd from 'shiki/langs/systemd.mjs';
import ogTheme from 'shiki/themes/dracula.mjs';
import cpp from 'shiki/langs/cpp.mjs';
import { InkeepConfig } from '@inkeep/cxkit-docusaurus';
+import { redirects } from './redirects';
// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)
@@ -235,6 +236,12 @@ const config: Config = {
} satisfies Preset.ThemeConfig,
plugins: [
+ [
+ '@docusaurus/plugin-client-redirects',
+ {
+ redirects,
+ },
+ ],
[
'@inkeep/cxkit-docusaurus',
{
diff --git a/docs/redirects.ts b/docs/redirects.ts
new file mode 100644
index 00000000000..30a2d360ad8
--- /dev/null
+++ b/docs/redirects.ts
@@ -0,0 +1,244 @@
+import fs from 'node:fs';
+import path from 'node:path';
+
+/**
+ * Redirects for URLs that used to resolve on spacetimedb.com and no longer do.
+ *
+ * `/docs/*` is a static bucket, so each of these becomes a generated HTML stub
+ * that bounces the reader on. Two consequences worth knowing: the plugin fails
+ * the build if a `to` is not a real route, which is the safety net that keeps
+ * this file honest as pages move; and a redirect can never differ from its
+ * target only by case, because the stub and the page would be the same file on
+ * a case-insensitive filesystem.
+ */
+
+export type Redirect = { from: string; to: string };
+
+const DOCS_DIR = path.join(__dirname, 'docs');
+
+/**
+ * URLs the pre-Docusaurus docs site served, taken from the `docs/nav.ts` that
+ * drove it (deleted in the Docusaurus migration, #3343).
+ *
+ * Every path here resolved on spacetimedb.com until October 2025, so inbound
+ * links, bookmarks and search results still point at them. Paths that came
+ * through the migration unchanged — `/bsatn`, `/cli-reference`,
+ * `/cli-reference/standalone-config`, `/http/*`, `/sats-json`,
+ * `/webassembly-abi`, `/how-to/reject-client-connections` — need no entry.
+ */
+const legacyRedirects: Redirect[] = [
+ // Intro.
+ { from: '/index', to: '/' },
+ { from: '/getting-started', to: '/' },
+ { from: '/ai-chat', to: '/ask-ai/ask-ai' },
+
+ // Deploying.
+ { from: '/deploying/maincloud', to: '/how-to/deploy/maincloud' },
+ {
+ from: '/deploying/spacetimedb-standalone',
+ to: '/how-to/deploy/self-hosting',
+ },
+ // Retired before the migration, but still archived and linked to.
+ { from: '/deploying/testnet', to: '/how-to/deploy/maincloud' },
+
+ // Unity tutorial.
+ { from: '/unity', to: '/tutorials/unity' },
+ { from: '/unity/part-1', to: '/tutorials/unity/part-1' },
+ { from: '/unity/part-2', to: '/tutorials/unity/part-2' },
+ { from: '/unity/part-3', to: '/tutorials/unity/part-3' },
+ { from: '/unity/part-4', to: '/tutorials/unity/part-4' },
+
+ // Unreal tutorial.
+ { from: '/unreal', to: '/tutorials/unreal' },
+ { from: '/unreal/part-1', to: '/tutorials/unreal/part-1' },
+ { from: '/unreal/part-2', to: '/tutorials/unreal/part-2' },
+ { from: '/unreal/part-3', to: '/tutorials/unreal/part-3' },
+ { from: '/unreal/part-4', to: '/tutorials/unreal/part-4' },
+ { from: '/unreal/reference', to: '/clients/unreal' },
+
+ // Server module languages. The per-language module references are gone;
+ // that material now lives in the language-agnostic core-concepts pages.
+ { from: '/modules', to: '/functions' },
+ { from: '/modules/rust', to: '/functions' },
+ { from: '/modules/c-sharp', to: '/functions' },
+ { from: '/modules/typescript', to: '/functions' },
+ { from: '/modules/rust/quickstart', to: '/quickstarts/rust' },
+ { from: '/modules/c-sharp/quickstart', to: '/quickstarts/c-sharp' },
+ { from: '/modules/typescript/quickstart', to: '/quickstarts/typescript' },
+
+ // Client SDK languages.
+ { from: '/sdks', to: '/clients' },
+ { from: '/sdks/rust', to: '/clients/rust' },
+ { from: '/sdks/c-sharp', to: '/clients/c-sharp' },
+ { from: '/sdks/typescript', to: '/clients/typescript' },
+ { from: '/sdks/rust/quickstart', to: '/quickstarts/rust' },
+ { from: '/sdks/c-sharp/quickstart', to: '/quickstarts/c-sharp' },
+ { from: '/sdks/typescript/quickstart', to: '/quickstarts/typescript' },
+
+ // SQL.
+ { from: '/sql', to: '/reference/sql' },
+ { from: '/sql/pg-wire', to: '/how-to/pg-wire' },
+
+ // Subscriptions.
+ { from: '/subscriptions', to: '/clients/subscriptions' },
+ { from: '/subscriptions/semantics', to: '/clients/subscriptions/semantics' },
+
+ // Row level security.
+ { from: '/rls', to: '/how-to/rls' },
+
+ // How to.
+ {
+ from: '/how-to/incremental-migrations',
+ to: '/databases/incremental-migrations',
+ },
+
+ // SpacetimeAuth.
+ { from: '/spacetimeauth', to: '/core-concepts/authentication/spacetimeauth' },
+ {
+ from: '/spacetimeauth/create-project',
+ to: '/core-concepts/authentication/spacetimeauth/creating-a-project',
+ },
+ {
+ from: '/spacetimeauth/configure-project',
+ to: '/core-concepts/authentication/spacetimeauth/configuring-a-project',
+ },
+ {
+ from: '/spacetimeauth/testing-authentication',
+ to: '/core-concepts/authentication/spacetimeauth/testing',
+ },
+ {
+ from: '/spacetimeauth/react-integration',
+ to: '/core-concepts/authentication/spacetimeauth/react-integration',
+ },
+
+ // HTTP API. The individual pages kept their URLs; only the section index
+ // went away.
+ { from: '/http', to: '/http/authorization' },
+
+ // Appendix. Its one section documented `#[auto_inc]` sequences.
+ { from: '/appendix', to: '/tables/auto-increment' },
+
+ // Never served, but published from this repo. The template README generator
+ // built the first three from file paths instead of slugs, and the rest were
+ // mistyped in hand-written READMEs. Every project created from a template
+ // keeps its own copy of the README, so these links outlive the fix.
+ {
+ from: '/intro/core-concepts/clients/typescript-reference',
+ to: '/clients/typescript',
+ },
+ {
+ from: '/intro/core-concepts/clients/rust-reference',
+ to: '/clients/rust',
+ },
+ {
+ from: '/intro/core-concepts/clients/csharp-reference',
+ to: '/clients/c-sharp',
+ },
+ { from: '/reference/cli-reference', to: '/cli-reference' },
+ { from: '/reference/sql-reference', to: '/reference/sql' },
+ { from: '/sdks/csharp/quickstart', to: '/quickstarts/c-sharp' },
+ // Installation is a page on the main site, outside the docs.
+ { from: '/install', to: 'https://spacetimedb.com/install' },
+
+ // The Godot tutorial postdates the migration, so these were never live — but
+ // they are the obvious guess next to `/unity/part-1` and `/unreal/part-1`,
+ // and they are what people try.
+ { from: '/godot', to: '/tutorials/godot' },
+ { from: '/godot/part-1', to: '/tutorials/godot/part-1' },
+ { from: '/godot/part-2', to: '/tutorials/godot/part-2' },
+ { from: '/godot/part-3', to: '/tutorials/godot/part-3' },
+ { from: '/godot/part-4', to: '/tutorials/godot/part-4' },
+
+ // Parts 3 and 4 were published under `/tutorials/Godot/` until the slug typo
+ // was fixed. Those URLs are unrecoverable here — see
+ // `rejectCaseOnlyRedirects` — and would have to be handled in front of S3.
+];
+
+function markdownFiles(dir: string): string[] {
+ return fs.readdirSync(dir, { withFileTypes: true }).flatMap(entry => {
+ const entryPath = path.join(dir, entry.name);
+ if (entry.isDirectory()) {
+ return markdownFiles(entryPath);
+ }
+ return /\.mdx?$/.test(entry.name) ? [entryPath] : [];
+ });
+}
+
+/**
+ * The URL Docusaurus would serve a doc at if it set no `slug`: its path under
+ * `docs/`, with the numeric ordering prefixes stripped.
+ */
+function defaultRoute(file: string): string {
+ const rawSegments = path
+ .relative(DOCS_DIR, file)
+ .replace(/\.mdx?$/, '')
+ .split(path.sep);
+ const segments = rawSegments.map(segment => segment.replace(/^\d+-/, ''));
+
+ // `index`, `readme` and a file named after its folder all address the folder
+ // itself. Docusaurus makes this comparison on the raw filenames, before the
+ // ordering prefixes come off, so `00000-index.md` is not a folder index.
+ const leaf = rawSegments.at(-1)!.toLowerCase();
+ const parent = rawSegments.at(-2)?.toLowerCase();
+ if (leaf === 'index' || leaf === 'readme' || leaf === parent) {
+ segments.pop();
+ }
+
+ return `/${segments.join('/')}`;
+}
+
+function frontMatterSlug(file: string): string | undefined {
+ const frontMatter = /^---\r?\n([\s\S]*?)\r?\n---/.exec(
+ fs.readFileSync(file, 'utf8')
+ )?.[1];
+ return /^slug:\s*(\S+)\s*$/m
+ .exec(frontMatter ?? '')?.[1]
+ .replace(/^['"]|['"]$/g, '');
+}
+
+/**
+ * Nearly every doc sets an explicit `slug`, which flattens the numbered folder
+ * structure out of its URL: `docs/00100-intro/00300-tutorials/00100-chat-app.md`
+ * is served at `/tutorials/chat-app`, not `/intro/tutorials/chat-app`. The
+ * folder-shaped path is still what the source tree looks like, so it is what
+ * anyone reading it will reasonably guess. Point each one at the slug the page
+ * actually uses.
+ */
+const structuralRedirects: Redirect[] = markdownFiles(DOCS_DIR)
+ .flatMap(file => {
+ const from = defaultRoute(file);
+ const to = frontMatterSlug(file);
+ // A doc with no slug already lives at its folder-shaped path, and one whose
+ // slug *is* that path would redirect to itself — which the plugin rejects,
+ // since writing the redirect would overwrite the page.
+ return to && to !== from ? [{ from, to }] : [];
+ })
+ // Deterministic across filesystems; the plugin does not care about order.
+ .sort((a, b) => a.from.localeCompare(b.from));
+
+/**
+ * A redirect whose source differs from its target only by case cannot be
+ * emitted: on a case-insensitive filesystem the generated redirect file and the
+ * real page are the same file, and the build aborts with an unexplained "not
+ * supposed to override existing files". Fail here, where the message can say
+ * what to do about it, rather than on the next Mac to run a build.
+ */
+function rejectCaseOnlyRedirects(all: Redirect[]): Redirect[] {
+ const caseOnly = all.filter(
+ ({ from, to }) => from !== to && from.toLowerCase() === to.toLowerCase()
+ );
+ if (caseOnly.length > 0) {
+ throw new Error(
+ 'These redirects differ from their target only by case, which cannot be ' +
+ 'served from a static build. Rename the source file to match the slug ' +
+ 'instead:\n' +
+ caseOnly.map(({ from, to }) => ` ${from} -> ${to}`).join('\n')
+ );
+ }
+ return all;
+}
+
+export const redirects: Redirect[] = rejectCaseOnlyRedirects([
+ ...legacyRedirects,
+ ...structuralRedirects,
+]);
diff --git a/docs/sidebars.ts b/docs/sidebars.ts
index a897b140c41..5e98a84eea1 100644
--- a/docs/sidebars.ts
+++ b/docs/sidebars.ts
@@ -33,11 +33,12 @@ const sidebars: SidebarsConfig = {
link: { type: 'doc', id: 'intro/tutorials/chat-app' },
items: [{ type: 'autogenerated', dirName: '00100-intro/00300-tutorials' }],
},
- // Core Concepts section header
+ // Core Concepts section header - links to the section's index page
{
- type: 'html',
- value: '',
- defaultStyle: false,
+ type: 'doc',
+ id: 'core-concepts/index',
+ label: 'Core Concepts',
+ className: 'spacetime-menu-header-link',
},
{
type: 'category',
@@ -89,11 +90,12 @@ const sidebars: SidebarsConfig = {
{ type: 'doc', id: 'core-concepts/clients/unreal-reference' },
],
},
- // Developer Resources section header
+ // Developer Resources section header - links to the section's index page
{
- type: 'html',
- value: '',
- defaultStyle: false,
+ type: 'doc',
+ id: 'resources/index',
+ label: 'Developer Resources',
+ className: 'spacetime-menu-header-link',
},
{
type: 'ref',
diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css
index 9d075b0e3cf..98a8f824d86 100644
--- a/docs/src/css/custom.css
+++ b/docs/src/css/custom.css
@@ -609,7 +609,7 @@ ul.theme-doc-sidebar-menu {
padding: 0;
}
-/* Static section headers (non-clickable labels like "Getting Started", "Core Concepts") */
+/* Static section headers (non-clickable labels like "Intro") */
.spacetime-menu-header {
overflow: hidden;
color: var(--clockworklabs-color-n4);
@@ -637,6 +637,23 @@ ul.theme-doc-sidebar-menu
padding-left: 8px !important;
}
+/* Section headers that link to their section's index page ("Core Concepts", "Developer Resources").
+ Same look as .spacetime-menu-header, but rendered as a regular sidebar doc link. */
+ul.theme-doc-sidebar-menu
+ > .menu__list-item.spacetime-menu-header-link
+ > .menu__link {
+ font-family: var(--clockworklabs-font-source);
+ letter-spacing: calc(var(--11-7px) * 0.08);
+ text-transform: uppercase;
+ padding: 24px 8px 12px 0 !important;
+}
+
+ul.theme-doc-sidebar-menu
+ > .menu__list-item.spacetime-menu-header-link
+ > .menu__link:hover {
+ background: transparent;
+}
+
ul.theme-doc-sidebar-menu
> .theme-doc-sidebar-item-category-level-1
> .menu__list-item-collapsible
diff --git a/docs/static/llms.md b/docs/static/llms.md
index e7e7aa1a8e5..e2d9cae393d 100644
--- a/docs/static/llms.md
+++ b/docs/static/llms.md
@@ -171,8 +171,8 @@ This is a list of common problems when using SpacetimeDB and how to fix them.
- [Godot Tutorial](/docs/tutorials/godot): Need help with the tutorial or CLI commands? Join our Discord server!
- [1 - Setup](/docs/tutorials/godot/part-1): Unity Tutorial Hero Image
- [2 - Connecting to SpacetimeDB](/docs/tutorials/godot/part-2): Need help with the tutorial? Join our Discord server!
-- [3 - Gameplay](/docs/tutorials/Godot/part-3): Need help with the tutorial? Join our Discord server!
-- [4 - Moving and Colliding](/docs/tutorials/Godot/part-4): Need help with the tutorial? Join our Discord server!
+- [3 - Gameplay](/docs/tutorials/godot/part-3): Need help with the tutorial? Join our Discord server!
+- [4 - Moving and Colliding](/docs/tutorials/godot/part-4): Need help with the tutorial? Join our Discord server!
- [Unity Tutorial](/docs/tutorials/unity): Need help with the tutorial or CLI commands? Join our Discord server!
- [1 - Setup](/docs/tutorials/unity/part-1): Unity Tutorial Hero Image
- [2 - Connecting to SpacetimeDB](/docs/tutorials/unity/part-2): Need help with the tutorial? Join our Discord server!
diff --git a/docs/versioned_sidebars/version-1.12.0-sidebars.json b/docs/versioned_sidebars/version-1.12.0-sidebars.json
index fda2b33d77f..834e3a873a1 100644
--- a/docs/versioned_sidebars/version-1.12.0-sidebars.json
+++ b/docs/versioned_sidebars/version-1.12.0-sidebars.json
@@ -46,9 +46,10 @@
]
},
{
- "type": "html",
- "value": "",
- "defaultStyle": false
+ "type": "doc",
+ "id": "core-concepts/index",
+ "label": "Core Concepts",
+ "className": "spacetime-menu-header-link"
},
{
"type": "category",
@@ -141,9 +142,10 @@
]
},
{
- "type": "html",
- "value": "",
- "defaultStyle": false
+ "type": "doc",
+ "id": "resources/index",
+ "label": "Developer Resources",
+ "className": "spacetime-menu-header-link"
},
{
"type": "category",
diff --git a/sdks/csharp/README.dotnet.md b/sdks/csharp/README.dotnet.md
index 749a371c540..d524d8e26a6 100644
--- a/sdks/csharp/README.dotnet.md
+++ b/sdks/csharp/README.dotnet.md
@@ -6,4 +6,4 @@ This repository contains the [C#](https://learn.microsoft.com/en-us/dotnet/cshar
## Documentation
-The C# SDK has a [Quick Start](https://spacetimedb.com/docs/sdks/c-sharp/quickstart) guide and a [Reference](https://spacetimedb.com/docs/sdks/c-sharp).
+The C# SDK has a [Quick Start](https://spacetimedb.com/docs/quickstarts/c-sharp) guide and a [Reference](https://spacetimedb.com/docs/clients/c-sharp).
diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs
index 0fa3dd38aa7..f17f888e1c8 100644
--- a/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs
+++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs
@@ -522,7 +522,7 @@ public TypedSubscriptionBuilder AddQuery(
/// Data from all the provided queries will be returned at the same time.
///
/// See the SpacetimeDB SQL docs for more information on SQL syntax:
- /// https://spacetimedb.com/docs/sql
+ /// https://spacetimedb.com/docs/reference/sql
///
public SubscriptionHandle Subscribe(
string[] querySqls
diff --git a/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs
index 948b4e405d7..4bdf39df0a8 100644
--- a/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs
+++ b/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs
@@ -479,7 +479,7 @@ public TypedSubscriptionBuilder AddQuery(
/// Data from all the provided queries will be returned at the same time.
///
/// See the SpacetimeDB SQL docs for more information on SQL syntax:
- /// https://spacetimedb.com/docs/sql
+ /// https://spacetimedb.com/docs/reference/sql
///
public SubscriptionHandle Subscribe(
string[] querySqls
diff --git a/sdks/csharp/examples~/regression-tests/republishing/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/republishing/client/module_bindings/SpacetimeDBClient.g.cs
index ba9311b5d45..446d0a75382 100644
--- a/sdks/csharp/examples~/regression-tests/republishing/client/module_bindings/SpacetimeDBClient.g.cs
+++ b/sdks/csharp/examples~/regression-tests/republishing/client/module_bindings/SpacetimeDBClient.g.cs
@@ -477,7 +477,7 @@ public TypedSubscriptionBuilder AddQuery(
/// Data from all the provided queries will be returned at the same time.
///
/// See the SpacetimeDB SQL docs for more information on SQL syntax:
- /// https://spacetimedb.com/docs/sql
+ /// https://spacetimedb.com/docs/reference/sql
///
public SubscriptionHandle Subscribe(
string[] querySqls
diff --git a/sdks/rust/src/lib.rs b/sdks/rust/src/lib.rs
index e7efd286514..09429973105 100644
--- a/sdks/rust/src/lib.rs
+++ b/sdks/rust/src/lib.rs
@@ -3,7 +3,7 @@
//!
//! This library depends on a set of module-specific definitions
//! autogenerated by [the SpacetimeDB CLI](https://spacetimedb.com/install).
-//! See [the SpacetimeDB Rust client SDK reference](https://spacetimedb.com/docs/sdks/rust#generate-module-bindings)
+//! See [the SpacetimeDB Rust client SDK reference](https://spacetimedb.com/docs/clients/rust#generate-module-bindings)
//! for more oh how to generate these bindings.
// Any `#[doc(hidden)]` modules or uses are public because
diff --git a/sdks/unreal/examples/README.md b/sdks/unreal/examples/README.md
index e46bb47eb57..17f8ddf819f 100644
--- a/sdks/unreal/examples/README.md
+++ b/sdks/unreal/examples/README.md
@@ -1,6 +1,6 @@
## Quickstart Chat Module Version
-This quickstart chat Client is built on from the [C# Module Quickstart](https://spacetimedb.com/docs/modules/c-sharp/quickstart). \
-If you have started with the [Rust Module Quickstart](https://spacetimedb.com/docs/modules/rust/quickstart) the reducer names will differ, send_message instead of SendMessage and set_name instead of SetName. /
+This quickstart chat Client is built on from the [C# Module Quickstart](https://spacetimedb.com/docs/quickstarts/c-sharp). \
+If you have started with the [Rust Module Quickstart](https://spacetimedb.com/docs/quickstarts/rust) the reducer names will differ, send_message instead of SendMessage and set_name instead of SetName. /
diff --git a/templates/angular-ts/README.md b/templates/angular-ts/README.md
index 2dcdcc7241c..91f59bf656a 100644
--- a/templates/angular-ts/README.md
+++ b/templates/angular-ts/README.md
@@ -114,4 +114,4 @@ spacetime logs
## Next steps
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/templates/astro-ts/README.md b/templates/astro-ts/README.md
index cc728b753a8..b22a7e237d4 100644
--- a/templates/astro-ts/README.md
+++ b/templates/astro-ts/README.md
@@ -133,5 +133,5 @@ spacetime logs
## Next steps
-- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/templates/basic-cs/README.md b/templates/basic-cs/README.md
index d693ce55ad2..34f1351bdd9 100644
--- a/templates/basic-cs/README.md
+++ b/templates/basic-cs/README.md
@@ -113,5 +113,5 @@ spacetime logs
## Next steps
-- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
-- Read the [C# SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/csharp-reference) for detailed API docs
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/tutorials/chat-app) for a complete example
+- Read the [C# SDK Reference](https://spacetimedb.com/docs/clients/c-sharp) for detailed API docs
diff --git a/templates/basic-cs/module_bindings/SpacetimeDBClient.g.cs b/templates/basic-cs/module_bindings/SpacetimeDBClient.g.cs
index 0ce09669c8d..8e3fc61ffa9 100644
--- a/templates/basic-cs/module_bindings/SpacetimeDBClient.g.cs
+++ b/templates/basic-cs/module_bindings/SpacetimeDBClient.g.cs
@@ -477,7 +477,7 @@ public TypedSubscriptionBuilder AddQuery(
/// Data from all the provided queries will be returned at the same time.
///
/// See the SpacetimeDB SQL docs for more information on SQL syntax:
- /// https://spacetimedb.com/docs/sql
+ /// https://spacetimedb.com/docs/reference/sql
///
public SubscriptionHandle Subscribe(
string[] querySqls
diff --git a/templates/basic-rs/README.md b/templates/basic-rs/README.md
index 083102976ec..86f0eb586ac 100644
--- a/templates/basic-rs/README.md
+++ b/templates/basic-rs/README.md
@@ -99,5 +99,5 @@ spacetime logs
## Next steps
-- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
-- Read the [Rust SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/rust-reference) for detailed API docs
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/tutorials/chat-app) for a complete example
+- Read the [Rust SDK Reference](https://spacetimedb.com/docs/clients/rust) for detailed API docs
diff --git a/templates/basic-ts/README.md b/templates/basic-ts/README.md
index a90b1813f62..1b468bfcb94 100644
--- a/templates/basic-ts/README.md
+++ b/templates/basic-ts/README.md
@@ -103,5 +103,5 @@ spacetime logs
## Next steps
-- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/templates/browser-ts/README.md b/templates/browser-ts/README.md
index 7e69847d072..8cb6e3511dc 100644
--- a/templates/browser-ts/README.md
+++ b/templates/browser-ts/README.md
@@ -102,5 +102,5 @@ conn.db.person.onDelete((ctx, person) => {
## Next steps
-- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/templates/bun-ts/README.md b/templates/bun-ts/README.md
index 21e5e33ef17..1cacad80bb1 100644
--- a/templates/bun-ts/README.md
+++ b/templates/bun-ts/README.md
@@ -228,5 +228,5 @@ bun run start
## Next steps
-- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/templates/chat-console-cs/module_bindings/SpacetimeDBClient.g.cs b/templates/chat-console-cs/module_bindings/SpacetimeDBClient.g.cs
index 1a2566ec9c7..a92813554c7 100644
--- a/templates/chat-console-cs/module_bindings/SpacetimeDBClient.g.cs
+++ b/templates/chat-console-cs/module_bindings/SpacetimeDBClient.g.cs
@@ -478,7 +478,7 @@ public TypedSubscriptionBuilder AddQuery(
/// Data from all the provided queries will be returned at the same time.
///
/// See the SpacetimeDB SQL docs for more information on SQL syntax:
- /// https://spacetimedb.com/docs/sql
+ /// https://spacetimedb.com/docs/reference/sql
///
public SubscriptionHandle Subscribe(
string[] querySqls
diff --git a/templates/chat-console-rs/README.md b/templates/chat-console-rs/README.md
index 13b4eed9b27..19a5fcb0bbd 100644
--- a/templates/chat-console-rs/README.md
+++ b/templates/chat-console-rs/README.md
@@ -2,4 +2,4 @@
A simple command-line client for [the `quickstart-chat` module](/modules/quickstart-chat).
-This client is described in-depth by [the SpacetimeDB Rust client quickstart](https://spacetimedb.com/docs/sdks/rust/quickstart).
+This client is described in-depth by [the SpacetimeDB Rust client quickstart](https://spacetimedb.com/docs/quickstarts/rust).
diff --git a/templates/chat-console-rs/spacetimedb/README.md b/templates/chat-console-rs/spacetimedb/README.md
index 33cefe667eb..833b1f8daac 100644
--- a/templates/chat-console-rs/spacetimedb/README.md
+++ b/templates/chat-console-rs/spacetimedb/README.md
@@ -1,7 +1,7 @@
# `quickstart-chat` *Rust* example
A SpacetimeDB module which defines a simple chat server. This module is explained in-depth
-by [the SpacetimeDB Rust module quickstart](https://spacetimedb.com/docs/modules/rust/quickstart).
+by [the SpacetimeDB Rust module quickstart](https://spacetimedb.com/docs/quickstarts/rust).
## Clients
@@ -9,16 +9,16 @@ by [the SpacetimeDB Rust module quickstart](https://spacetimedb.com/docs/modules
A Rust command-line client for this module is defined
in [the Rust SDK's examples](/crates/sdk/examples/quickstart-chat), and described
-by [the SpacetimeDB Rust SDK quickstart](https://spacetimedb.com/docs/sdks/rust/quickstart).
+by [the SpacetimeDB Rust SDK quickstart](https://spacetimedb.com/docs/quickstarts/rust).
### C#
A C# command-line client for this module is defined
in [the C# SDK's examples](https://github.com/clockworklabs/spacetimedb-csharp-sdk/tree/master/examples/quickstart/client),
-and described by [the SpacetimeDB C# SDK quickstart](https://spacetimedb.com/docs/sdks/csharp/quickstart).
+and described by [the SpacetimeDB C# SDK quickstart](https://spacetimedb.com/docs/quickstarts/c-sharp).
### TypeScript
A web client for this module, built with TypeScript and React, is defined
in [the TypeScript SDK's examples](https://github.com/clockworklabs/SpacetimeDB/tree/master/sdks/typescript/examples/quickstart-chat),
-and described by [the SpacetimeDB TypeScript SDK quickstart](https://spacetimedb.com/docs/sdks/typescript/quickstart).
+and described by [the SpacetimeDB TypeScript SDK quickstart](https://spacetimedb.com/docs/quickstarts/typescript).
diff --git a/templates/chat-react-ts/README.md b/templates/chat-react-ts/README.md
index 92a1c58637f..4731e68bc82 100644
--- a/templates/chat-react-ts/README.md
+++ b/templates/chat-react-ts/README.md
@@ -2,9 +2,9 @@
This is a simple chat application that demonstrates how to use SpacetimeDB with TypeScript and React. The chat application is a simple chat room where users can send messages to each other. The chat application uses SpacetimeDB to store the chat messages.
-It is based directly on the plain React + TypeScript + Vite template. You can follow the quickstart guide for how creating this project from scratch at [SpacetimeDB TypeScript Quickstart](https://spacetimedb.com/docs/sdks/typescript/quickstart).
+It is based directly on the plain React + TypeScript + Vite template. You can follow the quickstart guide for how creating this project from scratch at [SpacetimeDB TypeScript Quickstart](https://spacetimedb.com/docs/quickstarts/typescript).
-You can follow the instructions for creating your own SpacetimeDB module here: [SpacetimeDB Rust Module Quickstart](https://spacetimedb.com/docs/modules/rust/quickstart). Place the module in the `quickstart-chat/server` directory for compability with this project.
+You can follow the instructions for creating your own SpacetimeDB module here: [SpacetimeDB Rust Module Quickstart](https://spacetimedb.com/docs/quickstarts/rust). Place the module in the `quickstart-chat/server` directory for compability with this project.
In order to run this example, you need to:
diff --git a/templates/deno-ts/README.md b/templates/deno-ts/README.md
index 3b72e75af58..fb2d112296d 100644
--- a/templates/deno-ts/README.md
+++ b/templates/deno-ts/README.md
@@ -241,5 +241,5 @@ cat package.json
## Next steps
-- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/templates/hangman-react-ts/README.md b/templates/hangman-react-ts/README.md
index 14b48267aa3..87e30706eeb 100644
--- a/templates/hangman-react-ts/README.md
+++ b/templates/hangman-react-ts/README.md
@@ -114,5 +114,5 @@ The React UI in `src/App.tsx` includes the gallows drawing, masked-word board, k
## Next steps
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
-- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for another complete React example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/tutorials/chat-app) for another complete React example
diff --git a/templates/llm-chat-ts/README.md b/templates/llm-chat-ts/README.md
index 8be7edc1781..f6ec79e78eb 100644
--- a/templates/llm-chat-ts/README.md
+++ b/templates/llm-chat-ts/README.md
@@ -79,5 +79,5 @@ different host or database name.
## Next steps
-- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/templates/nextjs-ts/README.md b/templates/nextjs-ts/README.md
index 9fc4e60cca9..37c0e68e6ad 100644
--- a/templates/nextjs-ts/README.md
+++ b/templates/nextjs-ts/README.md
@@ -191,5 +191,5 @@ export function PersonList({ initialPeople }) {
## Next steps
-- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/templates/nodejs-ts/README.md b/templates/nodejs-ts/README.md
index 66a81387d26..4952881eab3 100644
--- a/templates/nodejs-ts/README.md
+++ b/templates/nodejs-ts/README.md
@@ -195,5 +195,5 @@ npm run start
## Next steps
-- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/templates/nuxt-ts/README.md b/templates/nuxt-ts/README.md
index 7df666f1010..bdebdf4dce6 100644
--- a/templates/nuxt-ts/README.md
+++ b/templates/nuxt-ts/README.md
@@ -224,4 +224,4 @@ const displayPeople = computed(() => {
## Next steps
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/templates/react-ts/README.md b/templates/react-ts/README.md
index 8db4516126e..df49c530075 100644
--- a/templates/react-ts/README.md
+++ b/templates/react-ts/README.md
@@ -112,5 +112,5 @@ spacetime logs
## Next steps
-- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/templates/remix-ts/README.md b/templates/remix-ts/README.md
index 7a5c0504866..d34f477fd4e 100644
--- a/templates/remix-ts/README.md
+++ b/templates/remix-ts/README.md
@@ -186,5 +186,5 @@ export default function Index() {
## Next steps
-- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/templates/solid-ts/README.md b/templates/solid-ts/README.md
index 386a51f1986..3f96dc8121a 100644
--- a/templates/solid-ts/README.md
+++ b/templates/solid-ts/README.md
@@ -111,4 +111,4 @@ spacetime logs
## Next steps
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/templates/svelte-ts/README.md b/templates/svelte-ts/README.md
index 3ef596dd66e..76e9a7188be 100644
--- a/templates/svelte-ts/README.md
+++ b/templates/svelte-ts/README.md
@@ -111,4 +111,4 @@ spacetime logs
## Next steps
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/templates/tanstack-ts/README.md b/templates/tanstack-ts/README.md
index 090e5bf244e..34a8cd5967e 100644
--- a/templates/tanstack-ts/README.md
+++ b/templates/tanstack-ts/README.md
@@ -140,5 +140,5 @@ function App() {
## Next steps
-- See the [Chat App Tutorial](https://spacetimedb.com/docs/intro/tutorials/chat-app) for a complete example
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- See the [Chat App Tutorial](https://spacetimedb.com/docs/tutorials/chat-app) for a complete example
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/templates/vue-ts/README.md b/templates/vue-ts/README.md
index 95e5b54e398..f546ab9e1da 100644
--- a/templates/vue-ts/README.md
+++ b/templates/vue-ts/README.md
@@ -111,4 +111,4 @@ spacetime logs
## Next steps
-- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/intro/core-concepts/clients/typescript-reference) for detailed API docs
+- Read the [TypeScript SDK Reference](https://spacetimedb.com/docs/clients/typescript) for detailed API docs
diff --git a/tools/templates/generate-template-readmes.ts b/tools/templates/generate-template-readmes.ts
index 9eacb14eef7..e7e6c6be85c 100644
--- a/tools/templates/generate-template-readmes.ts
+++ b/tools/templates/generate-template-readmes.ts
@@ -8,6 +8,7 @@
* Usage: pnpm run generate-readmes (from tools/templates/)
*/
+import { readFileSync } from 'node:fs';
import { readFile, readdir, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
@@ -108,13 +109,24 @@ function stripRemainingStepTags(content: string): string {
return out;
}
+/**
+ * The front-matter `slug` of a doc. Nearly every doc sets one, and when it
+ * does it replaces the folder-shaped path as the URL the page is served at.
+ */
+function frontMatterSlug(file: string): string | undefined {
+ const frontMatter = /^---\r?\n([\s\S]*?)\r?\n---/.exec(
+ readFileSync(file, 'utf-8')
+ )?.[1];
+ return /^slug:\s*['"]?(\/[^'"\s]*)['"]?\s*$/m.exec(frontMatter ?? '')?.[1];
+}
+
function rewriteDocLinks(
content: string,
quickstartDir: string,
docsRoot: string
): string {
return content.replace(
- /\[([^\]]+)\]\((\.\.\/)*(.+?\.md)(#[\w-]+)?\)/g,
+ /\[([^\]]+)\]\(((?:\.\.\/)*)(.+?\.md)(#[\w-]+)?\)/g,
(_, linkText, parentRefs, docPath, hash) => {
const relPath = (parentRefs || '') + docPath;
const resolved = path.resolve(quickstartDir, relPath);
@@ -122,11 +134,14 @@ function rewriteDocLinks(
.relative(docsRoot, resolved)
.replace(/\\/g, '/');
const withoutExt = relativeToDocs.replace(/\.md$/, '');
- const slug = withoutExt
- .split('/')
- .map(seg => seg.replace(/^\d+-/, ''))
- .join('/');
- const url = `${DOCS_BASE}/${slug}${hash || ''}`;
+ const route =
+ frontMatterSlug(resolved) ??
+ '/' +
+ withoutExt
+ .split('/')
+ .map(seg => seg.replace(/^\d+-/, ''))
+ .join('/');
+ const url = `${DOCS_BASE}${route}${hash || ''}`;
return `[${linkText}](${url})`;
}
);