Skip to content

fix(web): Top-Level Pages cards led nowhere, and /privacy was not a real page - #114

Merged
ralyodio merged 1 commit into
masterfrom
fix/top-level-pages
Jul 30, 2026
Merged

fix(web): Top-Level Pages cards led nowhere, and /privacy was not a real page#114
ralyodio merged 1 commit into
masterfrom
fix/top-level-pages

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

The bug

The Top-Level Pages band on logicsrc.com advertises eight stable routes. Two things were wrong with it.

1. Nothing on the band was a link. Each card rendered as plain <h3>/docs · Docs</h3> text. Confirmed against the running app — zero anchors in the whole band:

anchors inside Top-Level Pages band: []

2. /privacy was not a page. Four of the eight routes have no page of their own and fall through to src/app/[[...slug]]/page.tsx, which re-renders the entire homepage and relies on a useEffect scrollIntoView. Fetched from the dev server before the fix:

route status bytes
/privacy 200 81766
/openspec 200 81957
/credential-sharing 200 82022
/hire-us 200 81956
/docs 200 44769
/about 200 35009
/terms 200 38165

The first four are the same homepage, differing only in <title> and canonical. /openspec, /credential-sharing, and /hire-us at least scroll to real content bands. /privacy has no such section, so it scrolled to the card that only described the page — a dead end. A grep for personal data|we collect|cookie on the old /privacy returned 0.

3. Duplicate DOM ids. The cards used id="openspec", id="credential-sharing", and id="hire-us", which already name sections further up the same document, making those scroll targets ambiguous:

2 id="credential-sharing"
2 id="hire-us"
2 id="openspec"

The fix

  • Wrap each card title in <a href="/{route}"> so the band links where it says it links.
  • Add a real /privacy page. Content is grounded in what the code actually does, not boilerplate: CrawlProof analytics (layout.tsx), the Hire Us form fields (api/hire-us/project-request), the HttpOnly/SameSite=Lax CoinPay session cookie (lib/coinpay.ts), and the credshare boundary — 002_credshare.sql stores ciphertext, sealed per-member DEKs, and salted-hash fingerprints, so secret values never reach the server.
  • Prefix the card ids to page-<route>, removing the id collisions.
  • Drop privacy from ROUTE_META, and trim the home-interactivity scroll list to the three routes [[...slug]] still serves. docs, blog, about, and terms are real routes and were only ever aiming scrollIntoView at a card.

Verification

  • npm test (contract): 71 passed / 5 files.
  • npm run build: succeeds, and /privacy is now emitted as ○ /privacy (prerendered static) rather than resolving through the catch-all.
  • After the fix all eight cards link out, /privacy is 42KB of its own content with no Top-Level Pages band, and each of the three ids appears exactly once.
  • E2E: updated the /privacy test, which previously asserted the homepage band appeared there. Playwright could not run on this machine — Ubuntu 26.04 has no supported browser build and the cached Chromium is missing libatk-1.0.so.0. All 10 browser tests fail here regardless of this change; only the 2 request-only tests run. I validated every assertion in the new tests statically against the real rendered HTML instead (all 14 pass), but the e2e suite still needs a real run in CI.

Left alone deliberately

/openspec, /credential-sharing, and /hire-us still serve the full homepage plus a scroll. Their content is live, so this is not the reported bug, but it does mean four URLs serve near-identical 82KB documents under four different canonicals. Promoting them to real pages is a larger content migration — worth a follow-up.

🤖 Generated with Claude Code

… a page

The "Top-Level Pages" band advertises eight stable routes, but the cards
were plain <h3> text with no anchors -- nothing on that band was
clickable. Wrap each card title in a link to its route.

/privacy was the worst of the eight. It had no page and no homepage
section, so it fell through to [[...slug]], which served the entire
homepage (82KB, byte-identical to /openspec, /credential-sharing, and
/hire-us) and then scrolled to the card that merely described the page
that did not exist. Give it a real page covering what the site actually
does: CrawlProof analytics, the Hire Us form, the CoinPay OAuth session
cookie, and the credshare boundary -- ciphertext and salted-hash
fingerprints are stored, secret values never reach the server.

The cards also reused the ids openspec, credential-sharing, and hire-us,
which already name sections further up the same document. Duplicate ids
made those scroll targets ambiguous, so the cards are now page-<route>.
With that, the scroll list in home-interactivity only needs the three
routes [[...slug]] still serves; docs, blog, about, terms, and privacy
are real routes and were only ever aiming scrollIntoView at a card.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

@ralyodio
ralyodio marked this pull request as ready for review July 30, 2026 21:33
@ralyodio
ralyodio merged commit f9ebf9b into master Jul 30, 2026
5 checks passed
@ralyodio
ralyodio deleted the fix/top-level-pages branch July 30, 2026 21:35
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