feat: direct links to individual contracts — /contract/<id> (#611)#612
Conversation
Contracts were the only first-class catalog entity without their own URLs. Each of the 19 contracts now gets a real pre-rendered page: - render-contracts.js emits per-contract detail fragments (EN + DE) alongside the existing /contracts overview fragment; overview cards link to the detail pages - prerender-routes.js gains prerenderContractPages(), mirroring the anchor-pages loop from LLM-Coding#597: /contract/<id> plus /de/contract/<id>, each with own title, description, canonical URL, og/twitter tags and hreflang pair via applyHead - the SPA router resolves /contract/<id> to the contracts page, scrolled to the highlighted card, with the real contract title (not a de-kebab-cased slug) in the document title; ids are regex-validated before entering selectors (5 new unit tests, TDD) - sitemap gains the 38 contract URLs; contracts join the JSON-LD DefinedTermSet with their /contract/<id> URLs App version 0.6.1 -> 0.7.0. Closes LLM-Coding#611 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
WalkthroughDie PR erzeugt pro Contract vorgerenderte EN/DE-Detailfragmente, pre-rendert statische Seiten ChangesDirect Contract Links Feature
Sequence Diagram(s)sequenceDiagram
participant Browser as Browser/User
participant Router as handleRoute()
participant Modal as Anchor Modal
participant ContractsHandler as /contracts handler
participant DOM as Contract Card (data-contract-id)
participant Display as Document Title / Scroll / Highlight
Browser->>Router: navigate to /contract/:id
Router->>Router: validate id (kebab-case)
Router->>Modal: close if open
Router->>ContractsHandler: invoke /contracts handler
Router->>ContractsHandler: update pageview tracking
Router->>DOM: find card element by data-contract-id
Router->>Display: set document.title from card heading
Router->>Display: scrollIntoView card
Router->>Display: apply temporary blue ring highlight
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@scripts/render-contracts.js`:
- Around line 138-149: Add a SAFE_ID_PATTERN constant using the same regex
/^[a-z0-9]+(?:-[a-z0-9]+)*$/ and validate every contract.id before using it in
path.join or template literals; in scripts/render-contracts.js (inside the loop
that calls renderContractDetail(contract, 'en'/'de')) and in
scripts/prerender-routes.js (the section that builds URLs/filenames from
contract.id) check SAFE_ID_PATTERN.test(contract.id) and skip or log and
continue for invalid IDs to avoid path-traversal, ensuring all writes and URL
templates only occur for IDs that pass the check.
🪄 Autofix (Beta)
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: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 1ad9fafc-c2d9-4eb2-88ad-4304e5886254
📒 Files selected for processing (8)
docs/changelog.adocscripts/generate-jsonld.jsscripts/generate-sitemap.jsscripts/prerender-routes.jsscripts/render-contracts.jswebsite/src/main.jswebsite/src/utils/router.jswebsite/src/utils/router.test.js
Both render-contracts.js and prerenderContractPages() now check contract.id against the same SAFE_ID_PATTERN the SPA router enforces, and skip (with a warning) any entry that fails — defense-in-depth so a malformed contracts.json entry cannot reach path.join() or URL templates. Found by CodeRabbit review. Refs LLM-Coding#611 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
Implements #611: every semantic contract gets its own pre-rendered page at
/contract/<id>plus a German variant at/de/contract/<id>— the same treatment anchors got in #597. Contracts were the only first-class catalog entity without their own URLs.Implementation
render-contracts.jscontracts.json's existing German fields) alongside the overview fragment; overview cards link to detail pages; DE pages link DE anchor pages where they existprerender-routes.jsprerenderContractPages()mirroring the anchor loop: own title, description, canonical, og/twitter tags, hreflang pair per page viaapplyHead/contract/<id>renders the contracts page scrolled to the highlighted card; document title comes from the card heading (the real contract title, not a de-kebab-cased slug); ids are regex-validated before entering DOM selectorsgenerate-sitemap.jsgenerate-jsonld.jsDefinedTermSetasDefinedTermentities with their/contract/<id>URLs (same GEO rationale as #579/#597)Verification
/deprefix) — 107/107 tests passdist/contract/specification/anddist/de/contract/specification/for title ("Specification" / "Spezifikation"), canonical, per-pageog:url,lang="de", and full no-JS contentCloses #611
🤖 Generated with Claude Code
Summary by CodeRabbit
Neue Funktionen
Bug Fixes
SEO / Strukturierte Daten
Tests
Sonstiges