Skip to content

docs: redirect legacy cube.dev/docs URLs to new docs.cube.dev#11002

Merged
keydunov merged 1 commit into
masterfrom
docs/old-to-new-redirects
Jun 3, 2026
Merged

docs: redirect legacy cube.dev/docs URLs to new docs.cube.dev#11002
keydunov merged 1 commit into
masterfrom
docs/old-to-new-redirects

Conversation

@keydunov
Copy link
Copy Markdown
Member

@keydunov keydunov commented Jun 3, 2026

What

Sets up server-side 301 redirects from the old docs (cube.dev/docs) to the new Mintlify docs (docs.cube.dev).

The old Next.js/Nextra site stays deployed and issues cross-domain redirects so every legacy URL — and the many inbound links/SEO pointing at it — keeps resolving to the right page in the new docs.

Changes

  • docs-mintlify/scripts/build_old_site_redirects.py — generator that reuses the existing PATH_REWRITES mapping (single source of truth, shared with rewrite_links.py/migrate_redirects.py) to produce the cross-domain redirect table from the old redirects.json. Re-runnable whenever the mapping or redirects.json changes.
  • docs/redirects-new-docs.json — generated table of 509 redirects, first-match-wins order:
    • 455 specific page redirects (every legacy redirects.json entry, destination rewritten to the new structure) so consolidated/renamed pages reach their exact new home, e.g. /product/administration/workspace/saved-reportshttps://docs.cube.dev/admin/workspace.
    • 54 wildcard prefix redirects (/product/configuration/:path*…/docs/configuration/:path*, etc.) plus a /product/:path* catch-all for pages that never needed an explicit redirect.
  • docs/next.config.mjs — imports the new table and points root / at https://docs.cube.dev/docs/introduction.

Reviewer notes

  • basePath: false is intentionally omitted. Verified against the installed Next.js 16.1.6 (load-custom-routes.js): a redirect source gets the /docs basePath prefix unless basePath: false is set, while absolute https:// destinations are detected as external and never get basePath prepended. Omitting it makes sources match legacy /docs/... URLs while keeping cross-domain destinations intact. All 510 entries pass Next's own checkCustomRoutes validator.
  • External passthroughs preserved: two legacy redirects to cube.dev/blog/... are left untouched (not rewritten to docs.cube.dev) — intentional.
  • Deployment dependency: this relies on cube.dev/docs continuing to point at this old Vercel deployment so it can serve the redirects. Please confirm the old app stays live before/after the new docs cut over.

🤖 Generated with Claude Code

The new Mintlify docs are served at docs.cube.dev. The old Next.js/Nextra
site at cube.dev/docs now issues cross-domain 301s to it so legacy URLs and
inbound links keep resolving.

- Add build_old_site_redirects.py generator that reuses the existing
  PATH_REWRITES mapping to produce the cross-domain redirect table from
  the old redirects.json (specific page redirects first, then wildcard
  prefix redirects + a /product catch-all).
- Generate redirects-new-docs.json (509 redirects).
- Wire it into next.config.mjs and point root / at the new introduction.

basePath: false is intentionally omitted so sources still match under the
/docs basePath while absolute destinations stay external (verified against
Next.js load-custom-routes and checkCustomRoutes).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mintlify
Copy link
Copy Markdown
Contributor

mintlify Bot commented Jun 3, 2026

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
cubed3 🟢 Ready View Preview Jun 3, 2026, 2:14 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@github-actions github-actions Bot added docs Issues that require a documentation improvement javascript Pull requests that update Javascript code python labels Jun 3, 2026
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Jun 3, 2026

Claude finished @keydunov's task in 2m 27s —— View job


Claude Code Review

Verdict: looks solid — 0 high, 2 medium, 3 low/nits

Tasks

  • Read changed files
  • Inspect rewrite_links.PATH_REWRITES reuse
  • Validate generated redirects-new-docs.json (509 entries, no dup sources)
  • Verify specific-vs-wildcard ordering and dedup
  • Post review

Summary

The approach is clean: reuse PATH_REWRITES as a single source of truth, emit specific-first / wildcard-last, dedupe by source. Verified the generated table:

  • 509 entries, zero duplicate sources (uniq -d empty).
  • 455 specifics from redirects.json + 54 wildcards (one exact + one :path* per PATH_REWRITES entry + /product catch-all).
  • 2 external passthroughs to cube.dev/blog/... preserved (intentional, per PR body).
  • Specifics correctly win over wildcards — e.g. /product/administration/sso/okta keeps its consolidated …/saml destination instead of being grabbed by the SSO wildcard.

