Markdown Slides: Presentations with Marp and reveal.js

September 11, 2026 · 11 min read

Markdown Slides: Make Presentations with Marp and reveal.js

Markdown slides are a slide deck written as one plain-text file, with a separator line between slides. A tool such as Marp or reveal.js turns the file into HTML, PDF or PowerPoint. This guide gives you a complete eight-slide Marp deck explained line by line, the same deck in reveal.js, and a separator comparison so switching tools doesn't break your file.

How Do I Write Slides in Markdown?

You write ordinary Markdown and split it with a horizontal rule: three dashes on their own line. Everything between two rules is one of your markdown slides. Headings become slide titles, bullets become bullet points, images and code blocks render as you'd expect. That's the whole idea, and it's why a markdown presentation takes minutes rather than an afternoon in PowerPoint.

# Quarterly Review

Priya Nair, Engineering

---

## Agenda

- Shipped
- Learned
- Next

The --- line is the same horizontal rule from core Markdown, which our horizontal line guide covers. Slide tools simply reinterpret it.

That reuse has two side effects. You can't draw a visible rule inside a Marp slide, because *** and ___ split slides too, so a divider has to come from theme CSS. And a YAML front matter block at the top of the file also starts and ends with ---, which every tool handles as metadata rather than a slide break.

Draft Slide Content in the Editor

The content of each slide is plain GFM, the same syntax as the GitHub Markdown cheat sheet. That means you can draft the whole deck in a normal editor and check headings, bullets, code and images before you open a slide tool. Paste this in, and the --- lines render as rules where the slide breaks will fall.

Quarterly Review

Priya Nair, Engineering


Shipped

  • Ledger service at 40M transactions a day
  • Settlement batch down from 4 h to 25 min

Next quarter

  1. Kafka upgrade
  2. On-call rotation

Questions welcome at any point.

42 words242 characters19 lines
Markdown

A Complete Eight-Slide Marp Deck, Line by Line

Marp is the tool we recommend for your first markdown presentation slides. A Marp deck is a single .md file with no HTML wrapper. Save this as deck.md.

---
marp: true
theme: gaia
paginate: true
header: "Quarterly Review"
---

<!-- _paginate: false -->

# Quarterly Review

Priya Nair, Engineering

---

## Agenda

- Shipped
- Learned
- Next quarter

---

## Shipped

- Ledger service at 40M transactions a day
- Settlement batch down from 4 h to 25 min

<!-- Mention the zero-downtime cutover here. -->

---

## How the cutover worked

```go
func cutover(ctx context.Context) error {
    return ledger.Migrate(ctx, ledger.DualWrite)
}
```

---

![bg left:40%](architecture.png)

## Architecture

Event sourcing with Postgres partitions.

---

## Learned

![w:500](incident-timeline.png)

---

<!-- _class: lead -->

## Next quarter

1. Kafka upgrade
2. On-call rotation

---

## Questions?

priya@example.com

Here is what each construct does, using the Marpit directives documentation as the reference.

  • Front matter (lines 1 to 6). marp: true tells Marp for VS Code to treat the file as a deck. theme picks one of the built-in themes (default, gaia, uncover). paginate: true and header are directives that apply to every slide from this point on.
  • <!-- _paginate: false -->. An HTML comment holding a directive. The underscore prefix makes it apply to this slide only, so the title slide has no page number.
  • --- on its own line. The slide separator, seven of them for eight slides.
  • <!-- Mention the zero-downtime cutover here. -->. A comment that isn't a directive becomes a presenter note, visible in the presenter view and exportable with the CLI's --notes flag.
  • Fenced code. Renders with syntax highlighting. Keep it under about 15 lines per slide.
  • ![bg left:40%](architecture.png). Marp's image syntax: bg makes the image a background, left splits the slide with the image on the left, and :40% sets the split width. Split backgrounds need Marp's inline SVG mode, which Marp Core turns on by default.
  • ![w:500](incident-timeline.png). An inline image resized to 500 px wide. h: sets height, and both accept CSS units.
  • <!-- _class: lead -->. Applies the theme's lead class to one slide for a centred layout.

Themes deserve one more line. The three built-in themes cover most talks. The style global directive accepts raw CSS in the front matter for small tweaks such as a brand colour or a larger code font. A full custom theme is a CSS file registered with the CLI's --theme option or the VS Code extension's markdown.marp.themes setting.

Image paths are relative to the Markdown file, and the syntax for the image itself is standard, as in our Markdown image guide. Code slides follow the same fence rules as any Markdown code block.

What Are Marp Slides?

Marp (Markdown Presentation Ecosystem) is a family of tools for markdown presentations built on Marpit, a CommonMark-based framework that adds the directive and image extensions above. In practice you'll use two pieces. Marp for VS Code shows a live slide preview beside the editor and exports from the command palette. Marp CLI does the same from a terminal, which is what you want in a build script:

npx @marp-team/marp-cli@latest deck.md --pdf
npx @marp-team/marp-cli@latest deck.md --pptx
npx @marp-team/marp-cli@latest deck.md -o deck.html
npx @marp-team/marp-cli@latest deck.md --images png

