Getting Started

Learn how to configure and start using renoun.

This guide will help you get started using renoun in your project. Designed as a powerful toolkit for building documentation and authoring content with MDX, renoun offers a suite of utilities and components to create beautiful, interactive documentation tailored exactly to your needs.

While this getting-started guide uses Next.js as an example, renoun works with any framework or bundler that supports React Server Components.

Installation

First, install renoun and additionally set up a Next.js project if you haven’t already:

npm install renoun
pnpm add renoun
bun add renoun
yarn add renoun

Configuration

CLI

A CLI is included with renoun to help isolate the processing required for syntax highlighting and resolving type information. This greatly improves performance of these operations by keeping them separate from your application’s development and build processes.

To use the CLI, prepend renoun to your Next.js dev and build commands in your project’s package.json:

{
  "scripts": {
    "dev": "renoun next dev",
    "build": "renoun next build"
  }
}

Then start the development server:

npm run dev

Prepending the renoun CLI ensures that the renoun process starts before your framework’s server. The CLI starts a WebSocket server that will watch for changes to the file system and communicates with renoun components and utilities.

MDX Content

The renoun toolkit helps with authoring MDX using the renoun/mdx package, allowing you to write content with a mix of Markdown and React components. The renoun/mdx package is not required to use, but provides a set of useful plugins to enhance your content.

To start, create a new directory in your project called posts and add a new file called build-a-button-component-in-react.mdx:

build-a-button-component-in-react.mdx
export const metadata = {
  title: 'Build a Button Component in React',
  description: `Learn how to build a reusable Button component in React that can be used across your application.`,
  date: '2025-06-07',
  tags: ['react', 'design systems'],
}

In modern web development, creating reusable UI components is a must for efficiency and scalability. React, with its component-based architecture, allows developers to build encapsulated components that manage their own state and can be reused throughout applications.

## Building the Button Component

Let's start by creating our Button component:

```tsx
import React from 'react'

export function Button({ label, onClick, className }) {
  return (
    <button className={className} onClick={onClick}>
      {label}
    </button>
  )
}
```

We are using YAML front matter to define metadata for the post, such as the title, date, summary, and tags. This metadata can be used to show a list of posts, filter by tags, or display the post’s title and date.

Querying the File System

The Directory class is a core utility in renoun. This allows you to easily query and render files and directories within a file system. To create a list of blog posts, query all of the MDX files in the posts directory we created in the previous step:

import { Directory } from 'renoun/file-system'

const posts = new Directory({
  path: 'posts',
  include: '*.mdx',
})

Now we can use the configured directory to render the contents of our MDX files by querying them from the file system.

Create a new file in the app/posts directory called [slug].tsx and add the following:

import { Directory } from 'renoun/file-system'

const posts = new Directory({
  path: 'posts',
  include: '*.mdx',
})

export default async function Page({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  const slug = (await params).slug
  const post = await posts.getFile(slug, 'mdx')
  const Content = await post.getExportValue('default')

  return <Content />
}

This will create a collection of every MDX file in the posts directory and render the page based on the provided slug.

Loaders

By default, the Directory class will load files using the MDX compiler. However, if you are using a bundler like Webpack, Turbopack, or Vite, it is recommended to define a loader that resolves the module. This is especially useful for MDX files, which are often processed by the bundler’s loader.

Use the loader option in the Directory constructor to assign a specific loader for each file type. In the posts directory, for instance, you can use a dynamic import as the loader to ensure that the MDX files are processed by the bundler:

import { Directory } from 'renoun/file-system'

const posts = new Directory({
  path: 'posts',
  include: '*.mdx',
  loader: {
    mdx: (path) => import(`./posts/${path}.mdx`),
  },
})

A File System entry’s getPath method is used to generate a route path for each entry in the directory. To generate a link to each post, map over the directory’s entries using getEntries and then use the entry’s getPath method to generate a list of links:

import { Directory } from 'renoun/file-system'
import Link from 'next/link'

const posts = new Directory({
  path: 'posts',
  include: '*.mdx',
  loader: {
    mdx: (path) => import(`@/posts/${path}.mdx`),
  },
})

export default async function Page() {
  const allPosts = await posts.getEntries()

  return (
    <>
      <h1>Blog</h1>
      <ul>
        {allPosts.map((post) => {
          const pathname = post.getPathname()

          return (
            <li key={pathname}>
              <Link href={pathname}>{post.getTitle()}</Link>
            </li>
          )
        })}
      </ul>
    </>
  )
}

Validating Exports

Alongside file loading, renoun can validate module exports to ensure that source code is documented and exported according to a consistent schema. This is especially beneficial in larger projects where multiple developers collaborate on the same codebase.

Below is an example demonstrating how to validate a metadata object exported from a module using Zod:

posts.ts
import { Directory, withSchema } from 'renoun/file-system'
import { z } from 'zod'

export const posts = new Directory({
  path: 'posts',
  include: '*.mdx',
  loader: {
    mdx: withSchema(
      {
        metadata: {
          title: z.string(),
          date: z.coerce.date(),
          summary: z.string().optional(),
          tags: z.array(z.string()).optional(),
        },
      },
      (path) => import(`./posts/${path}.mdx`)
    ),
  },
})

Here we define a schema for the front matter of our MDX files and use it to validate each file in the posts directory. This ensures that each file adheres to the schema and provides type safety when accessing the metadata export:

import { posts } from './posts.ts'

const post = await posts.getFile('build-a-button-component-in-react.mdx')
const metadata = await post.getExportValue('metadata')
const { title, date, summary, tags } = metadata

Metadata

Now that we have a schema for the metadata, we can access it from the MDX file using the getExportValue method:

import { Directory, withSchema } from 'renoun/file-system'
import { z } from 'zod'

export const posts = new Directory({
  path: 'posts',
  include: '*.mdx',
  loader: {
    mdx: withSchema(
      {
        metadata: {
          title: z.string(),
          date: z.coerce.date(),
          summary: z.string().optional(),
          tags: z.array(z.string()).optional(),
        },
      },
      (path) => import(`./posts/${path}.mdx`)
    ),
  },
})

export default async function Page({
  params,
}: {
  params: Promise<{ slug: string }>
}) {
  const slug = (await params).slug
  const post = await posts.getFile(slug, 'mdx')
  const metadata = await post.getExportValue('metadata')
  const Content = await post.getExportValue('default')

  return (
    <>
      <h1>{metadata.title}</h1>
      <p>{metadata.description}</p>
      <Content />
    </>
  )
}

If you are using front matter, you can use the remark-frontmatter and remark-mdx-frontmatter packages to parse the front matter and export it as a JavaScript object.

Enhancing with Components

The renoun toolkit provides several built-in components to enhance your documentation like APIReference and CodeBlock. For example, you can use the APIReference component to document all exports from a module:

import { APIReference } from 'renoun/components'

<APIReference source="components/Card.tsx" />

Card

({ label, href, }: { label: React.ReactNode; href: string; }) => JSX.Element

Parameters
Properties

label *

ReactNode

href *

string
Returns
Element

Explore more components to enhance your documentation.

Conclusion

By following this guide, you should now have a basic setup running renoun in your Next.js project. You can now start writing content and documentation with renoun’s powerful toolkit. If you have any questions or need further assistance, feel free to reach out on Discord or GitHub.