feat(website): implement public website for PRD v1.0#1
Conversation
Built React-based website implementing ODD principles: - Load content from manifest.json - Navigation with 7 or fewer items (progressive disclosure) - Markdown rendering with frontmatter stripping - Mobile responsive design - Deep link support via hash routing Visual interface contracts implemented: - color-system@1.0.0 with dark mode - typography@1.0.0 modular scale - spacing@1.0.0 base-8 scale Evidence includes 3 screenshots showing desktop/mobile layouts and content rendering. Run ID: 71c6fdc7
Temporary compatibility fix to enable website lane deployment on existing Cloudflare Pages project configured with /dist output. Once a dedicated Cloudflare project is set up for the website lane with output directory products/website/dist, this can be reverted.
Deploying klappy-dev-website with
|
| Latest commit: |
1fb713d
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://b4652c4c.klappy-dev-website.pages.dev |
| Branch Preview URL: | https://run-website-prd-v1-0-cursor-ksmz.klappy-dev-website.pages.dev |
Verified deployment on klappy-dev-website Cloudflare project: - Preview URL: https://website-attempt-test.klappy-dev-website.pages.dev/ - Evidence URL: https://website-attempt-test.klappy-dev-website.pages.dev/_evidence/ All completion criteria verified: - Branch pushed: d1be3bd - Cloudflare builds: successful - App loads: HTTP 200 - /_evidence/: HTTP 200 - Screenshots: 3 present
| }) | ||
| .then(md => { | ||
| // Strip frontmatter if present | ||
| const contentWithoutFrontmatter = md.replace(/^---[\s\S]*?---\n*/m, ''); |
There was a problem hiding this comment.
Frontmatter regex incorrectly strips mid-document content
Medium Severity
The frontmatter stripping regex /^---[\s\S]*?---\n*/m uses the m (multiline) flag, which causes ^ to match at the start of any line rather than only at the beginning of the string. This means if a markdown document contains --- markers elsewhere in the content (e.g., horizontal rules followed by any content ending in ---), that content could be incorrectly stripped. Removing the m flag would ensure only true frontmatter at the start of the file is matched.
| // Tier 0: Entry points | ||
| const tier0 = resources | ||
| .filter(r => r.tier === 0 && r.exposure === 'nav') | ||
| .sort((a, b) => a.title.localeCompare(b.title)); |
There was a problem hiding this comment.
Tier 0 filter missing internal audience exclusion
Medium Severity
The tier0 filter in Home.jsx is missing the r.audience !== 'internal' check that's present in both the tier1 filter (same file, line 21) and the Navigation.jsx filter (line 22). This inconsistency means internal-audience tier 0 resources could appear in the "Start Here" section on the public home page, even though they're correctly excluded from navigation and the "Go Deeper" section.
| setError(err.message); | ||
| setLoading(false); | ||
| }); | ||
| }, [resource?.path]); |
There was a problem hiding this comment.
Race condition when navigating between content pages
Medium Severity
The useEffect that fetches markdown content has no cleanup or staleness check. When a user navigates quickly between pages (e.g., Page A → Page B), both fetches run concurrently. If the fetch for Page A completes after Page B's fetch, it overwrites the content with stale data, showing Page A's content when the user is on Page B. This requires either an AbortController to cancel pending fetches or a staleness flag to ignore outdated responses.
Champion selection is not production. A Promotion PR is now required to move a champion to main. This closes the lifecycle gap where promotion was implicit. Ledger updated to reflect PR #1 as the retroactive Promotion PR (first instance preceded rule formalization).
Publishes the beginner-friendly entry point article that introduces AI collaboration through the intern mental model. Updates start_here ordering so The Intern is the new #1 entry point, bumping The Most Expensive Problem to #2. https://claude.ai/code/session_01DRCpgptMuzkMkWkKKRnDft
10 queries tested: control (main, 411 docs) vs treatment (E0007 branch, 447 docs). 9/10 tests: E0007 governance article is #1 result, scores 1.5x-3x higher. Documents mechanism (BM25 relevance), technique (articles teach how), and limitations (behavioral outcomes require user testing). Proves: small pointed files dominate BM25, tool descriptions hint while canon teaches, server-side changes work for every caller.
…gex matcher in the sweep) Writes the forward handoff for the next session to pick up P1.3.4 — the LAST regex-matcher ship in the canon-parity sweep. Same D5 + D9 pattern that P1.3.2 applied to gate and P1.3.3 applied to challenge, now for encode's triggerRegex classifier and the cachedEncodingTypes module-level cache. Key substantive points: - Confirms the premise: encode's vocabulary is already governance-driven (reads ## Trigger Words from odd/encoding-types/*.md at runtime), but the matcher is literal regex alternation with no stemming. Input 'deciding' does not match canon vocab 'decided'. Same bug class challenge had pre-0.21.0. - Calls out the load-bearing multi-type design at orchestrate.ts L1161: 'no break' comment is canon-by-convention and the refactor must preserve both semantics (batch-untagged first-match and parseUnstructuredInput multi-match). Handoff explicitly names it so the next session does not accidentally collapse it into single-match. - Carries forward the P1.3.3 Bug #1 stop-word lesson: pass new Set() as second arg to tokenize() on both sides. Canon trigger vocab includes stop-word phrases ('going with', 'committed to', 'turns out', 'must not', etc.) — filtering them would recreate the strictly-additive invariant break. - Validation plan is SINGLE-PATH and binding per release-validation-gate. No Option A vs Option B. The P1.3.3 handoff's optionality section produced the P1.3.3 incident; this handoff does not repeat that mistake. 'Before merging the main → prod promotion PR' explicitly requires Sonnet 4.6 validator dispatch with the 5-corroboration pattern adapted for encode. - Attestation mapping table ties each constraint (release-validation-gate Rules 1/2/3, cache-fetches-and-parses, vodka-architecture, contract-governs-handoff-drift) to the specific gate that satisfies it. - Carry-forward O-opens updated: P11 (mechanical gate enforcement of release-validation-gate) flagged as the natural follow-up after the sweep closes — a capability add, not a parity ship, so candidate for epoch transition rather than P1.3.5. - Thin prompt at the bottom for fast next-session context load. Target: 45-75 min to prod, ~40-line code delta, ship as oddkit 0.22.0. Closes the canon-parity sweep.
…gex matcher in the sweep) (#128) Writes the forward handoff for the next session to pick up P1.3.4 — the LAST regex-matcher ship in the canon-parity sweep. Same D5 + D9 pattern that P1.3.2 applied to gate and P1.3.3 applied to challenge, now for encode's triggerRegex classifier and the cachedEncodingTypes module-level cache. Key substantive points: - Confirms the premise: encode's vocabulary is already governance-driven (reads ## Trigger Words from odd/encoding-types/*.md at runtime), but the matcher is literal regex alternation with no stemming. Input 'deciding' does not match canon vocab 'decided'. Same bug class challenge had pre-0.21.0. - Calls out the load-bearing multi-type design at orchestrate.ts L1161: 'no break' comment is canon-by-convention and the refactor must preserve both semantics (batch-untagged first-match and parseUnstructuredInput multi-match). Handoff explicitly names it so the next session does not accidentally collapse it into single-match. - Carries forward the P1.3.3 Bug #1 stop-word lesson: pass new Set() as second arg to tokenize() on both sides. Canon trigger vocab includes stop-word phrases ('going with', 'committed to', 'turns out', 'must not', etc.) — filtering them would recreate the strictly-additive invariant break. - Validation plan is SINGLE-PATH and binding per release-validation-gate. No Option A vs Option B. The P1.3.3 handoff's optionality section produced the P1.3.3 incident; this handoff does not repeat that mistake. 'Before merging the main → prod promotion PR' explicitly requires Sonnet 4.6 validator dispatch with the 5-corroboration pattern adapted for encode. - Attestation mapping table ties each constraint (release-validation-gate Rules 1/2/3, cache-fetches-and-parses, vodka-architecture, contract-governs-handoff-drift) to the specific gate that satisfies it. - Carry-forward O-opens updated: P11 (mechanical gate enforcement of release-validation-gate) flagged as the natural follow-up after the sweep closes — a capability add, not a parity ship, so candidate for epoch transition rather than P1.3.5. - Thin prompt at the bottom for fast next-session context load. Target: 45-75 min to prod, ~40-line code delta, ship as oddkit 0.22.0. Closes the canon-parity sweep.
Summary
Built React-based website implementing ODD principles for the website lane (PRD v1.0).
Features
Evidence
Run ID:
71c6fdc7Screenshots captured of:
Technical
Note
Builds the initial public site under
products/websitewith manifest-driven content and progressive disclosure UX.App.jsx,Navigation.jsx,Home.jsx,ContentPage.jsx,index.html,main.jsx, and tokenized styles insrc/index.css/content/manifest.json, renders markdown viamarked, supports hash-based deep links, and enforces ≤7 primary nav items with mobile hamburger menuinfra/scripts/smart-build.jsto mirrorwebsitelanedistto root/distand copy/_evidenceinto build outputproducts/website/vite.config.js; addspuppeteeras devDependency; includes attempt/evidence artifacts underattempts/website/...Written by Cursor Bugbot for commit ce5ff4b. This will update automatically on new commits. Configure here.