Skip to main content
For built-in article blocks such as images, code, and tables, use content components without imports. Use custom React components for your own UI and interactions. Add React components to your publication repository and import them into .mdx pages. Lettercamp includes React and its renderer with the CLI.

Supported imports

For Lettercamp Cloud, custom components can import react, react-dom, lettercamp/components, and local components, JavaScript or TypeScript helpers, and CSS or Sass files. Keep supporting source files in components/, lib/, styles/, or assets/.
  • Import reusable UI components from lettercamp/components. This CLI-provided entry point needs no separate installation.
  • Use relative imports such as ./Footer.module.css or ../lib/links.ts. Match filename casing exactly; Cloud’s file system is case-sensitive.
  • Do not use #blog/... aliases from package.json, @/... aliases from tsconfig.json, or aliases configured in another project’s bundler. These configurations are not included in CLI deployments.
  • Use .css, .scss, or .sass, including .module.css and .module.scss. Lettercamp includes the Sass compiler. Less and Stylus are not provided.
  • Do not import other npm packages, including react-icons, lucide-react, UI kits, or Next.js components. Use inline <svg> elements or small local icon components, and standard <a> and <img> elements for links and images.
Installing a package locally or adding it to package.json does not make it available when publishing to Lettercamp. A local preview or build can succeed by using packages installed on your computer that are unavailable in hosted builds. Do not rely on packages used internally by Lettercamp either. For images or fonts needed by a custom component, an agent can upload assets with the signed-in CLI and use the returned hosted URLs in the component or its CSS. After each component change, run npx lettercamp check. Agents can use npx lettercamp check --json, fix the reported files, and repeat until the full check passes. Do not install a missing library or externalize it in a bundler configuration to work around a Cloud compatibility error. If you build for another host, your components can use dependencies installed in your own build environment.

Try the starter calculator

The bundled starter includes components/ReadingTimeCalculator.jsx. Readers can enter a word count or choose a preset to estimate reading time at 200 words per minute, rounded up to whole minutes. Zero words produces zero minutes. To use it in a page, add the import after the frontmatter, then place the component where you want it:
The initialWords prop sets the starting word count and defaults to 600. The calculator uses the count the reader enters.

Create your own component

For an existing cloud site, connect your local coding agent to download its source. Develop locally, then use lettercamp push to review a cloud preview before publishing from the website. Keep reusable components in components/ or an optional components/elements/ subfolder beside pages/. Reserve components/layouts/ for the five automatically detected layout overrides. Use .jsx for JavaScript or .tsx for TypeScript. Import local files using paths relative to the MDX page, including the file extension.
For example, create components/Counter.jsx:
Import it in a page under pages/:
Import components directly in the .mdx page that uses them. Components can import other local components and use React hooks such as useState and useEffect.

Style your component

Import a CSS Module from your component, for example import styles from './Counter.module.css', then use a local class with className={styles.counter}. Lettercamp bundles the CSS and generates unique class names. Commit both files. Plain .css imports are global and can affect other parts of your publication; inherited fonts and global element styles still apply with CSS Modules. You can also replace your publication’s header or footer with a React component using the same styling approach.

Choose when a component becomes interactive

Lettercamp renders React components to HTML during the build. Add a client directive when a component needs event handlers or state updates in the browser. Place the client directive on the component’s usage in MDX to choose when it becomes interactive: Use strings, numbers, booleans, arrays, and plain objects for props passed to interactive components. Define event handlers inside the component instead of passing functions from MDX. Components with client:visible or client:load also render during the build. Access browser APIs such as window and localStorage in an effect or event handler, rather than at module scope or during the initial render.

Edit in the web editor

Both Edit and the page’s Preview show custom React components as labeled placeholders. Each placeholder marks the component’s position on the page. Inline components appear as small labels within the text. Imports and exports stay in Source and are preserved when you edit the page. Use a placeholder’s Edit source button to change its MDX props or imports. To change the component implementation, edit its .jsx or .tsx file in your publication repository. Use Preview for a read-only content preview of the current page, including unsaved text and component placeholders. Use npx lettercamp dev to check the publication’s full layout and interactive React components.

Preview locally

Run npx lettercamp dev from your publication folder. Imported component changes update the local preview automatically. This is useful when developing a component and checking repeated changes to its code.
Open the URL printed in the terminal. Set draft: false in your example page’s frontmatter to include it in the local site. Use the web editor’s Preview to view draft content and component placeholders.

Publish

For a workspace downloaded with lettercamp connect, run lettercamp check, then lettercamp push. Review the result in Settings → Agent connections and choose Publish this preview. See Connect and sync. For Lettercamp Cloud, run npx lettercamp check, then npx lettercamp deploy. For another host, run npx lettercamp build --site https://example.com to generate the HTML and JavaScript for hosting. Upload the entire output directory, including its generated assets, so interactive components can load. Commit component files alongside the MDX pages that import them. Hosted builds read those files from your publication repository. Check your components against the supported imports before publishing.

Troubleshooting

  • The component appears but does not respond: add client:visible or client:load to its usage in MDX. With client:visible, scroll the component into view before trying it. For a self-hosted site, also check that its generated JavaScript assets were uploaded.
  • The import cannot be resolved: check the relative path, filename casing, file extension, and matching default or named export. Commit the component file to the repository used by hosted builds.
  • The build reports that window or document is undefined: move browser-only code into useEffect or an event handler. Interactive components also render outside the browser during the build.
Run npx lettercamp check to check Cloud compatibility before publishing, and npx lettercamp dev to verify appearance and interactions.