.mdx
pages. Lettercamp includes React and its renderer with the CLI.
Supported imports
For Lettercamp Cloud, custom components can importreact, 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.cssor../lib/links.ts. Match filename casing exactly; Cloud’s file system is case-sensitive. - Do not use
#blog/...aliases frompackage.json,@/...aliases fromtsconfig.json, or aliases configured in another project’s bundler. These configurations are not included in CLI deployments. - Use
.css,.scss, or.sass, including.module.cssand.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.
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 includescomponents/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:
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 uselettercamp 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.
components/Counter.jsx:
pages/:
.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 exampleimport 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
Runnpx 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.
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 withlettercamp 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:visibleorclient:loadto its usage in MDX. Withclient: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
windowordocumentis undefined: move browser-only code intouseEffector an event handler. Interactive components also render outside the browser during the build.
npx lettercamp check to check Cloud compatibility before
publishing, and npx lettercamp dev to verify appearance and interactions.