Neaptide canonical experiment — 4 October 2026 Question Which configured metadata values change the emitted canonical host or path? Design Eight predefined cases in protocol.json; one unchanged control and seven deliberately incorrect configurations. Each case has before/after routes. The before and after fixtures coexist in one production build, so the runtime and dependencies are identical. Each pair changes one metadata setting. Environment Next.js 15.5.22, React and React DOM 19.2.6, Node.js v25.2.1, App Router. Static metadata exports. Local next build / next start, not a Vercel deployment. Build environment: LAB_CANONICAL_ORIGIN=https://preview.example.com Telemetry disabled with NEXT_TELEMETRY_DISABLED=1. Observed evidence 32 ordinary HTTP GET responses: 16 URLs, two collection passes. All responses returned 200 and exactly one canonical element in head. Both HTTP passes agreed. The rendered DOM on all 16 routes agreed with HTTP. One initial configuration matched its declared intended URL (the control). All eight after configurations matched; the control was unchanged. The seven initial mismatches were deliberately introduced, not discovered in a survey. These numbers are not prevalence, ranking or improvement rates. URL convention /cXX/before and /cXX/after are fixture namespaces, not intended public product paths. All canonical targets use reserved example.com demonstration domains. The target URL is declared per case in protocol.json. No request is made to those example domains. The fixture itself carries noindex, nofollow. Reproduction from the downloadable archive 1. Use the recorded Node version if reproducing the original environment. 2. cd fixture 3. npm install 4. LAB_CANONICAL_ORIGIN=https://preview.example.com NEXT_TELEMETRY_DISABLED=1 npm run build 5. npm run start -- -p 8780 -H 127.0.0.1 6. In another terminal, from the archive root: python3 collect.py http://127.0.0.1:8780 7. Open http://127.0.0.1:8780 and inspect the 16 linked pages. In browser developer tools, compare link[rel="canonical"] in the rendered document with the response HTML. Record any difference, including where it appears. The archive pins direct framework versions. Its package.json is not a complete lock of every transitive dependency; record your installed versions and any result differences. The original fixture-hashes.json identifies source files. collect.py writes new observations and analysis in the extracted directory; the original results are included separately in the archive under original/. The collector does not automate browser checks: those are a separate step. Scope and limitations No Search Console, authentic Googlebot requests, Google-selected canonical, rankings, traffic, conversions or live client incidents were measured. No claim covers other Next.js versions, Pages Router, dynamic/streamed metadata, middleware, a CDN rewriting HTML, or hosting-platform behavior. Repeated reads are not independent sites or statistical replication. Browser inspection and collection were performed by the same researcher. Pre-analysis build repair The first fixture build stopped on a navigation lint rule. Its index links were changed from a elements to Next.js Link. This did not change the frozen metadata cases. The subsequent build passed before observations were taken. Supplementary reproduction — 13 October 2026 The October 4 fixture was identified by SHA-256 source hashes, not a Git commit. For this additional run, its identical archived sources were committed as c9508dec9a9ea38c015d1718475bb4558898bc4c before building and collecting. All 32 HTTP canonical observations and all 16 browser DOM canonical checks matched the original measurements. This does not revise the original study date. The archive includes reproduction-2026-10-13/verification.json, source bundle, new raw responses, DOM records and the dependency lock produced during replay. The source bundle contains only the fixture, not this website repository. Clone it with: git clone fixture-source.bundle replay-fixture Use the original environment and commands above to build; the replay used npm install --ignore-scripts. The frozen version is a local experiment, not a recommended production starter; review current dependency advisories.