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
jsxImportSourceisreact. - Trusted MDX authors. Compiled MDX can execute JavaScript in the host application.
Install
pnpm add @amamo/mdxnpm install @amamo/mdxyarn add @amamo/mdxbun add @amamo/mdxThe 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:
---title: Hello---# HelloThis 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.
// amamo.config.mjsimport { 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
// vite.config.tsimport { 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
// next.config.tsimport { 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
// build-content.mjsimport { 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:
node build-content.mjsCall 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:
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:
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:
.amamo-mdx/ cache/ collections.d.ts collections.mjs index.json public.jsoncollections.mjscontains sorted metadata and lazy imports.collections.d.tsis emitted as a companion declaration file for the registry.index.jsonmaps source paths to cache records for the Next loader; Vite does not read it.cache/contains reusable compiled records, including highlighted output.public.jsonis the configured manifest. A differentoutputmay 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.