Skip to content

Commit c3fccc6

Browse files
committed
chore(docs): migrate hosting from Netlify to Cloudflare Pages
Switch the Nitro preset to cloudflare_pages and move all legacy 301 redirects into public/_redirects using Cloudflare's native :splat syntax (dropping the Netlify-only '!' force suffix and the '**' placeholders Nitro emits for routeRule redirects, which Cloudflare Pages cannot parse). Port the immutable asset cache-control headers into public/_headers and pin Node 22 via .nvmrc for reproducible Cloudflare builds.
1 parent c7e0f21 commit c3fccc6

4 files changed

Lines changed: 38 additions & 22 deletions

File tree

docs-v3/.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
22

docs-v3/nuxt.config.ts

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -127,32 +127,23 @@ export default defineNuxtConfig({
127127
}
128128
},
129129

130-
// 301 redirects from the legacy docs-v2 URL structure to the new /docs/* paths.
131-
// Removes the duplicate soft-404 pages Ahrefs flagged and preserves old backlinks.
132-
// Note: bare exact-match legacy paths (/quickstart, /repositories, /search) are
133-
// handled via public/_redirects with forced (301!) rules. Exact-match redirect
134-
// routeRules get prerendered as meta-refresh stub HTML files, which Netlify then
135-
// serves with a 200 (shadowing the redirect) — so they must NOT live here.
136-
routeRules: {
137-
'/api/**': { redirect: { to: '/docs/api/**', statusCode: 301 } },
138-
'/auth/**': { redirect: { to: '/docs/auth/**', statusCode: 301 } },
139-
'/search/**': { redirect: { to: '/docs/search/**', statusCode: 301 } },
140-
'/graphql/**': { redirect: { to: '/docs/graphql/**', statusCode: 301 } },
141-
'/mcp/**': { redirect: { to: '/docs/mcp/**', statusCode: 301 } },
142-
'/performance/**': { redirect: { to: '/docs/performance/**', statusCode: 301 } },
143-
'/boost/**': { redirect: { to: '/docs/boost/**', statusCode: 301 } },
144-
'/testing/**': { redirect: { to: '/docs/testing/**', statusCode: 301 } }
145-
},
130+
// 301 redirects from the legacy docs-v2 URL structure to the new /docs/* paths
131+
// (preserves old backlinks and removes the duplicate soft-404 pages Ahrefs flagged)
132+
// live in public/_redirects, authored in Cloudflare Pages' native syntax (:splat,
133+
// no forced-'!' suffix). They are intentionally NOT expressed as Nuxt routeRules:
134+
// Nitro emits routeRule redirects into _redirects using '**' placeholders, which
135+
// Cloudflare Pages does not understand, and exact-match rules would additionally be
136+
// prerendered as meta-refresh stub HTML that shadows the redirect with a 200.
146137

147138
// TypeScript configuration
148139
typescript: {
149140
typeCheck: false
150141
},
151142

152-
// Static site generation for Netlify
143+
// Static site generation for Cloudflare Pages
153144
ssr: true,
154145
nitro: {
155-
preset: 'netlify-static',
146+
preset: 'cloudflare_pages',
156147
prerender: {
157148
failOnError: false,
158149
crawlLinks: true,

docs-v3/public/_headers

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Long-lived immutable caching for hashed build assets.
2+
# Ported from the previous Netlify config; Cloudflare Pages uses the same _headers format.
3+
/_nuxt/builds/meta/*
4+
cache-control: public, max-age=31536000, immutable
5+
/_nuxt/builds/*
6+
cache-control: public, max-age=1, immutable
7+
/_fonts/*
8+
cache-control: public, max-age=31536000, immutable
9+
/_nuxt/*
10+
cache-control: public, max-age=31536000, immutable

docs-v3/public/_redirects

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
1-
# Forced 301s for legacy docs-v2 bare paths (override any static file / SPA fallback)
2-
/quickstart /docs/getting-started/quickstart 301!
3-
/repositories /docs/api/repositories 301!
4-
/search /docs/search/basic-filters 301!
1+
# Legacy docs-v2 URL structure -> new /docs/* paths. 301 to preserve backlinks/SEO.
2+
# Cloudflare Pages _redirects: '*' greedily captures the tail, placed back via ':splat'.
3+
# First matching rule wins, so exact-match rules must precede their wildcard counterparts.
4+
5+
# Bare exact-match legacy paths
6+
/quickstart /docs/getting-started/quickstart 301
7+
/repositories /docs/api/repositories 301
8+
/search /docs/search/basic-filters 301
9+
10+
# Wildcard section redirects
11+
/api/* /docs/api/:splat 301
12+
/auth/* /docs/auth/:splat 301
13+
/search/* /docs/search/:splat 301
14+
/graphql/* /docs/graphql/:splat 301
15+
/mcp/* /docs/mcp/:splat 301
16+
/performance/* /docs/performance/:splat 301
17+
/boost/* /docs/boost/:splat 301
18+
/testing/* /docs/testing/:splat 301

0 commit comments

Comments
 (0)