The HTML export is self-contained. PDF, PPTX and image export need Google Chrome, Microsoft Edge or Firefox installed, because the Marp CLI renders through a browser. Two flags to know. -w watches the file and rebuilds on save. --pptx-editable produces a PowerPoint with editable text boxes at the cost of lower fidelity and no presenter notes; the README flags it as experimental and it needs LibreOffice Impress installed as well as the browser. The standard --pptx output is an image per slide, so it's faithful but not editable.

The Same Deck in reveal.js Markdown

reveal.js is an HTML presentation framework that can load Markdown either inline or from an external file. It gives you fragments, vertical slides and speaker view, and it runs anywhere a browser does. The cost is an HTML wrapper. The reveal.js Markdown docs show both forms; here's the external-file form, which keeps the deck as a .md you can also feed to Marp.

<div class="reveal">
  <div class="slides">
    <section data-markdown="deck.md"
             data-separator="^\r?\n---\r?\n$"
             data-separator-vertical="^\r?\n--\r?\n$"
             data-separator-notes="^Note:">
    </section>
  </div>
</div>

And the deck.md it loads, with the reveal.js-specific parts:

# Quarterly Review

Priya Nair, Engineering

---

## Shipped

- Ledger service at 40M transactions a day <!-- .element: class="fragment" -->
- Settlement batch down from 4 h to 25 min <!-- .element: class="fragment" -->

Note: Mention the zero-downtime cutover here.

---

<!-- .slide: data-background="#0b3d91" -->

## Architecture

--

## Architecture: detail

Event sourcing with Postgres partitions.

Three things differ from Marp. Speaker notes are a line starting with Note: rather than an HTML comment. <!-- .element: --> adds attributes such as the fragment class to the element before it, and <!-- .slide: --> sets attributes on the slide. And -- on its own line creates a vertical slide beneath the current one, a feature Marp doesn't have.

Separators Compared: Marp, reveal.js and Slidev

Decks break when they move between tools, and the separator is the usual reason. The three most popular tools disagree in small ways.

ToolHorizontal slideVertical slideSpeaker notesPer-slide settings
Marp---Not supportedHTML comment<!-- _key: value -->
reveal.js--- by default (configurable regex)Off by default; -- when enabledNote: line<!-- .slide: attr -->
Slidev--- padded with blank linesNo, uses layoutsHTML comment at the end of the slideYAML block after the ---

Slidev, per its syntax guide, goes furthest: each --- can be followed by a YAML block with layout, background and class, and the first block is a headmatter with theme and title. A Slidev deck opens in Marp with all that YAML rendered as text, and a Marp deck opens in Slidev with its directives ignored. Pick a tool before you write the fifth slide.

Which Markdown Presentation Tool Should You Start With?

Every markdown presentation tool exports something different, and the export decides the tool as often as the syntax does. Marp gives you HTML, PDF, PPTX and PNG. reveal.js gives you a web page, with PDF through the browser's print dialog. Slidev gives you a web page, plus PDF, PPTX and PNG through its own export command, which needs Playwright's Chromium installed. If your audience wants a file attached to a calendar invite, Marp is the least setup. If they want a link, any of the three works.

Our recommendation by audience:

  • You give talks with code and want PDF or PowerPoint. Marp for VS Code. One file, live preview, three export formats, no build step.
  • You want animations, fragments and a web-hosted deck. reveal.js. Accept the HTML wrapper and get the richest presenter features.
  • You're a front-end developer who wants Vue components on slides. Slidev, which also has the best code highlighting of the three.
  • You already keep notes in Obsidian. The community Advanced Slides plugin uses reveal.js under the hood, so the reveal.js syntax above applies. Our Obsidian cheat sheet covers the base syntax.

Every one of these is also a markdown presenter in the literal sense: a presenter view with notes, a timer and the next slide. Marp's HTML export opens one on the P key, reveal.js has speaker view on the S key, and Slidev has a presenter page at /presenter. Search results for markdown-slides tools tend to lead with a GitHub project of that name, but the three above are the maintained options with real export paths.

The limitation shared by all of them: layout control stops at the theme. Positioning one element pixel-perfectly means writing CSS, and at that point a markdown slideshow has lost its main advantage. Keep each slide simple, one idea per screen, and let the theme do the design. If a slide needs a table, the Markdown table guide shows the alignment syntax every one of these tools accepts.

Common Markdown Slides Mistakes

A --- inside a slide. You wanted a divider and got a new slide. In Marp every thematic break splits, including ***, so put the divider in theme CSS or use a blank line and a heading instead.

No blank line around the separator. Slidev requires --- padded with blank lines. Worse, a --- directly under a paragraph is a setext heading underline in CommonMark, which turns the paragraph into an H2. Always leave a blank line above and below.

Presenter notes in the wrong syntax. An HTML comment is a note in Marp and Slidev but invisible in reveal.js, where notes start with Note:. Move a deck between tools and the notes vanish silently.

Markdown Slides FAQ

Writing markdown slides means one text file, a separator between slides, and a tool that renders it. Start with Marp if you want PDF and PowerPoint from a single file, or reveal.js if you want a web deck with fragments. Remember that the separators and note syntax don't travel between them. Draft the content in the editor first, then drop it into whichever tool you picked.