DocsBlogChangelog

Routing

Routing is delegated to each respective framework using helpers from the createSource utilitiy. This gives you full control for how to render content and documentation. The following demonstrates how to set up routing using the paths helper from createSource in Next.js.

Naming Conventions

Source files named <Component>.tsx can have an accompanying <Component>.mdx. This is the same for other files like hooks or utilities. For example, useHook.ts and useHook.mdx.

For index.ts or index.tsx, the accompanying file can be index.md, index.mdx, README.md, or README.mdx.

Rendering Content

MDX content can be rendered using the Content component exported from a source item in an App Router page:

app/blog/[slug]/page.tsx
import { createSource } from 'mdxts'

const allDocs = createSource('docs/**/*.mdx')

export default async function Page({ params }: { params: { slug: string[] } }) {
  const { Content } = await allDocs.get(params.slug)
  return <Content />
}

Configuring Base Directories

Depending on how you want paths structured in your project, you can set a base directory when defining sources with createSource:

posts.ts
import { createSource } from 'mdxts'

export const allPosts = createSource('src/posts/*.mdx', {
  baseDirectory: 'posts',
})

This will affect the paths method and how the get method is used to retrieve content:

app/[slug]/page.tsx
import { notFound } from 'next/navigation'
import { allPosts } from '../../posts'

export default async function Page({ params }: { params: { slug: string } }) {
  // now you don't need to prefix the "/src/posts" path
  const post = await allPosts.get(params.slug)

  if (!post) {
    return notFound()
  }

  const { Content } = post

  return <Content />
}

Visit the createSource API documentation for more information on how to configure sources.

Rendering Type Documentation

Type documentation can be rendered using the exportedTypes metadata from a source item. Any associated MDX content can be rendered using the Content component if present:

app/components/[slug]/page.tsx
import { createSource } from 'mdxts'

const allComponents = createSource('components/**/*.tsx')

export default async function Page({ params }: { params: { slug: string[] } }) {
  const { Content, exportedTypes } = await allComponents.get(params.slug)
  return (
    <>
      {Content ? <Content /> : null}
      <ul>
        {exportedTypes.map((type) => (
          <li key={type.name}>
            <h4>{type.name}</h4>
            <p>{type.description}</p>
            {type.types.map((type) =>
              type.properties ? (
                <ul>
                  {type.properties.map((property) => (
                    <li key={property.name}>
                      <h5>{property.name}</h5>
                      <p>{property.description}</p>
                    </li>
                  ))}
                </ul>
              ) : (
                type.text
              )
            )}
          </li>
        ))}
      </ul>
    </>
  )
}

When targeting JavaScript or TypeScript files, a few heuristics are used to infer public metadata:

  • First, package exports will be used if present.
  • Otherwise, the presence of an index file will be used to infer public exports.
  • Finally, if both fail to find public entry source files, the entire directory will be analyzed.

Generating Static Routes

Use the paths method for a source to generate static routes:

app/blog/[slug]/page.tsx
import { createSource } from 'mdxts'

const allDocs = createSource('docs/**/*.mdx')

export function generateStaticParams() {
  return allDocs.paths().map((pathname) => ({ slug: pathname }))
}

export default async function Page({ params }: { params: { slug: string[] } }) {
  const { Content } = await allDocs.get(params.slug)
  return Content ? <Content /> : null
}

Rendering Examples

Examples collected from .examples.tsx files and examples directories are available on a source item through examplePaths and getExample helpers. The exported example can be rendered using moduleExport:

app/examples/[...example]/page.tsx
import { createSource } from 'mdxts'

const allComponents = createSource('components/**/*.tsx')

export async function generateStaticParams() {
  return (await allComponents.examplePaths()).map((pathname) => ({
    example: pathname,
  }))
}

export default async function Page({
  params,
}: {
  params: { example: string[] }
}) {
  const example = await allComponents.getExample(params.example)
  return <example.moduleExport />
}
Last updated