Repository navigation
Expand file tree
/
Copy pathredirects.mjs
More file actions
502 lines (482 loc) · 23.3 KB
/
Copy pathredirects.mjs
File metadata and controls
502 lines (482 loc) · 23.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
// Single source of truth for SEO redirects.
//
// Imported by `astro.config.mjs` (so the dev server and the static HTML
// fallback pages stay in sync) and by `scripts/generate-caddy-redirects.mjs`
// (which emits real HTTP 301s at the Caddy layer for production).
//
// Keys and values are path-only (no origin) for internal redirects. Internal
// targets should end in `/` to match the site's canonical trailing-slash form
// and avoid a second redirect hop.
//
// Absolute targets are supported but restricted to explicitly allowed hosts,
// so a bad entry can never point traffic at an arbitrary domain. See
// `EXTERNAL_REDIRECT_HOSTS` below and the matching check in
// `scripts/generate-caddy-redirects.mjs`.
import { existsSync, readdirSync } from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const explicitRedirects = {
// Public community short link. Keep this slashless in authored links, while
// Caddy serves both variants so copied URLs cannot fall through to a 404.
'/discord': 'https://discord.gg/rivet-developer-network-822914074136018994',
// The agentOS 0.4 launch post moved from its draft date to its launch date.
'/changelog/2026-10-06-introducing-agentos-0-4-and-hosted-vms': '/changelog/2026-10-12-introducing-agentos-0-4-and-hosted-vms/',
// Integrations moved out of the documentation URL hierarchy.
'/docs/integrations/vercel-workflow': '/integrations/workflow-sdk/',
'/integrations/vercel-workflow': '/integrations/workflow-sdk/',
// The docs overview briefly lived under `/orchestrate/`; it is back at `/docs/`.
'/orchestrate/docs': '/docs/',
'/orchestrate': '/docs/',
// The self-host overview became the Deploy section root.
'/docs/deploy/self-host': '/docs/deploy/',
// The Pi Durable page merged into the Pi page when `pi()` became the Pi
// Durable agent.
'/agents/docs/pi-durable': '/agents/docs/pi/',
// The Instructions page became the System Prompt page.
'/agents/docs/instructions': '/agents/docs/system-prompt/',
// Product marketing pages folded into each product's docs overview.
'/actors': '/actors/docs/',
'/workflows': '/workflows/docs/',
'/dynamic-apps': '/dynamic-apps/docs/',
// The Tutorials tab became Learn.
'/actors/tutorials': '/guides/',
'/agentos/tutorials': '/agentos/docs/',
'/dynamic-apps/tutorials': '/dynamic-apps/docs/',
'/workflows/tutorials': '/workflows/docs/',
// Cookbook became the Actors Learn tab.
'/cookbook': '/guides/',
'/cookbook/ai-agent': '/guides/ai-agent/',
'/cookbook/chat-room': '/guides/chat-room/',
'/cookbook/collaborative-text-editor': '/guides/collaborative-text-editor/',
'/cookbook/cron-jobs': '/guides/cron-jobs/',
'/cookbook/live-cursors': '/guides/live-cursors/',
'/cookbook/multiplayer-game': '/guides/multiplayer-game/',
'/cookbook/per-tenant-database': '/guides/per-tenant-database/',
// Documentation restructure
'/docs/setup': '/actors/docs/',
// The docs overview absorbed the product-agnostic quickstart chooser, and
// Troubleshooting moved out of the Actors bundle because it covers control
// plane statuses rather than the SDK.
'/docs/quickstart': '/docs/',
'/actors/docs/troubleshooting': '/docs/troubleshooting/',
// The container runner and its Containers, Unity, and Godot integration
// pages were removed.
'/docs/container-runner': '/integrations/',
'/integrations/containers': '/integrations/',
'/integrations/unity': '/integrations/',
'/integrations/godot': '/integrations/',
// Endpoints was rewritten as the shorter Connect page; Runtime Modes folded
// into Workers & Pools.
'/docs/endpoints': '/docs/connect/',
'/docs/runtime-modes': '/docs/workers/',
// Dead links inside dated changelog posts. Neither target ever existed, so
// these point at the nearest real page rather than being rewritten in the
// posts, which are historical records.
'/docs/actors/ai-and-user-generated-actors': '/agentos/docs/',
'/integrations/better-auth': '/integrations/',
'/docs/deploy/cli': '/actors/docs/cli/',
'/docs/actors/queue': '/actors/docs/queues/',
'/docs/actors/websockets': '/actors/docs/websocket-handler/',
'/docs/actors/http': '/docs/api/',
// The HTTP API moved from the Actors docs to the site-wide API tab.
'/actors/docs/http-api': '/docs/api/',
'/docs/actors/run': '/actors/docs/lifecycle/',
'/docs/actors/scheduling': '/actors/docs/schedule/',
'/docs/actors/external-sql': '/actors/docs/state/',
'/docs/actors/raw-sql': '/actors/docs/sqlite/',
// Empty moved-page stubs were retired. Preserve both their current product
// URLs and legacy flat-docs spellings as one-hop redirects.
'/actors/docs/helper-types': '/actors/docs/types/',
'/docs/actors/helper-types': '/actors/docs/types/',
'/actors/docs/scaling': '/actors/docs/design-patterns/',
'/docs/actors/scaling': '/actors/docs/design-patterns/',
'/actors/docs/sharing-and-joining-state': '/actors/docs/design-patterns/',
'/docs/actors/sharing-and-joining-state': '/actors/docs/design-patterns/',
// Access Control merged into Permissions when the Authentication section
// split credentials (Overview, JWTs, ACL) from in-Actor authorization.
'/actors/docs/access-control': '/actors/docs/permissions/',
'/docs/actors/access-control': '/actors/docs/permissions/',
// Credential docs are platform-wide, so they live in the General bundle
// rather than the Actors one.
'/actors/docs/authentication': '/docs/authentication/',
'/docs/actors/authentication': '/docs/authentication/',
'/actors/docs/jwt': '/docs/jwt/',
'/docs/actors/ephemeral-variables': '/actors/docs/state/',
'/docs/actors/persistence': '/actors/docs/state/',
'/docs/actors/postgres': '/actors/docs/state/',
// Platform docs moved to clients/connect
'/docs/platforms/react': '/actors/docs/clients/react/',
'/docs/platforms/next-js': '/actors/docs/clients/javascript/',
// Registry configuration moved
'/docs/connect/registry-configuration': '/actors/docs/general/registry-configuration/',
// Quickstart index merged into the Actors introduction
'/docs/actors/quickstart': '/actors/docs/',
// Connect tab renamed to Deploy. The bare `/docs/connect` URL is now the
// Connect page in docs/general, so only the platform sub-pages redirect.
'/docs/connect/aws-ecs': '/docs/deploy/self-host/workers/',
'/docs/connect/aws-lambda': '/docs/deploy/self-host/workers/',
'/docs/connect/cloudflare': '/docs/deploy/self-host/workers/',
'/docs/connect/custom': '/docs/deploy/self-host/workers/',
'/docs/connect/freestyle': '/docs/deploy/self-host/workers/',
'/docs/connect/gcp-cloud-run': '/docs/deploy/self-host/workers/',
'/docs/connect/hetzner': '/docs/deploy/self-host/workers/',
'/docs/connect/kubernetes': '/docs/deploy/self-host/workers/',
'/docs/connect/railway': '/docs/deploy/self-host/workers/',
'/docs/connect/rivet-compute': '/docs/deploy/self-host/workers/',
'/docs/connect/supabase': '/docs/deploy/self-host/workers/',
'/docs/connect/vercel': '/docs/deploy/self-host/workers/',
'/docs/connect/vm-and-bare-metal': '/docs/deploy/self-host/workers/',
// Cloud docs removed - redirect to relevant sections
'/docs/cloud': '/docs/deploy/',
'/docs/cloud/api/actors/create': '/actors/docs/',
'/docs/cloud/api/routes/update': '/actors/docs/',
'/docs/cloud/self-hosting/single-container': '/docs/deploy/self-host/control-plane/',
// Next.js client redirect (linked from homepage)
'/docs/clients/next-js': '/actors/docs/clients/javascript/',
// Self-hosting redirect
'/docs/general/self-hosting': '/docs/deploy/self-host/control-plane/',
// Removed solution pages. `/actors/` itself now redirects to the docs, so
// land there directly rather than chaining.
'/agent': '/actors/docs/',
'/solutions/agents': '/',
'/solutions/app-generators': '/',
'/solutions/collaborative-state': '/',
'/solutions/game-servers': '/',
'/solutions/games': '/',
'/solutions/geo-distributed-db': '/',
'/solutions/per-tenant-db': '/',
'/solutions/user-session-store': '/',
'/solutions/workflows': '/',
// Changelog list view merged into the blog index
'/changelog': '/blog/',
// agentOS briefly lived at https://agentos-sdk.dev and is now a product
// vertical on this site, so these land on `/agentos/*` rather than off-site.
'/agent-os': '/agentos/',
'/agent-os/pricing': '/pricing/',
'/agent-os/use-cases': '/guides/',
'/agent-os/registry': '/agentos/docs/registry/',
// agentOS dropped its own tab bar: the Registry is a section of its docs
// (old entry pages collapse onto it via the wildcard below), and the Use Cases page
// was retired for the site-wide Guides.
'/agentos/registry': '/agentos/docs/registry/',
'/agentos/use-cases': '/guides/',
// The integrations pages live at the site root now. These are not covered
// by legacyDocsRedirects because they moved tab, not just prefix.
'/docs/integrations': '/integrations/',
'/docs/integrations/flue': '/integrations/flue/',
'/docs/integrations/vercel-eve': '/integrations/vercel-eve/',
'/docs/integrations/vercel-workflows': '/integrations/workflow-sdk/',
// The Vercel Workflows page is named after the SDK it integrates with.
'/actors/integrations/vercel-workflows': '/integrations/workflow-sdk/',
'/integrations/vercel-workflows': '/integrations/workflow-sdk/',
// `/contact` was never a page here; `/sales` itself now redirects, so land
// directly on the live destination to avoid a 301 chain.
'/contact': '/talk-to-an-engineer/',
// The Rivet Cloud marketing page became the pricing page. Its docs moved
// into the Deploy section; those redirects are derived from the bundle's
// content tree in `cloudDocsRedirects()` below.
'/cloud': '/pricing/',
// Retired pages. These were live URLs, so they redirect rather than 404.
'/meme/wired-in': '/',
// The Open-Source Friends page was retired. It had no equivalent and was
// part of a reciprocal-linking network, so preserve inbound links to home.
'/oss-friends': '/',
// Deployment folded into the shared Self-Host section.
'/agentos/docs/deployment': '/docs/deploy/',
// Bindings were renamed to host functions.
'/agentos/docs/bindings': '/agentos/docs/host-functions/',
// Air-gapped deployment is a self-hosting topic, not an actors cookbook.
'/guides/vpc-air-gapped': '/docs/deploy/self-host/control-plane/vm/',
'/cookbook/vpc-air-gapped': '/docs/deploy/self-host/control-plane/vm/',
// Rivet Compute is a Cloud feature, not a self-hosting target.
'/docs/deploy/rivet-compute': '/docs/deploy/cloud/compute/',
'/docs/deploy/freestyle': '/docs/deploy/self-host/workers/freestyle/',
'/docs/deploy/hetzner': '/docs/deploy/self-host/workers/vm/',
'/docs/self-hosting/render': '/docs/deploy/self-host/control-plane/render/',
// Comparison slugs name the product, not the company.
'/compare/rivet-vs-cloudflare-durable-objects':
'/actors/compare/rivet-actors-vs-cloudflare-durable-objects/',
'/compare/rivet-vs-temporal': '/workflows/compare/rivet-workflows-vs-temporal/',
'/actors/compare/rivet-vs-cloudflare-durable-objects':
'/actors/compare/rivet-actors-vs-cloudflare-durable-objects/',
'/workflows/compare/rivet-vs-temporal':
'/workflows/compare/rivet-workflows-vs-temporal/',
// The generated TypeDoc site and the hand-maintained config schema were
// retired; the Actors reference docs are the closest live destination.
'/typedoc': '/actors/docs/',
'/rivet.schema.json': '/actors/docs/',
// The standalone "Actors course" is now a guide in the Actors Learn tab.
'/learn': '/guides/',
'/learn/act-1/scene-1-a-radically-simpler-architecture':
'/guides/a-radically-simpler-architecture/',
'/docs/tools/actors': '/actors/docs/',
// The "append .md to any docs URL" feature was documented but never built.
// Its docs page and the hand-written markdown exports are both gone.
'/docs/general/docs-for-llms': '/actors/docs/general/skill/',
'/actors/docs/general/docs-for-llms': '/actors/docs/general/skill/',
'/install': '/agentos/docs/quickstart/',
// The "From Unix to Agents" essay has no page on this site; the product
// overview is the closest surviving destination.
'/from-unix-to-agents': '/agentos/',
'/docs/agent-os': '/agentos/docs/',
// The agentOS workspace cookbook was never rewritten; land on its docs.
'/cookbook/ai-agent-workspace': '/agentos/docs/',
// Workflows became its own product vertical. The legacy `/docs/actors/...`
// entry is spelled out here because `legacyDocsRedirects()` derives from the
// Actors content tree, which no longer has the page.
'/actors/docs/workflows': '/workflows/docs/',
'/docs/actors/workflows': '/workflows/docs/',
// Dynamic Apps became its own product vertical. The page was a single
// agentOS doc and is now a whole docs section, so every legacy spelling of
// the old URL lands on the section overview.
'/agentos/docs/apps': '/dynamic-apps/docs/',
'/docs/agent-os/apps': '/dynamic-apps/docs/',
'/agent-os/docs/apps': '/dynamic-apps/docs/',
// The standalone sales page folds into the talk-to-an-engineer flow.
'/sales': '/talk-to-an-engineer/',
};
// Every docs page moved out of the flat `/docs/...` hierarchy when the site
// split into per-product verticals (`/actors/docs/...`). The legacy map is
// derived from the content tree rather than hand-maintained, so it cannot drift
// as pages are added or renamed. Explicit entries above win on collision.
// This module lives at the repository root, but it is also bundled into the
// site build (`RerootLinks.astro` reads the map), where `import.meta.url` is a
// chunk under `dist/`. Walk up from wherever we are to the checkout that holds
// `src/content` so both callers resolve the same directory.
const CONTENT_ROOT = (() => {
let dir = path.dirname(fileURLToPath(import.meta.url));
for (;;) {
const candidate = path.join(dir, 'src/content');
if (existsSync(candidate)) return candidate;
const parent = path.dirname(dir);
if (parent === dir) throw new Error('redirects.mjs: cannot locate src/content');
dir = parent;
}
})();
function mdxSlugs(dir) {
const slugs = [];
const walk = (current, prefix) => {
for (const entry of readdirSync(current, { withFileTypes: true })) {
const next = prefix ? `${prefix}/${entry.name}` : entry.name;
if (entry.isDirectory()) {
walk(path.join(current, entry.name), next);
} else if (entry.name.endsWith('.mdx')) {
const slug = next.replace(/\.mdx$/, '').replace(/(^|\/)index$/, '');
slugs.push(slug.replace(/\/$/, ''));
}
}
};
walk(dir, '');
return slugs;
}
function legacyDocsRedirects() {
const map = {};
// Actors documentation: `/docs/actors/state` -> `/actors/docs/state`, and the
// former docs-root sections (`clients`, `general`, `cli`) moved underneath it.
for (const slug of mdxSlugs(path.join(CONTENT_ROOT, 'docs/actors/docs'))) {
const target = slug ? `/actors/docs/${slug}/` : '/actors/docs/';
const movedFromDocsRoot =
slug === 'cli' || slug.startsWith('clients/') || slug.startsWith('general/');
const legacy = movedFromDocsRoot
? `/docs/${slug}`
: slug
? `/docs/actors/${slug}`
: '/docs/actors';
map[legacy] = target;
}
// The old Deploy and Self-Hosting sections merged into the Deploy
// section: app deployment became `workers`, running Rivet yourself became
// `control-plane`. Pages land on the matching group overview until each
// guide is rewritten. `/docs/deploy` itself is a real page again (the
// Deploy overview), so only the Self-Hosting root gets a redirect.
const SECTION_TARGETS = {
deploy: '/docs/deploy/self-host/workers/',
'self-hosting': '/docs/deploy/self-host/control-plane/',
};
for (const [section, target] of Object.entries(SECTION_TARGETS)) {
if (section !== 'deploy') map[`/docs/${section}`] = target;
for (const slug of mdxSlugs(path.join(CONTENT_ROOT, `_pending-rewrite/${section}`))) {
if (!slug) continue;
map[`/docs/${section}/${slug}`] = target;
}
}
return map;
}
// The Rivet Cloud bundle (`cloud/docs/content`) used to be served at
// `/cloud/docs/...` and `/cloud/byoc/...`, then briefly at
// `/orchestrate/deploy/...`; it now renders inside the Deploy section at
// `/docs/deploy/...`. Mirrors `deployRouteSlugForContentId` in
// `src/sitemap/deploy.ts`, which this plain `.mjs` module cannot import.
function cloudDocsRedirects() {
const map = {};
const SECTIONS = { docs: 'cloud', byoc: 'byoc' };
for (const [section, segment] of Object.entries(SECTIONS)) {
for (const slug of mdxSlugs(path.join(CONTENT_ROOT, `docs/cloud/${section}`))) {
const target = slug ? `/docs/deploy/${segment}/${slug}/` : `/docs/deploy/${segment}/`;
map[slug ? `/cloud/${section}/${slug}` : `/cloud/${section}`] = target;
map[slug ? `/orchestrate/deploy/${segment}/${slug}` : `/orchestrate/deploy/${segment}`] = target;
}
}
return map;
}
// The Self-Host guides were served once per product (`/actors/self-host/...`,
// `/workflows/self-host/...`, ...) before collapsing into the single copy at
// `/docs/deploy/self-host/...`.
function selfHostRedirects() {
const map = {};
const PRODUCTS = ['actors', 'workflows', 'dynamic-apps', 'agentos'];
for (const slug of mdxSlugs(path.join(CONTENT_ROOT, 'self-host'))) {
const target = slug ? `/docs/deploy/self-host/${slug}/` : '/docs/deploy/';
for (const product of PRODUCTS) {
map[slug ? `/${product}/self-host/${slug}` : `/${product}/self-host`] = target;
}
}
return map;
}
// The Actors bundle's guides rendered at `/actors/learn/...` before they moved
// to the site-wide Guides tab at `/guides/...`. Guides from other bundles never
// had another URL.
function guidesRedirects() {
const map = {};
for (const slug of mdxSlugs(path.join(CONTENT_ROOT, 'docs/actors/guides'))) {
map[slug ? `/actors/learn/${slug}` : '/actors/learn'] = slug ? `/guides/${slug}/` : '/guides/';
}
return map;
}
// The Actors bundle's `integrations` section rendered at
// `/actors/integrations/...` before it became the site-wide Integrations tab
// at `/integrations/...`. Every page keeps its slug.
function integrationsRedirects() {
const map = {};
for (const slug of mdxSlugs(path.join(CONTENT_ROOT, 'docs/integrations/docs'))) {
map[slug ? `/actors/integrations/${slug}` : '/actors/integrations'] = slug
? `/integrations/${slug}/`
: '/integrations/';
}
return map;
}
// The Actors bundle was split into three: Actors, the product-agnostic docs at
// `/docs/`, and Integrations. Two things moved at once, so both are mapped here.
//
// - Twelve pages about running workloads rather than writing actors left the
// Actors vertical for `/docs/`.
// - The bundle's `general/` subdirectory was flattened away, so every page
// that stayed lost that path segment.
//
// The old `/docs/general/<page>` spellings are covered too: those URLs predate
// the per-product split and `legacyDocsRedirects` used to map them into
// `/actors/docs/general/`, which no longer exists.
function bundleSplitRedirects() {
// Old slug under `/actors/docs/` -> new path.
const MOVED = {
cli: '/docs/cli/',
'container-runner': '/integrations/',
statuses: '/docs/statuses/',
versions: '/docs/versions/',
'general/edge': '/docs/regions/',
'general/endpoints': '/docs/connect/',
'general/environment-variables': '/docs/environment-variables/',
'general/pool-configuration': '/docs/pool-configuration/',
'general/runtime-modes': '/docs/workers/',
'general/skill': '/docs/skill/',
'general/tracing': '/docs/tracing/',
};
// Pages that stayed in the Actors bundle but lost the `general/` segment.
const FLATTENED = [
'actor-configuration',
'cors',
'http-server',
'logging',
'production-checklist',
'registry-configuration',
'wasm-vs-native-sdk',
];
const map = {};
for (const [slug, target] of Object.entries(MOVED)) {
map[`/actors/docs/${slug}`] = target;
// Only the `general/`-prefixed legacy spellings get a `/docs/` entry. A
// flat one such as `/docs/cli` is now the destination itself, and mapping
// it would be a self-redirect.
if (slug.includes('/')) map[`/docs/${slug}`] = target;
}
for (const slug of FLATTENED) {
map[`/actors/docs/general/${slug}`] = `/actors/docs/${slug}/`;
map[`/docs/general/${slug}`] = `/actors/docs/${slug}/`;
}
// `debugging` split in two, keeping both URLs live: the management and runner
// APIs at `/docs/debugging`, the actor inspector at `/actors/docs/debugging`.
// Neither needs a redirect.
//
// Retired pages.
map['/actors/docs/fetch-and-websocket-handler'] = '/actors/docs/websocket-handler/';
map['/docs/actors/fetch-and-websocket-handler'] = '/actors/docs/websocket-handler/';
map['/actors/use-cases'] = '/actors/docs/';
map['/actors/learn/a-radically-simpler-architecture'] =
'/guides/a-radically-simpler-architecture/';
return map;
}
// agentOS's integrations were a tab of their own at `/agentos/integrations/...`
// before moving inside its docs at `/agentos/docs/integrations/...`. Every page
// keeps its slug. Mirrors `productIntegrationsSlugForContentId` in
// `src/sitemap/integrations.ts`.
function agentosIntegrationsRedirects() {
const map = {};
for (const slug of mdxSlugs(path.join(CONTENT_ROOT, 'docs/agentos/integrations'))) {
map[slug ? `/agentos/integrations/${slug}` : '/agentos/integrations'] = slug
? `/agentos/docs/integrations/${slug}/`
: '/agentos/docs/integrations/';
}
return map;
}
export const redirects = {
...legacyDocsRedirects(),
...bundleSplitRedirects(),
...cloudDocsRedirects(),
...selfHostRedirects(),
...guidesRedirects(),
...integrationsRedirects(),
...agentosIntegrationsRedirects(),
...explicitRedirects,
};
// External hosts that wildcard and absolute-URL redirect targets are restricted
// to. Used by both the Astro config and the Caddy generator so neither consumer
// can accidentally emit a redirect to an arbitrary host.
export const EXTERNAL_REDIRECT_HOSTS = ['agentos-sdk.dev', 'discord.gg'];
// Wildcard (prefix) redirects. Any request under `from` (at any depth) is sent
// to `to`.
//
// When `to` ends with `from`, the rule is a pure re-parenting and the request's
// suffix is carried through: `/agent-os/docs` -> `/agentos/docs`. Otherwise
// the suffix is dropped and every sub-path collapses onto `to`, which is what
// the old marketing paths need since they have no 1:1 mapping.
//
export const wildcardRedirects = [
// The old per-entry registry pages are now sections of the Registry's group
// pages; every old entry URL lands on the Registry overview.
{ from: '/agentos/registry', to: '/agentos/docs/registry' },
// Deep TypeDoc URLs are heavily linked from old docs and search results.
{ from: '/typedoc', to: '/actors/docs' },
{ from: '/learn', to: '/guides' },
{ from: '/compare', to: '/actors/compare' },
{ from: '/docs/agent-os', to: '/agentos/docs' },
{ from: '/agent-os', to: '/agentos' },
// Unknown deep paths under the old Rivet Cloud docs collapse onto the new
// section roots; every real page has an explicit entry above.
{ from: '/cloud/docs', to: '/docs/deploy/cloud' },
{ from: '/cloud/byoc', to: '/docs/deploy/byoc' },
// Same for the retired `/orchestrate/` namespace and the per-product
// Self-Host and Learn tabs. Real pages have explicit entries above; anything
// else lands on the section root.
{ from: '/orchestrate/docs', to: '/docs' },
{ from: '/orchestrate/deploy', to: '/docs/deploy' },
{ from: '/orchestrate', to: '/docs' },
{ from: '/actors/learn', to: '/guides' },
// Integrations briefly lived under the Actors vertical; they are a
// site-wide section at the root now. Real pages have explicit entries above
// (`integrationsRedirects`); unknown deep paths land on the section root.
{ from: '/actors/integrations', to: '/integrations' },
{ from: '/actors/self-host', to: '/docs/deploy' },
{ from: '/workflows/self-host', to: '/docs/deploy' },
{ from: '/dynamic-apps/self-host', to: '/docs/deploy' },
{ from: '/agentos/self-host', to: '/docs/deploy' },
];