---
description: Build a persistent MDX cache before Next bundling and read it through one verified Turbopack or Webpack loader.
---

# Next 16

The Next integration separates compilation from loading. The config wrapper builds the content set;
the bundler loader verifies `index.json` and returns the compiled module from its cache record.

## Requirements

- Keep persistent caching enabled. `cache: false` leaves the loader with no module record to read.
- Use `.mdx` for files imported through Next. The built-in Turbopack and Webpack rules are fixed to
  `*.mdx`, even if a collection lists another extension.
- Run on a [supported native target](/native-targets/) during `next dev` and `next build`.

## Configure Next

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

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

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

`withAmamoMdx(amamo)(nextConfig)` returns an async Next config function. Next later invokes it with
the current phase and `{ defaultConfig }`; it does not return a resolved config immediately.

The inner input may be a config object, a promise, or a config function:

```ts
import { withAmamoMdx } from '@amamo/mdx/next'

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

export default withAmamoMdx(amamo)(async (_phase, { defaultConfig }) => ({
  ...defaultConfig,
  images: {
    remotePatterns: [{ hostname: 'cdn.example.com', protocol: 'https' }],
  },
}))
```

The wrapper awaits the input, preserves its fields and existing `webpack` callback, then adds its
own Turbopack and Webpack rules.

## Phase behavior

| Phase                      | Preparation                                                                  |
| -------------------------- | ---------------------------------------------------------------------------- |
| `PHASE_DEVELOPMENT_SERVER` | Build once, then start the compiler's recursive watcher.                     |
| `PHASE_PRODUCTION_BUILD`   | Build once without starting a watcher.                                       |
| Any other phase            | Skip build and watch preparation, but still return config with loader rules. |

One wrapper invocation owns one lazy compiler and one shared build promise. Create the wrapper once
in the Next config rather than recreating it for individual requests.

## Loader flow

The same loader is registered at:

- `turbopack.rules['*.mdx']`, with output declared as JavaScript.
- A `test: /\.mdx$/` Webpack module rule.

For each imported source path, the loader:

1. Reads `<generatedDirectory>/index.json`.
2. Checks that its config fingerprint matches the wrapper's current normalized config.
3. Resolves the source's cache key and validates its hexadecimal shape.
4. Reads the corresponding JSON cache record.
5. Verifies the record key and returns its compiled `module` string.

Any mismatch rejects with `AMAMO_NEXT_CACHE_MISS` and asks for a coordinated rebuild. The loader is
read-only; parsing, Shiki, manifest writing, and cache pruning happen in the wrapper-owned compiler.

## Import MDX

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

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

Turbopack and Webpack read the same index and record format.

## Development behavior

In development, the compiler watches `config.root` recursively. A recognized create or change runs
`transform`; a deleted known record runs `remove`. This refreshes cache and generated outputs
independently of Next's file watcher; the two watchers have no ordering handshake.

Restart `next dev` after changing the configuration itself. The wrapper's normalized config,
fingerprint, and loader options are fixed when `withAmamoMdx(amamo)` is evaluated.

## Troubleshooting

| Symptom                               | Check                                                                                          |
| ------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `AMAMO_NEXT_CACHE_MISS`               | Cache is enabled, startup build completed, and `generatedDirectory` is shared with the loader. |
| Config fingerprint mismatch           | Restart Next after editing the config and remove stale generated output if necessary.          |
| A custom extension is not transformed | Rename it to `.mdx` or provide a separate Next loader; the built-in rule is fixed.             |
| Native binding unavailable            | Reinstall on a [supported target](/native-targets/) instead of copying `node_modules`.         |
