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
---
# 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.
// 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
// 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
// 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
// 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:
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.