Skip to main content

Marp and Slidev alternative inside a React app

Start with what this does not do. Marp and Slidev export decks to PDF and PPTX from the command line. reveal.js prints to PDF from the browser. @react-markdown-kit/slides has no export command and writes no PPTX. If the deliverable is a file to email, use one of those three.

What it does instead: it turns Markdown your React app already renders into a deck, in the same page, through the same <Markdown> component. No second toolchain, no second copy of the content, no static site to deploy beside your app.

npm install @react-markdown-kit/renderer @react-markdown-kit/slides
import Markdown, { defineMarkdownPreset } from '@react-markdown-kit/renderer'
import { slides } from '@react-markdown-kit/slides/present'
import '@react-markdown-kit/slides/styles.css'

const preset = defineMarkdownPreset({ extensions: [slides()] })

<div className="rmk-document">
<Markdown preset={preset}>{deck}</Markdown>
</div>

What each tool does

MarpSlidevreveal.js@react-markdown-kit/slides
Runs asa CLI, a VS Code extension, a bundled HTML filea Vite dev server and a built single-page appa page you hosta component in a React tree you already have
Deck sourceMarkdown, --- breaks, directives in HTML commentsMarkdown, --- breaks, per-slide front matter, Vue componentsHTML sections, or Markdown through its pluginthe same Markdown file, --- breaks, ??? notes, -- fragments (DIALECT.md)
ExportHTML, PDF, PPTX, PNG (Marp CLI)PDF, PNG, PPTX (exporting)print to PDF (PDF export)browser print, one slide per page (styles.css); no PPTX
Present modepresenter view in the editor and the CLI previewpresenter mode with notes (UI)speaker view pluginpresent mode, presenter view, cross-window sync (present.dom.test.tsx)
Server renderinga build step writes the HTMLa build step writes the HTMLthe page ships the deckthe deck is built from the parsed tree, so a server component emits it (same suite)
Stylinga theme is a CSS file of Marp's classesUnoCSS and Vue componentsa theme is a CSS file of reveal's classesdata attributes and --rmk-slide-* properties, no class from the kit (extension.test.tsx)
Editingyour editor, with a previewyour editor, with hot reloadyour editorthe same file, plus a rich editor with four deck commands (editor-toolbar.test.tsx)

Every claim in the last column links to the test or the file that holds it.

The deck, rendered by the kit

The deck below is not a screenshot. It was rendered when this page was built, by the same renderer that draws this paragraph. Click Present, then use the arrow keys.

A three-slide deck, rendered in this page
Markdown
---
title: Release review
---

## Release review

One Markdown file. A document in the docs route, a deck in the talk route.

---

<!-- class: center, middle -->

## No export step

- The deck is a React component
- The notes ship in the DOM, hidden

???

Say that the source is the same file the docs page renders.

---

## Ship it

Questions?
Rendered

Release review

One Markdown file. A document in the docs route, a deck in the talk route.

No export step

  • The deck is a React component
  • The notes ship in the DOM, hidden

Ship it

Questions?

The static stack shows every slide at once. Present mode covers the viewport; Escape brings this page back.

Coming from a Marp deck

MarpHere
--- between slidesthe same, at the root of the document
<!-- _class: lead --> on one slide<!-- class: center, middle -->, one directive per comment
<!-- theme: gaia -->a stylesheet of yours, set through --rmk-slide-* properties
notes in an HTML commenta paragraph that is exactly ???, then the notes
fragments from the list marker, * for bullets and ) for ordered lists (fragmented list)a paragraph that is exactly -- between the blocks to reveal
background images through ![bg](…)<!-- background: … -->, run through the renderer's URL policy
front matter for the whole deckfront matter for the whole deck: title, aspect, class, background

The dialect is written out in DIALECT.md and on the slides page. A construct the plugin does not accept is reported as a diagnostic with its source range, not swallowed.

Stay with Marp or Slidev when

  • The output is a file. A PDF for a conference upload, or a PPTX for a colleague who edits in PowerPoint, is their job and not this plugin's.
  • The deck is a standalone artefact with no app around it, and a CLI is the shorter path.
  • You want Vue components, UnoCSS or Monaco inside slides, which is Slidev's design.
  • You want a theme you can install. Marp and reveal.js both have theme ecosystems; this has CSS custom properties and no themes to install.

Use this plugin when

  • The content already lives in your React app and is already rendered as Markdown. A deck then costs one preset, not a second pipeline.
  • The deck must sit behind your auth, your routing or your data. It is a component, so the page around it is yours.
  • The same file has to stay readable as a document. A deck is CommonMark or GFM with rules, so GitHub and a diff still show it as prose.
  • The deck must render on the server. It is built from the parsed tree by a root handler, so a server component emits the full markup.
  • The document is edited by people who do not write Markdown by hand. The editor entry adds New slide, Speaker notes, Pause and Background as toolbar buttons, tested in editor-toolbar.test.tsx.

What a CLI cannot give you

  • One source. The deck and the document are the same file, and a deck loaded and saved without edits is written back byte for byte (round-trip.test.ts).
  • The renderer's security policy. A javascript: background loses its src like any other URL in the document (extension.test.tsx), under the same security model as your prose.
  • Markup you can style. The deck emits no class, no inline style and no id beyond slide-<name>, so your stylesheet needs nothing from the kit.
  • No runtime for the static deck. The root entry loads nothing beyond the parser. React comes in with the present entry, Lexical only with the editor entry (packaging.test.ts).

Questions

Is there a Marp alternative that runs inside a React app?
This plugin is one. It adds slide rules to the Markdown renderer you already use, so a deck is a component in your own routes rather than a separate site or a build step.
Can I export a deck to PDF or PPTX?
There is no export command. The shipped stylesheet gives each slide its own page under @media print, so a browser prints a deck to PDF. PPTX is what Marp and Slidev do; this does not.
Does an existing Marp deck render unchanged?
The slide breaks, the prose and the code fences do. Marp directives, themes and its image sizing syntax do not; the mapping table on this page says what each one becomes.
Do I have to move my content out of my app?
No. The deck is the same Markdown file the renderer already reads, so a document and a deck are one source and one pipeline.

Next

The slides demo · The demo without its chrome, for an iframe · Markdown presentations in React · @react-markdown-kit/slides on npm · The renderer · Security model