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 />
}

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