diff --git a/.lane/reports/fix-clean-pagehead-self-decl-2026-08-14.md b/.lane/reports/fix-clean-pagehead-self-decl-2026-08-14.md new file mode 100644 index 00000000..4c43e12c --- /dev/null +++ b/.lane/reports/fix-clean-pagehead-self-decl-2026-08-14.md @@ -0,0 +1,35 @@ +# Lane 1: /agents, /pricing, /specimen page-head self-declaration + +Branch: `fix/clean-pagehead-self-decl-2026-08-14` +PR: https://github.com/nish3451/TinyStudio.io/pull/210 +Commit: `3ff1398` + +## Change + +All three pages now self-declare their clean extensionless URLs in the head +(the same form the worker serves at 200 and the sitemap lists), matching +`/audit`: + +| Page | canonical / og:url / WebPage @id+url | +| --- | --- | +| /agents | `https://tinystudio.io/agents` (`agents#webpage`) | +| /pricing | `https://tinystudio.io/pricing` (`pricing#webpage`) | +| /specimen | `https://tinystudio.io/specimen` (`specimen#webpage`) | + +Before: all three declared the `.html` twin, which the worker 307-redirects. + +## Files touched + +- `public/agents.html` — canonical, og:url, WebPage @id/url -> clean +- `public/pricing.html` — same +- `public/specimen.html` — same +- `scripts/check-site.mjs` — page-URL expectation tables (social share, structured data, canonical) now require the clean URL on all five pages; canonical comment updated + +## Validation + +- `node scripts/check-site.mjs` → "TinyStudio.io checks passed." +- `npm test` (full suite: check, headings, sitemap, worker, ui, contract, viewport, narrow-pages) → exit 0 + +## Notes + +- The `.html` twins remain allow-listed and served; this change only fixes what the pages declare about themselves. No redirect/route behavior changed. diff --git a/public/agents.html b/public/agents.html index 44495da3..2e3117d3 100644 --- a/public/agents.html +++ b/public/agents.html @@ -5,13 +5,13 @@ TinyStudio — The Desk - + - + @@ -42,8 +42,8 @@ }, { "@type": "WebPage", - "@id": "https://tinystudio.io/agents.html#webpage", - "url": "https://tinystudio.io/agents.html", + "@id": "https://tinystudio.io/agents#webpage", + "url": "https://tinystudio.io/agents", "name": "TinyStudio — The Desk", "description": "Seven specialists, one human signature. Each does a single job on your actual pages and numbers; nothing reaches you until a person has read and signed it.", "inLanguage": "en", diff --git a/public/pricing.html b/public/pricing.html index 5e513b12..825f772d 100644 --- a/public/pricing.html +++ b/public/pricing.html @@ -5,13 +5,13 @@ TinyStudio — Pricing & terms - + - + @@ -42,8 +42,8 @@ }, { "@type": "WebPage", - "@id": "https://tinystudio.io/pricing.html#webpage", - "url": "https://tinystudio.io/pricing.html", + "@id": "https://tinystudio.io/pricing#webpage", + "url": "https://tinystudio.io/pricing", "name": "TinyStudio — Pricing & terms", "description": "One price, plainly stated: the appraisal is free, the desk is $2,500 a month on a three-month minimum, and the delivery guarantee is written out in full.", "inLanguage": "en", diff --git a/public/specimen.html b/public/specimen.html index bcb96b72..53eb4cec 100644 --- a/public/specimen.html +++ b/public/specimen.html @@ -5,13 +5,13 @@ TinyStudio — The Website Appraisal — specimen - + - + @@ -42,8 +42,8 @@ }, { "@type": "WebPage", - "@id": "https://tinystudio.io/specimen.html#webpage", - "url": "https://tinystudio.io/specimen.html", + "@id": "https://tinystudio.io/specimen#webpage", + "url": "https://tinystudio.io/specimen", "name": "TinyStudio — The Website Appraisal, specimen", "description": "The appraisal, with the client's name removed: a real audit of a clinic homepage, four findings with evidence and fixes, read and signed by Nish.", "inLanguage": "en", diff --git a/scripts/check-site.mjs b/scripts/check-site.mjs index a130cbf8..5c7469ff 100644 --- a/scripts/check-site.mjs +++ b/scripts/check-site.mjs @@ -1557,9 +1557,9 @@ if (!worker.includes("https://cloudflareinsights.com")) { const socialSharePages = [ ["homepage", siteHome, "https://tinystudio.io/"], ["audit page", siteAudit, "https://tinystudio.io/audit"], - ["desk page", read("public/agents.html"), "https://tinystudio.io/agents.html"], - ["pricing page", read("public/pricing.html"), "https://tinystudio.io/pricing.html"], - ["specimen page", read("public/specimen.html"), "https://tinystudio.io/specimen.html"] + ["desk page", read("public/agents.html"), "https://tinystudio.io/agents"], + ["pricing page", read("public/pricing.html"), "https://tinystudio.io/pricing"], + ["specimen page", read("public/specimen.html"), "https://tinystudio.io/specimen"] ]; const SOCIAL_IMAGE_URL = "https://tinystudio.io/og-image.png"; @@ -1631,9 +1631,9 @@ for (const [pageName, pageHtml, pageUrl] of socialSharePages) { const structuredDataPages = [ ["homepage", siteHome, "https://tinystudio.io/"], ["audit page", siteAudit, "https://tinystudio.io/audit"], - ["desk page", read("public/agents.html"), "https://tinystudio.io/agents.html"], - ["pricing page", read("public/pricing.html"), "https://tinystudio.io/pricing.html"], - ["specimen page", read("public/specimen.html"), "https://tinystudio.io/specimen.html"] + ["desk page", read("public/agents.html"), "https://tinystudio.io/agents"], + ["pricing page", read("public/pricing.html"), "https://tinystudio.io/pricing"], + ["specimen page", read("public/specimen.html"), "https://tinystudio.io/specimen"] ]; const ORGANIZATION_ID = "https://tinystudio.io/#organization"; @@ -1863,15 +1863,14 @@ for (const [pageName, pageHtml] of internalLinkPages) { // link sits inside the head and points at the absolute https://tinystudio.io // address of the page. The deployed worker 307-redirects every .html form to // its clean extensionless twin, so a canonical must name the address that -// serves 200, never the redirecting form: the audit page's canonical is the -// clean /audit, while the remaining pages keep their .html form here until -// they are migrated the same way. +// serves 200, never the redirecting form: every page's canonical is its clean +// extensionless address (/audit, /agents, /pricing, /specimen). const canonicalPages = [ ["homepage", siteHome, "https://tinystudio.io/"], ["audit page", siteAudit, "https://tinystudio.io/audit"], - ["desk page", read("public/agents.html"), "https://tinystudio.io/agents.html"], - ["pricing page", read("public/pricing.html"), "https://tinystudio.io/pricing.html"], - ["specimen page", read("public/specimen.html"), "https://tinystudio.io/specimen.html"] + ["desk page", read("public/agents.html"), "https://tinystudio.io/agents"], + ["pricing page", read("public/pricing.html"), "https://tinystudio.io/pricing"], + ["specimen page", read("public/specimen.html"), "https://tinystudio.io/specimen"] ]; const canonicalLinkPattern = /]*\brel\s*=\s*["']canonical["'][^>]*>/gi;