Skip to content

fix(public): point internal page links at final clean URLs (dogfood 996dffe45ef7) - #34

Merged
nish3451 merged 2 commits into
mainfrom
fix/internal-links-clean-urls
Aug 9, 2026
Merged

fix(public): point internal page links at final clean URLs (dogfood 996dffe45ef7)#34
nish3451 merged 2 commits into
mainfrom
fix/internal-links-clean-urls

Conversation

@nish3451

@nish3451 nish3451 commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

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 .html page-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 .html navigation 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-page index.html#start CTAs (now /#start). No .html page 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 test fails if any of the five pages reintroduces an <a href> pointing at a .html page target.

Verification

  • npm run check — pass
  • npm test — pass (74 tests: 6 headings + 53 worker + 15 ui)
  • git diff --check — clean
  • npm run check:render-blocking — all six pages PASS
  • npx wrangler deploy --dry-run — pass

Rerun of the dogfood batch (20260808T074205Z-msk2fl3n engine) should drop the fingerprint from active findings.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The public pages now use extensionless root-relative routes for navigation and internal links. scripts/check-site.mjs validates that these pages do not retain known .html targets.

Changes

Clean route navigation

Layer / File(s) Summary
Normalize public page routes
public/index.html, public/audit.html, public/agents.html, public/pricing.html, public/specimen.html
Header, content, CTA, FAQ, and footer links now use clean root-relative routes.
Validate clean routes
scripts/check-site.mjs
Static checks scan the five public pages and reject known .html link targets.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes updating internal public-page links to final clean URLs.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/internal-links-clean-urls

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread scripts/check-site.mjs
Comment on lines +1231 to +1233
["desk page", read("public/agents.html")],
["pricing page", read("public/pricing.html")],
["specimen page", read("public/specimen.html")]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between aa64d7d and 44b241c.

📒 Files selected for processing (6)
  • public/agents.html
  • public/audit.html
  • public/index.html
  • public/pricing.html
  • public/specimen.html
  • scripts/check-site.mjs

Comment thread public/agents.html
Comment on lines +65 to +70
<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>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ 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
done

Repository: 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.html

Repository: 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.jsonc

Repository: 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.xml

Repository: 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.jsonc

Repository: 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.

Comment thread scripts/check-site.mjs
Comment on lines +1244 to +1252
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)}).`
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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.

Suggested change
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.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@nish3451
nish3451 merged commit 39a6238 into main Aug 9, 2026
3 checks passed
nish3451 added a commit that referenced this pull request Aug 9, 2026
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.
nish3451 added a commit that referenced this pull request Aug 9, 2026
… 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.
nish3451 added a commit that referenced this pull request Aug 10, 2026
… 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.
nish3451 added a commit that referenced this pull request Aug 13, 2026
… 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.
nish3451 added a commit that referenced this pull request Aug 14, 2026
…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>
nish3451 added a commit that referenced this pull request Aug 15, 2026
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant