fix(public): point internal page links at final clean URLs (dogfood 996dffe45ef7) - #34
Conversation
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
📝 WalkthroughWalkthroughThe public pages now use extensionless root-relative routes for navigation and internal links. ChangesClean route navigation
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 44b241cb52
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ["desk page", read("public/agents.html")], | ||
| ["pricing page", read("public/pricing.html")], | ||
| ["specimen page", read("public/specimen.html")] |
There was a problem hiding this comment.
Include the confirmation page in the clean-link guard
After a successful HTML signup, the worker redirects users to /brief-requested, but that served page still links to index.html, audit.html, agents.html, and pricing.html (including its back link). Because internalLinkPages stops at the specimen page, npm test passes while clicks from the confirmation page continue through the redirects this change is intended to eliminate; migrate public/brief-requested.html to clean URLs and include it in this guard.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@public/agents.html`:
- Around line 65-70: Choose a single canonical route scheme for the public
pages, then apply it consistently to the navigation links in the public HTML
files and all related og:url and JSON-LD WebPage URL values, including audit,
agents, pricing, and specimen. Update other public references to use the same
scheme while preserving the worker’s support for both route forms.
In `@scripts/check-site.mjs`:
- Around line 1244-1252: Update the anchor href extraction and target comparison
in the internalLinkPages validation loop to accept single-quoted, double-quoted,
and unquoted href attributes, then normalize same-origin paths by removing
leading ./ or / and excluding query strings and fragments before checking
htmlPageTargets. Preserve the existing failure message and add regression cases
covering /audit.html, /audit.html?source=nav, and ./audit.html.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: c2fd8905-9cc4-4459-a577-2e7e3c47730d
📒 Files selected for processing (6)
public/agents.htmlpublic/audit.htmlpublic/index.htmlpublic/pricing.htmlpublic/specimen.htmlscripts/check-site.mjs
| <a class="logo" href="/">Tiny<span>Studio</span></a> | ||
| <div class="navlinks"> | ||
| <a href="audit.html">The appraisal</a> | ||
| <a href="agents.html" aria-current="page">The desk</a> | ||
| <a href="pricing.html">Pricing</a> | ||
| <a class="navcta" href="index.html#start">Request the appraisal</a> | ||
| <a href="/audit">The appraisal</a> | ||
| <a href="/agents" aria-current="page">The desk</a> | ||
| <a href="/pricing">Pricing</a> | ||
| <a class="navcta" href="/#start">Request the appraisal</a> |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
for file in public/index.html public/audit.html public/agents.html public/pricing.html public/specimen.html; do
if rg -n 'og:url|`@id`|^[[:space:]]*"url"' "$file" | rg -q 'tinystudio\.io/[^"]*\.html'; then
printf 'stale public URL metadata: %s\n' "$file" >&2
exit 1
fi
doneRepository: nish3451/TinyStudio.io
Length of output: 205
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- repository root ---'
find . -maxdepth 1 -type f -printf '%f\n' | sort
printf '%s\n' '--- plan candidates ---'
fd -HI -t f '(^|/)(plan|PLAN|readme|README)([^/]*|/.*)$' . | head -80
printf '%s\n' '--- tracked target files ---'
git ls-files public/index.html public/audit.html public/agents.html public/pricing.html public/specimen.html
printf '%s\n' '--- metadata and navigation references ---'
rg -n -C 3 'og:url|application/ld\+json|`@id`|^[[:space:]]*"url"|href="/(audit|agents|pricing)|canonical|tinystudio\.io' public/index.html public/audit.html public/agents.html public/pricing.html public/specimen.htmlRepository: nish3451/TinyStudio.io
Length of output: 38301
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- repository guidance ---'
cat AGENTS.md
printf '%s\n' '--- project overview ---'
cat README.md
printf '%s\n' '--- plan references to routes and metadata ---'
rg -n -i -C 3 'clean route|pretty route|canonical|metadata|og:url|agents|audit|pricing|specimen' specs/*/plan.md
printf '%s\n' '--- deployment and route-related files ---'
git ls-files | rg '(^|/)(wrangler|worker|server|functions|routes|public|src|app)' | head -160
cat wrangler.jsoncRepository: nish3451/TinyStudio.io
Length of output: 7647
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- plan files ---'
for file in specs/*/plan.md; do
printf '\n### %s\n' "$file"
cat "$file"
done
printf '%s\n' '--- worker outline ---'
ast-grep outline src/worker.js
printf '%s\n' '--- worker route handling ---'
rg -n -C 8 'pathname|/audit|/agents|/pricing|/specimen|\.html|ASSETS|fetch\(' src/worker.js
printf '%s\n' '--- sitemap URLs ---'
cat public/sitemap.xmlRepository: nish3451/TinyStudio.io
Length of output: 19864
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
import json
import re
pages = {
"public/index.html": "/",
"public/audit.html": "/audit",
"public/agents.html": "/agents",
"public/pricing.html": "/pricing",
"public/specimen.html": "/specimen",
}
for filename, route in pages.items():
text = Path(filename).read_text()
html_urls = re.findall(r'https://tinystudio\.io/[^"\s<]+\.html(?:#\w+)?', text)
og = re.findall(r'<meta property="og:url" content="([^"]+)"', text)
jsonld = re.findall(r'<script type="application/ld\+json">\s*(.*?)\s*</script>', text, re.S)
webpages = []
for block in jsonld:
graph = json.loads(block).get("`@graph`", [])
webpages.extend(item for item in graph if item.get("`@type`") == "WebPage")
print(filename)
print(" expected public route:", route)
print(" extensionless route exposed by worker:", route in {
"/", "/audit", "/agents", "/pricing", "/specimen"
})
print(" og:url:", og)
print(" WebPage `@id`:", [item.get("`@id`") for item in webpages])
print(" WebPage url:", [item.get("url") for item in webpages])
print(" .html metadata URLs:", html_urls)
PY
printf '%s\n' '--- route and metadata references ---'
rg -n -i 'canonical|clean route|extensionless|\.html|href="/(audit|agents|pricing|specimen)' README.md AGENTS.md specs public src wrangler.jsonc \
-g '!public/*.js' -g '!public/*.css' -g '!public/*.png' -g '!public/*.svg'
printf '%s\n' '--- focused change summary ---'
git diff --stat -- public/index.html public/audit.html public/agents.html public/pricing.html public/specimen.html src/worker.js wrangler.jsoncRepository: nish3451/TinyStudio.io
Length of output: 19590
Align public routes and metadata.
The worker serves both route forms, but navigation uses extensionless paths while og:url and JSON-LD WebPage URLs use .html in public/audit.html, public/agents.html, public/pricing.html, and public/specimen.html. Choose one canonical route scheme and apply it to the navigation, metadata, and related public references.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@public/agents.html` around lines 65 - 70, Choose a single canonical route
scheme for the public pages, then apply it consistently to the navigation links
in the public HTML files and all related og:url and JSON-LD WebPage URL values,
including audit, agents, pricing, and specimen. Update other public references
to use the same scheme while preserving the worker’s support for both route
forms.
| for (const [pageName, pageHtml] of internalLinkPages) { | ||
| const anchors = [...pageHtml.matchAll(/<a\b[^>]*>/gi)].map((match) => match[0]); | ||
| for (const anchor of anchors) { | ||
| const href = anchor.match(/\bhref="([^"]*)"/i)?.[1] ?? ""; | ||
| const target = href.split("#")[0]; | ||
| if (Object.prototype.hasOwnProperty.call(htmlPageTargets, target)) { | ||
| failures.push( | ||
| `Internal page link on ${pageName} must point at the clean destination ${JSON.stringify(htmlPageTargets[target])} (found ${JSON.stringify(href)}).` | ||
| ); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Normalize href values before checking old page targets.
The guard only matches href="..." and only compares bare audit.html-style values. Valid internal links such as href='/audit.html', href="/audit.html?source=nav", and href=./audit.html can bypass this check. Normalize same-origin URL paths before comparing them with htmlPageTargets, and add regression cases for these forms.
Proposed guard hardening
for (const [pageName, pageHtml] of internalLinkPages) {
const anchors = [...pageHtml.matchAll(/<a\b[^>]*>/gi)].map((match) => match[0]);
for (const anchor of anchors) {
- const href = anchor.match(/\bhref="([^"]*)"/i)?.[1] ?? "";
- const target = href.split("#")[0];
+ const hrefMatch = anchor.match(
+ /(?:^|\s)href\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'`=<>]+))/i
+ );
+ const href = hrefMatch?.[1] ?? hrefMatch?.[2] ?? hrefMatch?.[3] ?? "";
+ let target;
+ try {
+ const url = new URL(href, "https://tinystudio.io/");
+ if (url.origin !== "https://tinystudio.io") continue;
+ target = url.pathname.replace(/^\/+/, "");
+ } catch {
+ continue;
+ }
if (Object.prototype.hasOwnProperty.call(htmlPageTargets, target)) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for (const [pageName, pageHtml] of internalLinkPages) { | |
| const anchors = [...pageHtml.matchAll(/<a\b[^>]*>/gi)].map((match) => match[0]); | |
| for (const anchor of anchors) { | |
| const href = anchor.match(/\bhref="([^"]*)"/i)?.[1] ?? ""; | |
| const target = href.split("#")[0]; | |
| if (Object.prototype.hasOwnProperty.call(htmlPageTargets, target)) { | |
| failures.push( | |
| `Internal page link on ${pageName} must point at the clean destination ${JSON.stringify(htmlPageTargets[target])} (found ${JSON.stringify(href)}).` | |
| ); | |
| for (const [pageName, pageHtml] of internalLinkPages) { | |
| const anchors = [...pageHtml.matchAll(/<a\b[^>]*>/gi)].map((match) => match[0]); | |
| for (const anchor of anchors) { | |
| const hrefMatch = anchor.match( | |
| /(?:^|\s)href\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'`=<>]+))/i | |
| ); | |
| const href = hrefMatch?.[1] ?? hrefMatch?.[2] ?? hrefMatch?.[3] ?? ""; | |
| let target; | |
| try { | |
| const url = new URL(href, "https://tinystudio.io/"); | |
| if (url.origin !== "https://tinystudio.io") continue; | |
| target = url.pathname.replace(/^\/+/, ""); | |
| } catch { | |
| continue; | |
| } | |
| if (Object.prototype.hasOwnProperty.call(htmlPageTargets, target)) { | |
| failures.push( | |
| `Internal page link on ${pageName} must point at the clean destination ${JSON.stringify(htmlPageTargets[target])} (found ${JSON.stringify(href)}).` | |
| ); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/check-site.mjs` around lines 1244 - 1252, Update the anchor href
extraction and target comparison in the internalLinkPages validation loop to
accept single-quoted, double-quoted, and unquoted href attributes, then
normalize same-origin paths by removing leading ./ or / and excluding query
strings and fragments before checking htmlPageTargets. Preserve the existing
failure message and add regression cases covering /audit.html,
/audit.html?source=nav, and ./audit.html.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
This branch sat open long enough for four other public-page PRs (#28 heading hierarchy, #30 apple touch icon, #32 schema.org, #33/#34 links) to land on the same five head sections and the same guard script, so every touched file conflicted. Resolution: all six conflicts were additive, not competing. - The five HTML files each gained a <link rel="canonical"> on this branch and icon/og/twitter/JSON-LD tags on main; both sets are kept. - scripts/check-site.mjs was rebuilt from main's version with this branch's 53-line canonical guard inserted verbatim before the migrations loop, rather than by textually merging two overlapping hunks — the first attempt at that spliced a dangling `const canonicalPages = [` and broke the file. intended-outcome: PR #29 becomes mergeable with the canonical guard and every already-landed head guard both enforced. verify: node scripts/check-site.mjs -> "TinyStudio.io checks passed."; npm test -> 15/15; npm run check, test:headings, test:worker all pass. check:render-blocking is not runnable here (playwright is not installed in this worktree) — CI covers it.
… current main and live (#39) The code-side fix (PR #34) and CI enforcement (the 'Internal page links (dogfood 996dffe45ef7)' guard in scripts/check-site.mjs) for dogfood finding 996dffe45ef7 ('Redirecting internal links on home') are already merged in origin/main. This lane re-verified the guarantee still holds after the subsequent page edits (canonical URLs, sitemap): - npm run check passes on all five public pages: no anchor targets any .html page name on any of them. - npm test passes (source checks + heading-hierarchy, sitemap, agent-worker and agent-UI suites). - Fresh live measurement of the deployed pages in real Chromium confirms the same: every internal link on all five pages returns HTTP 200 with no Location header (probed with maxRedirects 0) — zero redirecting internal links — including the home page the finding flagged (https://tinystudio.io/). The .html forms the pre-fix home linked at still 307-redirect to their clean twins, but no page links to them. Nothing further to change; the receipt now records the closeout on the current head so the finding cannot be re-opened by tracker drift.
… current main and live (#80) The code-side fix (PR #34) and CI enforcement (the 'Internal page links (dogfood 996dffe45ef7)' guard in scripts/check-site.mjs) for dogfood finding 996dffe45ef7 ('Redirecting internal links on home') are already merged in origin/main. This lane re-verified the guarantee still holds after the page edits that landed since the first receipt (canonicals on the appraisal page, the homepage footer daily-reads link, the 44px tap-target pass, the Agent Desk de-index, the AI-answer source pages): - npm run check passes on all five public pages: no anchor targets any .html page name on any of them. - npm test passes (source checks + heading-hierarchy, sitemap, agent-worker, agent-UI and product-contract suites; 90 tests total). - Fresh live measurement of the deployed pages in real Chromium (2026-08-11) confirms the same: every internal link on all five pages returns HTTP 200 with no Location header (probed with maxRedirects 0) — zero redirecting internal links — including the home page the finding flagged (https://tinystudio.io/). The .html forms the pre-fix home linked at still 307-redirect to their clean twins, but no page links to them. Nothing further to change; the receipt now records the closeout on the current head (8b42e0a) so the finding cannot be re-opened by tracker drift.
… current main and live (#126) The code-side fix (PR #34) and CI enforcement (the 'Internal page links (dogfood 996dffe45ef7)' guard in scripts/check-site.mjs) for dogfood finding 996dffe45ef7 ('Redirecting internal links on home') are already merged in origin/main. This lane re-verified the guarantee still holds after the page edits that landed since the last receipt (the rel=icon favicon pass on every page, the /brief-requested favicon guard, the appraisal intake labels and document titles, the 'conversion audit' search-intent bridge, the retired app/api hosts rename): - npm run check passes on all five public pages: no anchor targets any .html page name on any of them. - npm test passes (source checks + heading-hierarchy, sitemap, agent-worker, agent-UI and product-contract suites; 92 tests total). - Fresh live measurement of the deployed pages in real Chromium (2026-08-12) confirms the same: every internal link on all five pages returns HTTP 200 with no Location header (probed with maxRedirects 0) — zero redirecting internal links — including the home page the finding flagged (https://tinystudio.io/). The .html forms the pre-fix home linked at still 307-redirect to their clean twins, but no page links to them. Nothing further to change; the receipt now records the closeout on the current head (18128e8) so the finding cannot be re-opened by tracker drift.
…45ef7) against current main and live (#34) (#179) The finding's fix (PR #34, "fix(public): point internal page links at final clean URLs") is already on origin/main: all five public pages point every page link at the clean URL the worker serves (/ , /audit, /agents, /pricing, /specimen — never at a .html file that resolves to it), and the "Internal page links (dogfood 996dffe45ef7)" guard in scripts/check-site.mjs enforces the shape. Re-verified against current main (b0e9c57) and live: npm run check and npm test pass (117 tests, 0 failures), and real-Chromium measurement on 2026-08-14 shows every internal link on every page probing 200 with no Location header (maxRedirects 0) — zero redirecting internal links — while the five .html forms still 307 to their clean twins, unlinked. Closes out the dogfood item with a dedicated receipt. Co-authored-by: nish3451 <nish3451@users.noreply.github.com> Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
…45ef7) against current main and live (2026-08-15) (#225) Re-verified the finding on the current origin/main head (c0305df) and the deployed site, in the pattern of the 2026-08-09 closeout (PR #34) and the 2026-08-11/08-12/08-14 re-verifications: npm run check and npm test pass (the 996dffe45ef7 guard still rejects any .html page-name anchor on the five public pages), the only link-surface change since the last receipt is a one-line copy change on the home page (ffc1672), and the live site serves zero redirecting internal links on all five public pages — measured in real Chromium, home included. The finding stays closed with no code change needed. Co-authored-by: nish3451 <nish3451@users.noreply.github.com> Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
Closes dogfood finding 996dffe45ef7 (audit 20260808T074205Z-msk2fl3n), "Redirecting internal links on home".
intended-outcome: The five appraisal pages link every internal page anchor at the clean final-destination URL the worker serves (
/,/audit,/agents,/pricing,/specimen), with a static guard that fails if a.htmlpage-link target returns.verify: ! rg -q '<a[^>]+href="[^"]*.html' public/index.html public/audit.html public/agents.html public/pricing.html public/specimen.html
What the dogfood run reported
The audit engine flagged every
.htmlnavigation target on the home page as a redirecting internal link:index.html->/,audit.html->/audit,agents.html->/agents,pricing.html->/pricing,specimen.html->/specimen.Fix per the engine: "Update internal links so they point directly to the final destination URL."
Change
All five public pages (
index.html,audit.html,agents.html,pricing.html,specimen.html) now link every internal page anchor (<a>) at the clean final-destination URL the worker serves (/,/audit,/agents,/pricing,/specimen), including the logo link and the cross-pageindex.html#startCTAs (now/#start). No.htmlpage link remains on any of the five pages.Guard
Added a static source guard in
scripts/check-site.mjs(repo convention for dogfood fixes):npm testfails if any of the five pages reintroduces an<a href>pointing at a.htmlpage target.Verification
npm run check— passnpm test— pass (74 tests: 6 headings + 53 worker + 15 ui)git diff --check— cleannpm run check:render-blocking— all six pages PASSnpx wrangler deploy --dry-run— passRerun of the dogfood batch (20260808T074205Z-msk2fl3n engine) should drop the fingerprint from active findings.