Fix a stale tutorial link in the feature flags tutorials list - #20045
Conversation
Vercel matches redirect sources literally, so the browser redirects for /tutorials/node-external-cache and /tutorials/evaluation-runtimes-and-environments do not cover the Gatsby page-data.json paths. Those two page-data URLs return 404. Add a page-data redirect next to each browser redirect. Generated-By: PostHog Desktop Task-Id: cb742882-d196-4ebc-ac88-22b5f42511bf
🦔 PostHog Review reviewed this pull requestFound 1 must fix, 0 should fix, 1 consider. Published 2 findings (view the review). Resolved comments: 1 fixed, 1 left for you |
Deploy preview
|
Bundle reportTotal JS (gzip)8.86 MiB (+0.0 KiB / +0.0%) Eager graph (modules shipped in each entrypoint's initial chunks)
Largest modules in the
|
| Module | Size |
|---|---|
./src/data/mcp-tools.json |
1119.8 KiB |
css ./node_modules/.pnpm/css-loader@5.2.7_webpack@5.101.3/node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[8].oneOf[1].use[1]!./node_modules/.pnpm/postcss-loader@4.3.0_postcss@8.5.6_webpack@5.101.3/node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[8].oneOf[1].use[2]!./src/styles/global.css |
761.0 KiB |
./src/components/Stickers/Stickers.tsx |
696.4 KiB |
./node_modules/.pnpm/@radix-ui+react-icons@1.3.2_react@18.3.1/node_modules/@radix-ui/react-icons/dist/react-icons.esm.js |
481.4 KiB |
./node_modules/.pnpm/@posthog+brand@0.8.0_react@18.3.1/node_modules/@posthog/brand/dist/generated/hoggies/svg/x-ray.mjs |
480.8 KiB |
./node_modules/.pnpm/rehype-raw@7.0.0/node_modules/rehype-raw/lib/index.js + 29 modules |
395.1 KiB |
./node_modules/.pnpm/@posthog+brand@0.8.0_react@18.3.1/node_modules/@posthog/brand/dist/generated/hoggies/svg/im-the-driver.mjs |
385.7 KiB |
./src/hooks/useCustomers.tsx + 55 modules |
370.0 KiB |
./node_modules/.pnpm/@posthog+icons@0.36.6_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
354.8 KiB |
./node_modules/.pnpm/react-markdown@8.0.7_@types+react@16.14.66_react@18.3.1/node_modules/react-markdown/lib/react-markdown.js + 88 modules |
351.4 KiB |
./src/components/ProductComparisonTable/index.tsx + 126 modules |
302.5 KiB |
./node_modules/.pnpm/cloudinary-core@2.14.0_lodash@4.17.21/node_modules/cloudinary-core/cloudinary-core.js |
281.9 KiB |
./node_modules/.pnpm/@posthog+brand@0.8.0_react@18.3.1/node_modules/@posthog/brand/dist/generated/hoggies/svg/doll-house.mjs |
281.7 KiB |
./node_modules/.pnpm/@posthog+brand@0.8.0_react@18.3.1/node_modules/@posthog/brand/dist/generated/hoggies/svg/director.mjs |
275.6 KiB |
./src/components/SearchUI/index.tsx + 87 modules |
273.7 KiB |
Eager-graph budgets are report-only until a baseline is established. Sizes are gzip of public/**/*.js; eager size is webpack module source bytes for the modules actually shipped in the entrypoint's initial chunks (post-tree-shake).
|
PostHog Review alpha 🦔 If you find any issues helpful - please reply "valid", "invalid", etc., for evaluation purposes 🙏 |
| { | ||
| "source": "/page-data/tutorials/evaluation-runtimes-and-environments/page-data.json", | ||
| "destination": "/page-data/tutorials/evaluation-runtimes-and-contexts/page-data.json" | ||
| }, |
There was a problem hiding this comment.
Page-data redirects bypass Gatsby's client redirect flow
Why we think it's a valid issue
- Checked: Gatsby 4.25.9 (
package.json:112) client runtime —cache-dir/loader.js,cache-dir/navigation.js,cache-dir/root.js— plus@gatsbyjs/reach-router1.3.9 route matching, and searched the whole repo forcreateRedirect/redirectInBrowser. - Found:
loader.js:167-186accepts any page-data body that parses and has apathfield. It makes no comparison betweenjsonPayload.pathand the requestedpagePath, so the destination document is stored under the old path. - Found:
toPageResources(loader.js:63-77) copiespath: pageData.path, androot.js:44-56gives the single<Router>route that path whilelocationstays on the old path.pickfinds no route and reach-router returnsnull(es/index.js:285). The page body is empty. This confirms the empty-page mechanism. - Found: the present 404 is not only prefetch noise. It starts an escape hatch:
loader.js:199-201refetches/404.htmlwithnotFound: true, thenProdLoader.loadPageDataJson(loader.js:871-891) sends a HEAD request to the page URL. That request follows the existing 308 and returns 200, so the loader reportsPageResourceStatus.Error, andnavigation.js:93-98doeswindow.location = pathname. The full page load then follows the browser redirect and lands the user on the destination,?tab=Node.jsincluded. The new page-data rules remove the 404, sonotFoundis never set and this path never runs. - Found: no
createRedirectorredirectInBrowsercall exists anywhere in the repo, somaybeGetBrowserRedirect(navigation.js:12-22) holds no entry for either old path. Nothing else corrects the URL client side. - Impact: for in-app navigation to
/tutorials/node-external-cacheand/tutorials/evaluation-runtimes-and-environments, the change turns a correct (if noisy) redirect into a blank page at the old URL, and the Node reader never reaches the?tab=Node.jsdestination. Direct requests and crawlers are unaffected, because the browser redirects are unchanged. Removing the two page-data rules restores today's behavior;createRedirectwithredirectInBrowser: trueis the mechanism that makes client navigation follow the redirect without a full load.
Issue description
Gatsby follows each new 308 redirect and receives the destination page-data document. That document contains the destination path. However, Gatsby still navigates to the old URL because Vercel redirects do not populate Gatsby's client redirect map. Reach Router then finds no matching route and can render an empty page. The Node redirect also loses its ?tab=Node.js destination.
Suggested fix
Register these URL pairs with Gatsby's actions.createRedirect and set redirectInBrowser: true. Keep the Vercel URL redirects for direct requests, but remove the page-data redirects. Test each old link through client-side navigation in a preview.
Prompt to fix with AI (copy-paste)
## Context
@vercel.json#L2736-2739
@vercel.json#L5105-5108
<issue_description>
Gatsby follows each new 308 redirect and receives the destination page-data document. That document contains the destination path. However, Gatsby still navigates to the old URL because Vercel redirects do not populate Gatsby's client redirect map. Reach Router then finds no matching route and can render an empty page. The Node redirect also loses its `?tab=Node.js` destination.
</issue_description>
<issue_validation>
- **Checked:** Gatsby 4.25.9 (`package.json:112`) client runtime — `cache-dir/loader.js`, `cache-dir/navigation.js`, `cache-dir/root.js` — plus `@gatsbyjs/reach-router` 1.3.9 route matching, and searched the whole repo for `createRedirect` / `redirectInBrowser`.
- **Found:** `loader.js:167-186` accepts any page-data body that parses and has a `path` field. It makes no comparison between `jsonPayload.path` and the requested `pagePath`, so the destination document is stored under the old path.
- **Found:** `toPageResources` (`loader.js:63-77`) copies `path: pageData.path`, and `root.js:44-56` gives the single `<Router>` route that path while `location` stays on the old path. `pick` finds no route and reach-router returns `null` (`es/index.js:285`). The page body is empty. This confirms the empty-page mechanism.
- **Found:** the present 404 is not only prefetch noise. It starts an escape hatch: `loader.js:199-201` refetches `/404.html` with `notFound: true`, then `ProdLoader.loadPageDataJson` (`loader.js:871-891`) sends a HEAD request to the page URL. That request follows the existing 308 and returns 200, so the loader reports `PageResourceStatus.Error`, and `navigation.js:93-98` does `window.location = pathname`. The full page load then follows the browser redirect and lands the user on the destination, `?tab=Node.js` included. The new page-data rules remove the 404, so `notFound` is never set and this path never runs.
- **Found:** no `createRedirect` or `redirectInBrowser` call exists anywhere in the repo, so `maybeGetBrowserRedirect` (`navigation.js:12-22`) holds no entry for either old path. Nothing else corrects the URL client side.
- **Impact:** for in-app navigation to `/tutorials/node-external-cache` and `/tutorials/evaluation-runtimes-and-environments`, the change turns a correct (if noisy) redirect into a blank page at the old URL, and the Node reader never reaches the `?tab=Node.js` destination. Direct requests and crawlers are unaffected, because the browser redirects are unchanged. Removing the two page-data rules restores today's behavior; `createRedirect` with `redirectInBrowser: true` is the mechanism that makes client navigation follow the redirect without a full load.
</issue_validation>
## Task
Investigate the issue and solve it
<potential_solution>
Register these URL pairs with Gatsby's `actions.createRedirect` and set `redirectInBrowser: true`. Keep the Vercel URL redirects for direct requests, but remove the page-data redirects. Test each old link through client-side navigation in a preview.
</potential_solution>
There was a problem hiding this comment.
You are right, and I verified the mechanism against the real Gatsby 4.25.9 client runtime rather than reasoning about it. Every step holds:
- The page-data fetch accepts any 200 response that parses and carries a
pathfield. It never compares that path to the path that was requested, so the destination's document gets cached under the old URL. - The router is then given one route, whose path comes from the loaded document (the destination), while the browser location stays on the old URL. Nothing matches, and the page renders empty. The client 404 page does not appear either, because the load counted as a success.
- Today's 404 is load-bearing, exactly as you say. It sets
notFound, which makes the loader send a HEAD request to the page URL. The existing browser redirect answers 200, the loader reports an error, and the router falls back to a full page load. That full load follows the browser redirect and lands the reader on the destination,?tab=Node.jsincluded.
So this PR does trade a noisy but correct redirect for a blank page on in-app navigation. I am not landing a fix unattended, and I am leaving this for a human, because both ways forward are decisions rather than mechanical changes:
- Register the pairs with Gatsby's
createRedirectandredirectInBrowser, and drop the page-data rules. This repo has no such registration anywhere. All of the roughly 1500 redirects are hand-maintained invercel.json, and the Gatsby build contains no redirect code at all. This would add a second, build-time source of redirects, which the repo's own contributor guide puts behind an explicit ask-first rule for build-pipeline changes. It also emits a document at the old path, which then sits alongside the existing browser redirect for that same path. Both effects are visible only on a deployed preview, and this checkout has no installed dependencies and no test that covers redirect behavior, so I cannot prove it here. - Drop the two page-data rules and close the PR. This restores today's confirmed-correct behavior, but it reverts the whole change and leaves the reported page-data 404s in place.
What a human needs to decide: whether the prefetch noise is worth introducing a build-time client redirect mechanism to this site, or whether the full page load is an acceptable cost and this PR should simply be closed. Either way, please do not merge it as it stands — it is still a draft, and the two rules as committed cause the empty page you describe.
The docs index linked to /tutorials/evaluation-runtimes-and-tags, a redirect source, so in-app navigation from that link took a full page load through the redirect. Point it at the live page and match the page's own title, which the tags-to-contexts rename changed. Generated-By: PostHog Desktop Task-Id: e90c3adf-0286-421f-9929-d393f61398d6
|
Vale prose linter → found 3 errors, 36 warnings, 0 suggestions in your markdown Full report → Copy the linter results into an LLM to batch-fix issues. Linter being weird? Update the rules!
|
| Line | Severity | Message | Rule |
|---|---|---|---|
| 9:27 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 10:25 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 11:36 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 16:45 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 18:31 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 19:25 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 23:132 | error | Hi, Andy here... use an en dash ( – ) with spaces. On Mac, holding down the Option and hyphen key will give you an en dash. | PostHogBase.EnDash |
| 24:75 | error | Hi, Andy here... use an en dash ( – ) with spaces. On Mac, holding down the Option and hyphen key will give you an en dash. | PostHogBase.EnDash |
| 25:19 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 25:91 | error | Hi, Andy here... use an en dash ( – ) with spaces. On Mac, holding down the Option and hyphen key will give you an en dash. | PostHogBase.EnDash |
| 27:15 | warning | Capitalize 'Experiments' for PostHog's product. Use 'experiments' for the general industry concept. | PostHogBase.ProductNames |
| 27:32 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 38:26 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 40:26 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 41:24 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 42:25 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 43:25 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 44:26 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 46:26 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 47:22 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 49:39 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 50:41 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 51:36 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 52:23 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 53:22 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 54:38 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 56:24 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 57:32 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 58:25 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 59:22 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 60:21 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 61:25 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 62:47 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 63:21 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 67:18 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 71:30 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 75:4 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'Feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 79:20 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
| 80:16 | warning | Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. | PostHogBase.ProductNames |
The page-data JSON redirects are not the cause of the 404s, so drop them and keep only the stale in-repo tutorial link fix. Generated-By: PostHog Desktop Task-Id: cab6b9cc-92fb-4c63-988b-5fb87a846413
Changes
Why
The stale-tutorial report pointed at
/page-data/**/page-data.json404s, but those are Gatsby prefetch noise, not the user-facing problem: the browser redirects already send readers to the correct page. The real defect is an in-repo link that points at a tutorial path which no longer exists.Fix
contents/docs/feature-flags/tutorials.mdxlinked to/tutorials/evaluation-runtimes-and-tags. That page is now/tutorials/evaluation-runtimes-and-contexts. The link and its text now match the tutorial's current title, so the reader goes straight to the page instead of through a redirect.vercel.jsonis unchanged. The page-data redirects that this PR first proposed are removed.On
/tutorials/node-external-cacheThat path appears nowhere in
contents/orsrc/. Its only occurrence in the repository is the existing redirect source invercel.json, which already sends readers to/docs/feature-flags/local-evaluation/distributed-environments. There is no in-repo link to fix.Checklist
vercel.jsonCreated with PostHog Desktop from this inbox report.