Skip to content

Commit 0088f8b

Browse files
lbliiiclaude
andauthored
docs(fern): fix redirects so Sphinx URLs actually resolve (#1310)
## Summary - All 11 unique `docs.nvidia.com/nemo/gym/*.html` links from `README.md` were returning **404** with no redirect on the production Fern preview (`https://nvidia-gym.docs.buildwithfern.com/`). - Root cause: with `experimental.basepath-aware: true`, Fern requires the full `/nemo/gym/` basepath with a leading slash on **both** source and destination of every redirect rule (verified by comparing to nemo-curator's working `docs.yml`). Our block had two systematic issues: 1. Legacy Sphinx sources omitted the leading slash (`nemo/gym/foo.html`) → never matched. 2. Most destinations omitted the basepath (`/latest/foo`) → matched but emitted a `Location` outside the basepath, still 404. - Mirrors nemo-curator's pattern, and adds 3 explicit redirects for pages renamed during the Fern migration: `unsloth-training` → `unsloth`, `apidocs` → `api/reference/api-reference`, `creating-training-environment` → `single-step-environment`. ## Test plan - [x] Local trace of all 11 README URLs through the new rule table — every URL resolves to a canonical Fern path. - [x] Spot-checked the resolved canonicals against the live preview — 10/11 are 200. (`training-tutorials/verl` is a stale-deploy issue, separate from redirects.) - [ ] **Post-merge**: redeploy and run `curl -sI <old-url>` against each old Sphinx URL; expect `308` + a `Location:` header pointing at the canonical Fern path. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Lawrence Lane <llane@nvidia.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 5c10941 commit 0088f8b

1 file changed

Lines changed: 104 additions & 82 deletions

File tree

fern/docs.yml

Lines changed: 104 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -76,89 +76,111 @@ versions:
7676
availability: stable
7777

7878
redirects:
79-
# Generated by utils/generate_redirects.py — re-run from repo root; see scripts README
80-
- source: "nemo/gym/index.html"
81-
destination: "/main"
82-
- source: "nemo/gym/index"
83-
destination: "/main"
84-
- source: "nemo/gym/about/concepts/configuration-system.html"
85-
destination: "/about/concepts/configuration"
86-
- source: "nemo/gym/about/concepts/core-abstractions.html"
87-
destination: "/about/core-components"
88-
- source: "nemo/gym/get-started/setup-installation.html"
89-
destination: "/get-started/installation"
90-
- source: "/latest/get-started/detailed-setup"
91-
destination: "/latest/get-started/quickstart"
92-
- source: "/latest/get-started/rollout-collection"
93-
destination: "/latest/get-started/quickstart"
94-
- source: "nemo/gym/how-to-faq.html"
95-
destination: "/reference/faq"
96-
- source: "nemo/gym/infrastructure/aiohttp-vs-httpx.html"
97-
destination: "/infrastructure/engineering-notes/aiohttp-vs-httpx"
98-
- source: "nemo/gym/infrastructure/swe-rl-case-study.html"
99-
destination: "/infrastructure/engineering-notes/swe-rl-case-study"
100-
- source: "nemo/gym/training/rl-framework-integration/generation-backend-and-openai-compatible-http-server.html"
101-
destination: "/contribute/rl-framework-integration/generation-backend-and-openai-compatible-http-server"
102-
- source: "nemo/gym/training/rl-framework-integration/gym-integration-footprint-and-form-factor.html"
103-
destination: "/contribute/rl-framework-integration/gym-integration-footprint-and-form-factor"
104-
- source: "nemo/gym/training/rl-framework-integration/gym-rl-framework-integration-success-criteria.html"
105-
destination: "/contribute/rl-framework-integration/gym-rl-framework-integration-success-criteria"
106-
- source: "nemo/gym/training/rl-framework-integration/index.html"
107-
destination: "/contribute/rl-framework-integration"
108-
- source: "nemo/gym/training/rl-framework-integration/integration-footprint.html"
109-
destination: "/contribute/rl-framework-integration/gym-integration-footprint-and-form-factor"
110-
- source: "nemo/gym/training/rl-framework-integration/on-policy-corrections.html"
111-
destination: "/contribute/rl-framework-integration/openai-compatible-http-server-on-policy-correction"
112-
- source: "nemo/gym/training/rl-framework-integration/openai-compatible-http-server-on-policy-correction.html"
113-
destination: "/contribute/rl-framework-integration/openai-compatible-http-server-on-policy-correction"
114-
- source: "nemo/gym/tutorials/creating-resource-server.html"
115-
destination: "/environment-tutorials/single-step-environment"
116-
- source: "nemo/gym/tutorials/index.html"
117-
destination: "/training-tutorials"
118-
- source: "nemo/gym/tutorials/nemo-rl-grpo/about-workplace-assistant.html"
119-
destination: "/training-tutorials/nemo-rl-grpo/about-workplace-assistant"
120-
- source: "nemo/gym/tutorials/nemo-rl-grpo/gym-configuration.html"
121-
destination: "/training-tutorials/nemo-rl-grpo/gym-configuration"
122-
- source: "nemo/gym/tutorials/nemo-rl-grpo/index.html"
123-
destination: "/training-tutorials/nemo-rl-grpo"
124-
- source: "nemo/gym/tutorials/nemo-rl-grpo/multi-node-training.html"
125-
destination: "/training-tutorials/nemo-rl-grpo/multi-node-training"
126-
- source: "nemo/gym/tutorials/nemo-rl-grpo/nemo-rl-configuration.html"
127-
destination: "/training-tutorials/nemo-rl-grpo/nemo-rl-configuration"
128-
- source: "nemo/gym/tutorials/nemo-rl-grpo/setup.html"
129-
destination: "/training-tutorials/nemo-rl-grpo/setup"
130-
- source: "nemo/gym/tutorials/nemo-rl-grpo/single-node-training.html"
131-
destination: "/training-tutorials/nemo-rl-grpo/single-node-training"
132-
- source: "nemo/gym/tutorials/offline-training-w-rollouts.html"
133-
destination: "/training-tutorials/offline-training-w-rollouts"
134-
- source: "/latest/about/concepts/core-components"
135-
destination: "/latest/about/core-components"
136-
- source: "/latest/about/concepts/architecture"
137-
destination: "/latest/infrastructure/engineering-notes/system-design"
138-
- source: "/latest/about/concepts/task-verification"
139-
destination: "/latest/resources-server"
140-
- source: "/latest/about/concepts/configuration"
141-
destination: "/latest/reference/configuration"
142-
- source: "/latest/environment-tutorials/designing-customer-evaluation"
143-
destination: "/latest/environment-tutorials"
144-
- source: "/v0.2.1/environment-tutorials/real-world-data-generation"
145-
destination: "/v0.2.1/environment-tutorials/real-world-environment/generating-training-data"
146-
- source: "/v0.2.1/environment-tutorials/real-world-implementation"
147-
destination: "/v0.2.1/environment-tutorials/real-world-environment/resources-server-implementation"
148-
- source: "/latest/environment-tutorials/real-world-data-generation"
149-
destination: "/latest/environment-tutorials/real-world-environment/generating-training-data"
150-
- source: "/latest/environment-tutorials/real-world-implementation"
151-
destination: "/latest/environment-tutorials/real-world-environment/resources-server-implementation"
152-
- source: "/v0.2/:path*"
153-
destination: "/v0.2.1/:path*"
154-
- source: "nemo/gym/latest/:path*/index.html"
79+
# With `experimental.basepath-aware: true`, both source and destination must include
80+
# the full `/nemo/gym/` basepath with a leading slash. See nemo-curator's docs.yml.
81+
# Legacy Sphinx top-level entry points (Main is now the default version)
82+
- source: "/nemo/gym/index.html"
83+
destination: "/nemo/gym/main"
84+
- source: "/nemo/gym/index"
85+
destination: "/nemo/gym/main"
86+
# Legacy Sphinx page paths → current Fern slugs
87+
- source: "/nemo/gym/about/concepts/configuration-system.html"
88+
destination: "/nemo/gym/about/concepts/configuration"
89+
- source: "/nemo/gym/about/concepts/core-abstractions.html"
90+
destination: "/nemo/gym/about/core-components"
91+
- source: "/nemo/gym/get-started/setup-installation.html"
92+
destination: "/nemo/gym/get-started/installation"
93+
- source: "/nemo/gym/how-to-faq.html"
94+
destination: "/nemo/gym/reference/faq"
95+
- source: "/nemo/gym/infrastructure/aiohttp-vs-httpx.html"
96+
destination: "/nemo/gym/infrastructure/engineering-notes/aiohttp-vs-httpx"
97+
- source: "/nemo/gym/infrastructure/swe-rl-case-study.html"
98+
destination: "/nemo/gym/infrastructure/engineering-notes/swe-rl-case-study"
99+
- source: "/nemo/gym/training/rl-framework-integration/generation-backend-and-openai-compatible-http-server.html"
100+
destination: "/nemo/gym/contribute/rl-framework-integration/generation-backend-and-openai-compatible-http-server"
101+
- source: "/nemo/gym/training/rl-framework-integration/gym-integration-footprint-and-form-factor.html"
102+
destination: "/nemo/gym/contribute/rl-framework-integration/gym-integration-footprint-and-form-factor"
103+
- source: "/nemo/gym/training/rl-framework-integration/gym-rl-framework-integration-success-criteria.html"
104+
destination: "/nemo/gym/contribute/rl-framework-integration/gym-rl-framework-integration-success-criteria"
105+
- source: "/nemo/gym/training/rl-framework-integration/index.html"
106+
destination: "/nemo/gym/contribute/rl-framework-integration"
107+
- source: "/nemo/gym/training/rl-framework-integration/integration-footprint.html"
108+
destination: "/nemo/gym/contribute/rl-framework-integration/gym-integration-footprint-and-form-factor"
109+
- source: "/nemo/gym/training/rl-framework-integration/on-policy-corrections.html"
110+
destination: "/nemo/gym/contribute/rl-framework-integration/openai-compatible-http-server-on-policy-correction"
111+
- source: "/nemo/gym/training/rl-framework-integration/openai-compatible-http-server-on-policy-correction.html"
112+
destination: "/nemo/gym/contribute/rl-framework-integration/openai-compatible-http-server-on-policy-correction"
113+
- source: "/nemo/gym/tutorials/creating-resource-server.html"
114+
destination: "/nemo/gym/environment-tutorials/single-step-environment"
115+
- source: "/nemo/gym/tutorials/index.html"
116+
destination: "/nemo/gym/training-tutorials"
117+
- source: "/nemo/gym/tutorials/nemo-rl-grpo/about-workplace-assistant.html"
118+
destination: "/nemo/gym/training-tutorials/nemo-rl-grpo/about-workplace-assistant"
119+
- source: "/nemo/gym/tutorials/nemo-rl-grpo/gym-configuration.html"
120+
destination: "/nemo/gym/training-tutorials/nemo-rl-grpo/gym-configuration"
121+
- source: "/nemo/gym/tutorials/nemo-rl-grpo/index.html"
122+
destination: "/nemo/gym/training-tutorials/nemo-rl-grpo"
123+
- source: "/nemo/gym/tutorials/nemo-rl-grpo/multi-node-training.html"
124+
destination: "/nemo/gym/training-tutorials/nemo-rl-grpo/multi-node-training"
125+
- source: "/nemo/gym/tutorials/nemo-rl-grpo/nemo-rl-configuration.html"
126+
destination: "/nemo/gym/training-tutorials/nemo-rl-grpo/nemo-rl-configuration"
127+
- source: "/nemo/gym/tutorials/nemo-rl-grpo/setup.html"
128+
destination: "/nemo/gym/training-tutorials/nemo-rl-grpo/setup"
129+
- source: "/nemo/gym/tutorials/nemo-rl-grpo/single-node-training.html"
130+
destination: "/nemo/gym/training-tutorials/nemo-rl-grpo/single-node-training"
131+
- source: "/nemo/gym/tutorials/offline-training-w-rollouts.html"
132+
destination: "/nemo/gym/training-tutorials/offline-training-w-rollouts"
133+
# Renamed/moved pages within the Fern site
134+
- source: "/nemo/gym/latest/get-started/detailed-setup"
135+
destination: "/nemo/gym/latest/get-started/quickstart"
136+
- source: "/nemo/gym/latest/get-started/rollout-collection"
137+
destination: "/nemo/gym/latest/get-started/quickstart"
138+
- source: "/nemo/gym/latest/about/concepts/core-components"
139+
destination: "/nemo/gym/latest/about/core-components"
140+
- source: "/nemo/gym/latest/about/concepts/architecture"
141+
destination: "/nemo/gym/latest/infrastructure/engineering-notes/system-design"
142+
- source: "/nemo/gym/latest/about/concepts/task-verification"
143+
destination: "/nemo/gym/latest/resources-server"
144+
- source: "/nemo/gym/latest/about/concepts/configuration"
145+
destination: "/nemo/gym/latest/reference/configuration"
146+
- source: "/nemo/gym/latest/about/concepts/training-approaches"
147+
destination: "/nemo/gym/latest/about/concepts/training"
148+
- source: "/nemo/gym/latest/environment-tutorials/designing-customer-evaluation"
149+
destination: "/nemo/gym/latest/environment-tutorials"
150+
- source: "/nemo/gym/v0.2.1/environment-tutorials/real-world-data-generation"
151+
destination: "/nemo/gym/v0.2.1/environment-tutorials/real-world-environment/generating-training-data"
152+
- source: "/nemo/gym/v0.2.1/environment-tutorials/real-world-implementation"
153+
destination: "/nemo/gym/v0.2.1/environment-tutorials/real-world-environment/resources-server-implementation"
154+
- source: "/nemo/gym/latest/environment-tutorials/real-world-data-generation"
155+
destination: "/nemo/gym/latest/environment-tutorials/real-world-environment/generating-training-data"
156+
- source: "/nemo/gym/latest/environment-tutorials/real-world-implementation"
157+
destination: "/nemo/gym/latest/environment-tutorials/real-world-environment/resources-server-implementation"
158+
# Version alias: v0.2 → v0.2.1
159+
- source: "/nemo/gym/v0.2"
160+
destination: "/nemo/gym/v0.2.1"
161+
- source: "/nemo/gym/v0.2/:path*"
162+
destination: "/nemo/gym/v0.2.1/:path*"
163+
# README/blog links that pointed to Sphinx pages whose canonical was renamed in Fern
164+
- source: "/nemo/gym/latest/training-tutorials/unsloth-training"
165+
destination: "/nemo/gym/latest/training-tutorials/unsloth"
166+
- source: "/nemo/gym/latest/apidocs"
167+
destination: "/nemo/gym/api/reference/api-reference"
168+
- source: "/nemo/gym/latest/environment-tutorials/creating-training-environment"
169+
destination: "/nemo/gym/latest/environment-tutorials/single-step-environment"
170+
# Version-root index.html: explicit because :path* does not match the empty-path case
171+
- source: "/nemo/gym/latest/index.html"
172+
destination: "/nemo/gym/latest"
173+
- source: "/nemo/gym/v0.2.1/index.html"
174+
destination: "/nemo/gym/v0.2.1"
175+
- source: "/nemo/gym/main/index.html"
176+
destination: "/nemo/gym/main"
177+
# Catch-all: Sphinx `.../index.html` → Fern canonical (must precede `.html` catch-all)
178+
- source: "/nemo/gym/latest/:path*/index.html"
155179
destination: "/nemo/gym/latest/:path*"
156-
- source: "nemo/gym/v0.2.1/:path*/index.html"
180+
- source: "/nemo/gym/v0.2.1/:path*/index.html"
157181
destination: "/nemo/gym/v0.2.1/:path*"
158-
- source: "nemo/gym/:path*/index.html"
182+
- source: "/nemo/gym/:path*/index.html"
159183
destination: "/nemo/gym/:path*"
160-
- source: "/latest/about/concepts/training-approaches"
161-
destination: "/latest/about/concepts/training"
162-
# Legacy page URLs (foo.html); must follow all :path*/index.html rules above
163-
- source: "nemo/gym/:path*.html"
184+
# Catch-all: Sphinx `foo.html` → Fern canonical `foo`
185+
- source: "/nemo/gym/:path*.html"
164186
destination: "/nemo/gym/:path*"

0 commit comments

Comments
 (0)