Medium

  1. basePath is environment-conditionaldocs/next.config.mjs:21 reads basePath: process.env.BASE_PATH || ''. Sources in redirects-new-docs.json are written as /product/... (no /docs prefix), so they only match legacy cube.dev/docs/product/... URLs when BASE_PATH=/docs is set at deploy time. Worth verifying that the Vercel project for the old site sets BASE_PATH=/docs (otherwise the redirects silently won't match in production). The reviewer note explains the absolute-destination interaction with basePath, but doesn't mention this prerequisite.

  2. No catch-all for non-/product legacy roots — Old top-level URLs like /guides/..., /cohort-retention, /cube, /active-users etc. are present in redirects.json as specifics and carried forward, but there's no wildcard fallback for those prefixes. If a legacy /docs/guides/<page-not-in-redirects.json> URL is hit (or any of the ~30 non-/product/ top-level paths I spotted), it'll fall through to 404 on the old site rather than 301 to new docs. May be intentional (those pages never existed), but a deliberate /guides/:path*/api-reference/recipes/:path* or similar fallback would be cheap insurance for the SEO-inbound case.

Low / nits

  1. build_old_site_redirects.py:88-91 — the /product exact + /product/:path* catch-all is appended after iterating PATH_REWRITES. Since PATH_REWRITES doesn't include a /product mapping, this is fine, but the dedup loop will silently drop them if a /product entry ever appears in PATH_REWRITES later — worth a one-line comment to make that ordering invariant explicit.

  2. build_old_site_redirects.py:55-62r.get("source", "") and r.get("destination", "") will produce a redirect with empty source: "" if the input is malformed. Cheap to add an assert source and destination so a bad redirects.json fails loud instead of emitting a garbage entry. Not a real risk today since the input is generated, but a small guard.

  3. Generator output is checked into docs/redirects-new-docs.json (2547 lines). Consider a one-line Makefile target or npm script (yarn build:redirects) so reviewers don't need to remember the exact python build_old_site_redirects.py ... invocation when the source mapping changes. Optional.

Notes / praise

  • The seen dedup pattern at build_old_site_redirects.py:126-132 is the right call — it makes specific-first / wildcard-last self-correcting even if both layers reference the same path.
  • Module-level docstring is genuinely useful — explains the basePath: false decision and the two-layer model in one place.
  • Reusing PATH_REWRITES from rewrite_links.py instead of forking the mapping is the right architectural choice.
• [`docs/old-to-new-redirects`](https://github.com/cube-js/cube/tree/docs/old-to-new-redirects)

@keydunov keydunov merged commit 96ba2d5 into master Jun 3, 2026
14 checks passed
@keydunov keydunov deleted the docs/old-to-new-redirects branch June 3, 2026 02:16
keydunov added a commit that referenced this pull request Jun 3, 2026
The cross-domain redirect table (#11002) sent most legacy cube.dev/docs
URLs to non-existent docs.cube.dev pages — 386 of 509 destinations (76%)
returned 404, e.g. /product/data-modeling/reference/pre-aggregations went
to the dead /docs/data-modeling/reference/pre-aggregations instead of the
real /reference/data-modeling/pre-aggregations.

Root cause: build_old_site_redirects.py reused rewrite_links.PATH_REWRITES,
which describes an intermediate migration layout (/access-security,
/api-reference, /analytics tabs and /docs/data-modeling/reference/...) that
never shipped. Content was consolidated into the live tabs (admin, reference,
docs, recipes, embedding, configuration, cube-core).

Rewrite the generator to be content-driven and self-validating:
- Derive each destination by matching the old page's body text against the
  live Mintlify pages (new files were copied from old ones during migration,
  so prose is preserved). 319 old pages mapped.
- Pin ambiguous/consolidated/removed pages in an explicit OVERRIDES table,
  verified by hand against the real tree.
- Emit a redirect for every legacy alias and every canonical /product page,
  plus a /product/:path* catch-all so nothing 404s.
- Validate every destination against the on-disk Mintlify tree and exit
  non-zero if any would 404, so a broken table can't be committed silently.

Regenerated redirects-new-docs.json (509 -> 774 entries, all validated).
All 455 original alias sources remain covered. Live-checked the reported
pre-aggregations page (now 200, was 404) plus a 30-destination sample (all 200).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Issues that require a documentation improvement javascript Pull requests that update Javascript code python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant