---
description: Run a complete startup build, transform imported MDX directly, and keep generated metadata current in development.
---

# Vite 8

`amamoMdx` gives one Vite plugin instance one lazily created compiler. Vite owns module transforms and
filesystem events; the compiler owns validated records, manifests, and generated collection files.

## Configure the plugin

```ts
// 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)],
})
```

The plugin is `enforce: 'pre'` and `sharedDuringBuild: true`. When a Vite multi-environment build is
configured to reuse shared plugins, client and SSR environments therefore use the same plugin
compiler instead of compiling the content set independently.

## Import a document

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

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

For a recognized collection file, the `transform` hook ignores the incoming source string and asks
the compiler for the current JavaScript module. Frontmatter has already been validated, Markdown
media has been rewritten, and enabled Shiki output has been injected before Vite receives the code.

## Lifecycle

| Vite hook or event          | Compiler action                                        |
| --------------------------- | ------------------------------------------------------ |
| `buildStart`                | Run one complete `build()`.                            |
| `transform`                 | Run `transform(id)` for recognized collection files.   |
| dev server `add` / `change` | Transform the path and refresh generated outputs.      |
| dev server `unlink`         | Remove the known record and refresh generated outputs. |
| dev HTTP server `close`     | Detach watcher handlers and dispose the compiler.      |

The first startup call is shared, so repeated build hooks do not start duplicate full builds.
Compiler operations are serialized after that.

## Development updates

When add, change, or unlink changes at least one generated output, the plugin invalidates
`collections.mjs` if it is in Vite's module graph and sends a full reload. There is no document-level
HMR boundary yet.

A watcher compilation failure is sent to Vite's logger and error overlay. Successful record warnings
such as `AMAMO_MEDIA_MISSING` remain in `record.diagnostics`; the plugin does not print them.

## Generated collections

Application code may import the generated registry:

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

const published = collections.posts.filter((document) => !document.frontmatter.draft)
```

Each registry item has metadata plus `load: () => import(originalMdxPath)`. Vite processes that lazy
import through the same plugin. The plugin does not read `index.json`; that private index exists for
the Next loader.

## Production builds

`vite build` runs the same full startup build and per-import transforms. Outputs whose bytes are
unchanged keep their modification times, which lets downstream tools avoid work.

Set `cache: false` only when repeated native/Shiki work is acceptable. Vite can transform without
persistent records, unlike the Next adapter.

## Current limits

- Generated-output changes trigger a full reload.
- The plugin does not print `IBuildResult`; call the direct [Compiler API](/compiler-api/) when a
  report is required.
- Every plugin invocation owns separate compiler state. Register the plugin once for one content
  config.
