A tiny, zero-dependency CLI that augments Marp decks.
The first command, agenda, inserts an agenda recap slide before each
heading section — highlighting where you are, dimming what's next, and
checking off what's done.
npx marplux agenda slide.md -o dist/slide.mdNo install required. Zero runtime dependencies.
Write a normal Marp deck. Every ## heading becomes an agenda item, and
marplux agenda inserts a recap slide just before it:
## Purpose → <!-- _class: agenda -->
# Agenda
<ol class="agenda">
<li class="is-done">Intro</li>
<li class="is-active">Purpose</li>
<li class="is-upcoming">Wrap-up</li>
</ol>
---
## PurposeThe transform is idempotent: it strips the slides it generated before regenerating, so you can run it as many times as you like.
marplux only emits markup and the CSS classes is-done / is-active /
is-upcoming — styling is up to your Marp theme.
marplux agenda <input.md> [options]| Option | Description |
|---|---|
-o, --output <file> |
Write to <file> (and create parent dirs) instead of stdout. |
--check |
Exit non-zero if <file> is not already up to date. Writes nothing. Great for CI. |
--heading-level <n> |
Heading level that defines an agenda item (default: 2). |
--title <text> |
Title shown on each recap slide (default: Agenda). |
--class <name> |
CSS class for the recap slide and its list (default: agenda). |
-h, --help |
Show help. |
-v, --version |
Show the version. |
Read from stdin with -:
cat slide.md | marplux agenda - > dist/slide.mdWrite these HTML comments inside a slide to control behavior:
<!-- agenda-skip -->— exclude that section from the agenda.<!-- agenda-overview -->— a placeholder slide expanded into the full agenda list (no item emphasised).
Commit the generated deck and verify it in CI:
marplux agenda slide.md -o dist/slide.md --checkmarplux only emits markup — but it ships a matching flat / modern Marp
theme so the engine and its styling stay in sync. The CSS is an inert static
asset (no runtime dependency, not bundled into the JS).
Available themes (all under node_modules/marplux/themes/):
@theme name |
Look |
|---|---|
marplux-base |
Understated slate — the shared foundation. |
marplux-blue |
Flat, vivid blue. Built on marplux-base. |
Register the directory with --theme-set, then pick a theme from front
matter. Registering the folder (not a single file with --theme) is what
lets the theme: directive choose — and it resolves the @import a color
variant makes into marplux-base:
marplux agenda examples/deck.md -o dist/deck.md
marp dist/deck.md --theme-set node_modules/marplux/themes -o dist/deck.html---
theme: marplux-blue # matches the `/* @theme marplux-blue */` header
---
--theme <file.css>also works but forces that one theme and ignores thetheme:directive. Use--theme-set <dir>when you want the front matter to decide. In the VS Code Marp extension, add the file tomarkdown.marp.themesinstead.
A runnable deck lives in examples/deck.md.
Structure lives once in marplux-base; colors are role-based CSS custom
properties. A new palette is a thin file that imports the base and remaps a few
variables:
/* @theme marplux-green */
@import 'marplux-base';
:root {
--c-heading: #14532d;
--c-accent: #16a34a;
--c-accent-deep: #15803d;
}The theme styles the classes marplux agenda emits (ol.agenda +
is-done / is-active / is-upcoming) and the _class: lead / section
slides. The is-* state classes are fixed, so keep --class at its default
agenda for the theme selectors to match.
import { buildDeck } from "marplux";
const out = buildDeck(markdown, { headingLevel: 2, title: "Agenda" });Requires pnpm. Node is pinned via Volta.
pnpm install
pnpm test # vitest
pnpm typecheck
pnpm build # tsup -> dist/Tests are written strictly TDD-first. Releases are managed with
Changesets: add one with
pnpm changeset, and merging the generated "Version Packages" PR publishes
to npm.