feat(web): /pages/:slug renders bundled markdown — screen-gaps phase 3 (refs #83)#104
Merged
Conversation
Closes the <ComingSoon /> placeholders at /pages/{mission,leadership,
code-of-conduct,hackathons} per behaviors/app-shell.md. Adds the
content directory + a client-side markdown route using `marked`
(static pages aren't user content, so the no-client-markdown rule
doesn't apply). The placeholder copy in each page calls itself out;
porting the legacy laddr-site text is a content PR, not engineering.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
npm install --workspace apps/web marked Static /pages/:slug content is staff-authored bundle-time markdown, not user content — the no-client-markdown rule doesn't apply. marked is the smallest standalone markdown library that does what we need. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes the <ComingSoon /> placeholders at /pages/{mission,leadership,
code-of-conduct,hackathons} per specs/behaviors/app-shell.md.
Content lives in apps/web/src/content/pages/*.md, loaded as raw text
at build time via Vite's import.meta.glob. The new StaticPage
component parses the slug-matched source with `marked` and renders
inside a tailwind `prose` typographic container. Unknown slugs fall
through to <NotFound />.
This is safe to render client-side: static-page content is
build-time-static, not user input, so the CLAUDE.md
no-client-markdown rule (about XSS via user content) doesn't apply.
The four bundled pages carry placeholder copy with a self-disclosing
"awaiting content port" footer. Porting the legacy laddr-site copy
into these files is a content PR — out of scope for this engineering
plan, called out in the closeout follow-ups.
7 new tests cover all four bundled pages, the NotFound fallback,
markdown→heading semantic rendering, and inline link resolution.
Refs #83.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
All 5 validation checkboxes ticked. Notes covers the marked-v18 sync default, the deliberate prose-class duplication vs MarkdownView, and the no-DOMPurify rationale for build-time-static content. Follow-ups: content port from the legacy site, phase 4 (buzz/new form) still pending under #83, MDX upgrade path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Third phase of #83 — closes the `` placeholders at `/pages/{mission,leadership,code-of-conduct,hackathons}` per `specs/behaviors/app-shell.md`.
Safe to render client-side: static-page content is build-time-static, not user input, so the `CLAUDE.md` no-client-markdown rule (about XSS via user content) doesn't apply.
The four bundled pages carry placeholder copy that names itself as such ("awaiting content port"). Porting the real copy from `codeforphilly.org/site-root/pages/` is a content PR — out of scope for this engineering plan.
Test plan
What's left under #83
Only phase 4 remains: `/projects/:slug/buzz/new` create form. The API endpoint exists; just the SPA form is missing.
🤖 Generated with Claude Code