Skip to main content
Layouts arrange components. Components provide their default appearance and behavior. Start with design settings, then copy a starter layout when you need to change the arrangement or add your own UI. Your articles stay in Markdown or MDX. Lettercamp handles routing, SEO, search indexing, and publishing, including when you replace the presentation.

Layouts and elements

components/elements/ is a convention for organizing your own components, not an automatically detected directory. A component there only appears when imported and rendered. Keep styles beside the component they belong to.

Override files and fallback

Each override is optional and independent: Use .jsx or .tsx with a default export. Do not create both extensions for the same override. Older flat paths such as components/Header.jsx still work; components/layouts/Header.jsx takes precedence when both exist. Remove both versions to restore the built-in header. Other regions keep their own defaults. A broken override reports an error; it does not silently fall back. Returning null intentionally hides that region. Omitting a TOC or pagination from a custom layout also leaves it out; Lettercamp does not insert missing controls.

Try the starter examples

The bundled starter includes examples/layouts/. These examples use the same elements and default styles as the built-in site. They are inactive until copied into components/layouts/. Copy only the layout you want to edit:
Or copy all five examples:
You own their arrangement. Updating Lettercamp updates the imported components; it does not rewrite your layout files or rearrange your custom page.

Keep a default element

The public Header, Footer, and PostCard always render Lettercamp’s default element. Import one with an alias to distinguish it from your override:
This renders the same header as having no override. You can add markup around it, pass a CSS Module class, or replace it entirely. It does not call your override again. See UI components for props and styling hooks.

Post list

A custom list owns its heading, navigation, cards, empty state, and pagination. Use the supplied PostCard to honor your card override and its default fallback:
An imported PostCard from lettercamp/components always uses the standard card. The PostCard prop uses your override when present. Choose the prop when you want your card design to apply throughout the publication.

Post card

Start with the standard card:
Or render your own markup from post. The card receives site, pathname, basePath, and priority in addition to post. Set eager image loading when priority is true. Search results use their own presentation.

Post layout

The starter composes the standard article header, TOC, article body, and related posts. Add your own component directly where you want it, for example immediately after {children}:
PostHeader includes the title, description, category, cover, byline, and sharing. TableOfContents defaults to the floating control on the left. The starter explicitly selects sidebar for the horizontal article layout. Render children once. Lettercamp supplies the rendered body and its built-in block styles. Keep article content in pages/; do not parse Markdown in the layout or copy article text into React code.

Shared props and post data

All five overrides receive: A post includes the article’s frontmatter plus these normalized fields: Use supplied URLs directly. Do not prepend basePath again to post links, images, category links, or pagination URLs. Use basePath when creating your own publication-relative navigation. Absolute URLs can link to the parent website. Components render during the build and hydrate in the browser. Use browser APIs such as window inside effects or event handlers, not during rendering. Keep these components compatible with browser execution for online previews.

Settings and defaults

Pass the layout’s site to settings-aware components so they use live settings in the editor preview. PostHeader honors hero layout, cover visibility, reading width, and reading-time visibility. TableOfContents and RelatedPosts honor their visibility settings. The default header and footer honor their settings. Your own markup only follows settings you use in code. The starter layouts show how to retain reading width, listing layout, and the standard components. You can intentionally replace those choices with your own design. The online design customizer identifies custom layouts and replaces the built-in layout picker for a custom list or article. Other controls apply where your components use them. Removing an override restores the saved default settings. Colors and typography remain available through CSS variables. Site identity, favicon, language, time zone, SEO, and analytics remain managed by Lettercamp.

Write a component

Create ordinary components under components/elements/ and import them from your layout using a relative path, such as ../elements/NewsletterSignup.jsx. See React components for authoring and supported imports for Cloud dependencies.

Add styles with CSS Modules

Create components/layouts/Header.module.css beside your component:
Import the stylesheet and use className={styles.header}. Lettercamp bundles the CSS with unique class names. Site typography and global element styles still apply. Use variables such as var(--font-family) and var(--site-background) to match your publication. Local previews and standalone builds support assets in public/; see Cloud asset preparation when publishing to Lettercamp.

Style your post components

Keep each stylesheet beside its component and import it:
Your module classes control your own markup. For the article body, scope rules beneath your content wrapper and use these hooks:
  • Standard elements: h2, p, a, ul, blockquote, and other Markdown output.
  • Body root: [data-lettercamp-body].
  • Rich blocks: [data-lettercamp-table], [data-lettercamp-code], [data-lettercamp-faq], [data-lettercamp-key-takeaways], and [data-lettercamp-subscribe].
  • Width choices: data-block-width, data-image-width, data-table-width, and data-code-width, with values such as regular, wide, and full.
  • Shared variables: --font-family, --heading-font, --site-background, --site-foreground, --site-border, and --post-content-width.
Retain the built-in sizing and interaction markup. Wide and full-width blocks expand within the managed body wrapper; give that wrapper enough room and avoid clipping it with overflow: hidden. Avoid depending on generated CSS Module class names. A custom stylesheet can still hide or distort content, so check representative tables, media, code, and FAQs at desktop and mobile widths.

Keep article typography separate from block UI

CSS Modules make class names local; they do not isolate descendant elements. A rule such as .content h2 also matches an email subscribe title inside that wrapper. Use .content :global(.prose > h2) for top-level article headings, and give your own post header a separate module class. Use explicit selectors for nested article content, such as .content :global(.prose blockquote > p). Lettercamp’s subscribe title, description, and status message define their own spacing inside .prose, so ordinary article typography does not add heading dividers or paragraph margins to them. They still inherit your site’s fonts and colors. This is CSS scoping, not a Shadow DOM boundary: highly specific selectors and !important can still override native styles. To intentionally customize a subscribe block, target its parts instead of all headings or paragraphs:
The block exposes [data-subscribe-card], [data-subscribe-title], [data-subscribe-description], [data-subscribe-form], [data-subscribe-button], and [data-subscribe-message]. Preserve form controls, focus styles, and status messages. Check the rendered Preview as well as the rich text editor, which uses its own editing styles.

Use the web editor

Article content stays editable through either the Markdown/MDX files or the online rich editor. Write uses Lettercamp’s editing surface; Preview shows the custom post components from the last successful build with current draft content and settings. New and unpublished articles can use that layout too. The site build bundles the post components and their CSS once. Editing text, a table, metadata, or settings updates preview data without compiling the theme again. Publish component or stylesheet changes to update the online theme bundle; local lettercamp dev updates while you work on those files. No per-editor server is required. Keep generated assets with the site when self-hosting. Built-in rich blocks render in the draft preview. Arbitrary React imports and JavaScript expressions inside an MDX article remain placeholders in the online editor and draft preview; inspect those with lettercamp dev or a published page. Custom headers and footers retain their existing online preview placeholders.

Preview and publish

Run npx lettercamp dev for live updates as you edit code and CSS or add and remove layout components. Run npx lettercamp check before publishing. Agents should use npx lettercamp check --json and fix the reported problems until the full build passes. This catches dependencies and aliases that can work in a local preview but fail on Cloud. Use local icon components with inline SVG instead of installing an icon library. Publish your component files and stylesheets with npx lettercamp deploy, or commit them to the repository connected to GitHub publishing. For self-hosting, run npx lettercamp build --site https://example.com and upload the entire output directory, including its generated CSS and JavaScript assets.