lecture.studio

marp-cli config, watch mode, server mode and engines

Past the first marp deck.md --pdf, marp-cli has four features that make it a course workflow: a config file (.marprc or marp.config.js) holding the theme set, HTML setting and options so every command is short; --watch to rebuild on save; --server to serve a folder of decks; and --engine for markdown-it plugins. This guide shows each with the exact file or flag, then a Makefile.

The config file

marp-cli reads marp.config.js (also .mjs/.cjs), .marprc (JSON or YAML), or a marp key in package.json, from the current folder. For a course:

# .marprc.yml
themeSet: ./themes
allowLocalFiles: true
html: true
pdfOutlines: true
options:
  emoji:
    unicode: false

Then marp slides/week-05.md --pdf uses the themes, allows local images, enables HTML and adds PDF bookmarks without repeating the flags. options are Marp Core constructor options (math, emoji, and so on). A different config for a different job: marp -c student.yml ….

Watch mode

marp -w slides/week-05.md

Rebuilds the HTML on every save. With --pdf it rebuilds the PDF, which is slower but shows the real page breaks. Pair it with a browser tab on the output file and reload, or use the preview window:

marp -p slides/week-05.md

--preview opens a window that reloads on change and can be presented from as an immersive window (it is not available in the Docker image).

Server mode

marp -s slides/

Serves the folder on a local port: open the URL, click a deck, and it converts on request; edits show on reload. Query parameters pick a format (?pdf, ?pptx). It is the quickest way to browse a term's decks without building anything, and a reasonable "presentation server" for a lab machine.

Whole-folder conversion

marp -I slides -o dist --pdf

--input-dir converts every Markdown file under slides, keeping the structure, into dist. This is the CI command; see publishing on GitHub Pages.

Engines

An engine file customises the Marp instance: extra markdown-it plugins, custom directives, changed rendering.

// engine.mjs
export default ({ marp }) => marp.use(myMarkdownItPlugin);
marp --engine ./engine.mjs deck.md

Two engines on this site that were tested with marp-cli 4.5: one that renders Mermaid diagrams and one that drops slides marked hidden. Put engine: ./engine.mjs in the config file to use one by default.

A course Makefile

SLIDES := $(wildcard slides/*.md)
PDFS   := $(patsubst slides/%.md,dist/%.pdf,$(SLIDES))
HTMLS  := $(patsubst slides/%.md,dist/%.html,$(SLIDES))

all: $(PDFS) $(HTMLS)

dist/%.pdf: slides/%.md themes/*.css
	marp $< -o $@ --pdf

dist/%.html: slides/%.md themes/*.css
	marp $< -o $@

watch:
	marp -w -I slides -o dist

serve:
	marp -s slides

clean:
	rm -rf dist

With the config file holding the flags, the recipes stay one line each, and make only rebuilds the decks that changed.

The other flags worth knowing

The full list is marp --help; the cheat sheet has the ones a slide author uses.

FAQ

Where does marp-cli look for a config file?

marp.config.js (.mjs, .cjs), .marprc (JSON or YAML) or the marp key in package.json, in the current directory; -c path names another.

How do I make marp-cli rebuild on save?

marp -w deck.md (watch), or marp -p deck.md for a preview window that reloads.

What does marp-cli server mode do?

marp -s folder/ serves the folder; each Markdown file converts on request in the browser, with ?pdf and ?pptx for other formats.

How do I convert all decks in a folder?

marp -I slides -o dist --pdf, which keeps the folder structure in dist.