# react-markdown (/integrations/react-markdown)

[Full example on GitHub](https://github.com/leandrocp/lumis/tree/main/packages/javascript/rehype-lumis/examples/react-markdown)

`react-markdown` already supports `rehypePlugins`, so Lumis fits naturally through `@lumis-sh/rehype-lumis`.

## Install

```bash
npm install react-markdown
npm install @lumis-sh/rehype-lumis \
  @lumis-sh/lumis @lumis-sh/themes \
  @lumis-sh/wasm-bundle-web
```

## Server-side rendering

`rehype-lumis` is async, so use `MarkdownAsync` for server rendering:

```tsx
import {MarkdownAsync} from 'react-markdown'
import rehypeLumis from '@lumis-sh/rehype-lumis'
import {htmlInline} from '@lumis-sh/lumis/formatters'
import web from '@lumis-sh/wasm-bundle-web'
import latte from '@lumis-sh/themes/catppuccin_latte'

export async function Article({source}: {source: string}) {
  return (
    <MarkdownAsync
      rehypePlugins={[[rehypeLumis, {
        formatter: (language) =>
          htmlInline({language, theme: latte}),
        languages: [web],
      }]]}
    >
      {source}
    </MarkdownAsync>
  )
}
```

## Client-side rendering

For client-side rendering (e.g. with Vite), use `MarkdownHooks` instead:

```tsx
import {MarkdownHooks} from 'react-markdown'
import rehypeLumis from '@lumis-sh/rehype-lumis'
import {htmlInline} from '@lumis-sh/lumis/formatters'
import web from '@lumis-sh/wasm-bundle-web'
import latte from '@lumis-sh/themes/catppuccin_latte'

function Article({source}: {source: string}) {
  return (
    <MarkdownHooks
      rehypePlugins={[[rehypeLumis, {
        formatter: (language) =>
          htmlInline({language, theme: latte}),
        languages: [web],
      }]]}
    >
      {source}
    </MarkdownHooks>
  )
}
```

`MarkdownAsync` is for React Server Components. `MarkdownHooks` uses `useEffect` internally and works in any client-side React app.