/// Typography
Prose
A typographic wrapper that styles raw rendered HTML (CMS/markdown output) with the PDS type scale and rhythm.
import { Prose } from "@protocore/pds";Rendering markup
Wrap already-rendered HTML — from a CMS, an MDX pipeline, or markdown — in Prose. Every descendant (h1–h6, p, lists, blockquote, code, pre, a, table, hr) inherits the type scale and vertical rhythm from the single scope; the source markup carries no classes of its own.
Deploying to the edge
Protocore ships static sites to CloudFront, one distribution per domain. Content is driven by a single multi-tenant CMS, so editors never touch a build.
How a publish flows
- An editor saves a change in the CMS.
- A webhook triggers the affected site's static export.
- The bundle syncs to S3 and the distribution is invalidated — see the pipeline notes.
Sharp edges, monochrome surfaces, one reserved accent. The rhythm carries the page.
Inline tokens.css holds the source of truth, and a pre block renders any snippet in the mono family:
export const deploy = () => sync(bucket);Trusted HTML string
Pass a pre-sanitized HTML string via the html prop when the content arrives as a string off the wire. It renders through dangerouslySetInnerHTML, so the producer must sanitize it first.
From the CMS
This block was authored in a rich-text field and rendered to plain HTML.
- Editors write content.
- The field serializes to HTML.
- Prose gives it the house type scale.
Compact density
size="sm" drops the base to 14px with tighter flow spacing — for sidebars, cards, and dense help panels.
Release 2.4
Compact prose for changelog panels and card bodies. Same rhythm, a smaller reading measure.
- Added the OverflowList component.
- Fixed RTL mirroring on the Timeline.
When to use it
Prose is the render target for any body content the design system does not compose element-by-element: a blog post, a changelog entry, a docs page, a rich-text CMS field. Because Protocore sites are CMS-driven, this is the seam where editor output meets the type system — the CMS emits plain semantic HTML and Prose gives it the house measure, rhythm, and link treatment without the editor needing to know a single class name.
It is server-safe and stateless: render it in a React Server Component, or feed it a string. For content you compose yourself in JSX, reach for Text, Heading, and Blockquote directly instead.
Usage
Do
- Feed it semantic HTML from your CMS or markdown renderer.
- Sanitize any `html` string upstream before it reaches the prop.
- Use `size="sm"` inside cards and narrow columns.
- Let a parent constrain the line length (a `max-width` around 68ch reads best).
Don't
- Pass unsanitized user input to `html`; sanitize at the source.
- Reach for it to lay out app UI; compose Text/Heading/Stack there.
- Add classes to the inner markup; the scope styles bare elements.
- Nest a Prose inside a Prose; one scope owns the whole block.
Accessibility
- Emits no wrapper semantics beyond a `div`; the heading order and landmarks come from your source HTML, so keep it well-structured.
- Link styling uses an underline plus an accent decoration color, so links are distinguishable without relying on color alone.
- Code blocks scroll horizontally inside their own container so long lines never force the page to scroll.
Prose props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | |
html | string | — | A trusted HTML string to render into the scope (e.g. CMS/markdown output). Rendered via `dangerouslySetInnerHTML`, so it MUST already be sanitized by the producer. Mutually exclusive with `children`. |
size | enum | md | Body density: `sm` sets a 14px base with tighter rhythm; `md` (default) is the 16px reading measure. |
style | CSSProperties | — |