@amamo/mdx
On This Page

Getting started

This guide starts with one content/posts/hello.mdx file and ends with a host-importable module, collection registry, and companion declaration file.

Requirements

  • Node.js 20.19 or newer. This is the package's declared engine floor.
  • A supported native target. The binding has no JavaScript or WASI fallback. See Native targets.
  • React 19 in the host application. The default jsxImportSource is react.
  • Trusted MDX authors. Compiled MDX can execute JavaScript in the host application.

Install

Shell
pnpm add @amamo/mdx

The published root package selects a matching platform package during installation. Do not copy a node_modules directory between operating systems, CPU architectures, or Linux libc variants.

Add a document

Create the collection directory and a first document:

MDX
---
title: Hello
---

# Hello

This document is compiled by @amamo/mdx.

Save it as content/posts/hello.mdx.

Define the collection

Collection schemas use the package's Zod-compatible z.object; every other configuration value must be plain serializable data. defineConfig is an identity helper that exposes the config shape to TypeScript-aware tooling; schema conversion, validation, and defaults are applied when a compiler or adapter is created.

JavaScript
// amamo.config.mjs
import { defineConfig, z } from '@amamo/mdx'

export default defineConfig({
  root: import.meta.dirname,
  collections: {
    posts: {
      directory: 'content/posts',
      schema: z.object({ title: z.string() }),
    },
  },
  manifests: {
    public: {
      output: '.amamo-mdx/public.json',
      fields: {
        key: 'key',
        slug: 'slug',
        title: 'title',
      },
    },
  },
})

The content/posts directory must exist before a full build. Relative collection, cache, generated, and manifest paths are resolved from root.

Choose who owns the build

Vite

TypeScript
// vite.config.ts
import { amamoMdx } from '@amamo/mdx/vite'
import { defineConfig } from 'vite'

import amamo from './amamo.config.mjs'

export default defineConfig({ plugins: [amamoMdx(amamo)] })

Vite runs a full startup build, transforms imported content directly, and uses its watcher for add, change, and unlink events.

Next

TypeScript
// next.config.ts
import { withAmamoMdx } from '@amamo/mdx/next'

import amamo from './amamo.config.mjs'

export default withAmamoMdx(amamo)({ reactStrictMode: true })

Next builds the persistent cache before development or production bundling, then registers a read-only loader for Turbopack and Webpack. Keep the cache enabled for this adapter.

Direct API

JavaScript
// build-content.mjs
import { createCompiler } from '@amamo/mdx'

import amamo from './amamo.config.mjs'

const compiler = await createCompiler(amamo)
try {
  const result = await compiler.build()
  console.log(result)
} finally {
  await compiler.dispose()
}

Run it with:

Shell
node build-content.mjs

Call build() before transform() or remove() when generated outputs must represent the whole collection. The incremental methods update the compiler's current in-memory record set; they do not discover missing siblings by themselves.

Import content

Inside a configured Vite or Next application, import an MDX file like a module:

TSX
import Post, { frontmatter } from './content/posts/hello.mdx'

export function Page() {
  return (
    <main>
      <h1>{frontmatter.title}</h1>
      <Post />
    </main>
  )
}

Or import the generated collection registry from application code:

TypeScript
import { collections } from './.amamo-mdx/collections.mjs'

const hello = collections.posts.find((document) => document.slug === 'hello')
const module = await hello?.load()

The load() function imports the original MDX path, so it must run through a host that has the Vite plugin or Next loader configured.

Generated files

With the config above, the first build writes:

text
.amamo-mdx/
  cache/
  collections.d.ts
  collections.mjs
  index.json
  public.json
  • collections.mjs contains sorted metadata and lazy imports.
  • collections.d.ts is emitted as a companion declaration file for the registry.
  • index.json maps source paths to cache records for the Next loader; Vite does not read it.
  • cache/ contains reusable compiled records, including highlighted output.
  • public.json is the configured manifest. A different output may place a manifest elsewhere.

Add .amamo-mdx/ to the host repository's ignore file. Unchanged shared files and manifests are not rewritten.

Next, read Configuration for every available option and its default.

Copyright © 2026 白熱.