Johannes Kaindl1k downloadsTurn a Markdown note into a slide deck and export it to PDF or a PNG image series, with live readability checks.
🇬🇧 English · 🇩🇪 Deutsch
Turn a Markdown note into a slide deck and export it to PDF or a PNG image series, with live readability checks.
kami 紙 (light, default), kogane 黄金 (dark), sumi 墨 (true-black, high-contrast), kairo 回路 (dark, cyan), kurenai 紅 (dark, red); plus the crimson 紅 family in four modes (crimson-dark, crimson-dark-lc, crimson-light, crimson-light-lc), which adds a serif display face over a mono body and a faint scanline the low-contrast modes dim. Selected per deck via the theme: frontmatter key; each carries a matching code-highlight and Mermaid theme. Legacy 0.4.x keys (default, dark, serif, high-contrast) still work — they resolve silently to their Nordstern successor.from frontmatter / from default / ● unsaved) that shows where the active theme comes from, and a Set button that writes theme: directly into the note's frontmatter. Frontmatter is the source of truth; the Settings default applies only to notes without a theme: key..css files into a configurable themes folder (default Slide-Deck-Themes/); the frontmatter theme: value is the filename without the .css extension. Each file is a --sd-* token block with optional extra CSS on top of the plugin's design system (type scale, spacing, rhythm) — a 7-token theme already looks finished; user themes inherit the kami theme's code-highlight and Mermaid styles unless overridden. See the theming guide. The Settings tab shows all valid theme keys live..css starting point; a toggle hides the themes folder in Obsidian's file explorer.default, title, section, quote, image-focus, two-column, columns-3, stat, cover-image, agenda, threads, closing — set per slide with a layout directive (an HTML comment); columns are separated by a column directive, and in multi-column templates the leading heading spans all columns. See the layout guide.compact (tighter type) or code-heavy (smaller code) to any template in the same layout directive.section, a lone block quote becomes quote, a lone image or diagram becomes image-focus, and column splits pick two-column / columns-3. An explicit layout directive always wins.header:, footer:, and paginate: frontmatter keys render as floating corner slots on every slide (pagination shows n / N).object-fit: contain), for both Obsidian embeds (![[…]]) and standard Markdown images.---; YAML frontmatter controls theme, aspect ratio, and font floor per note.minFontPx); slides that would need smaller text are flagged as overflowing instead of becoming unreadable.modern-screenshot and writes numbered PNGs into a configurable export folder (Settings, default Slide-Deck-Export/); typographically accurate inter-word spacing.$…$ / $$…$$) rendered by KaTeX.> [!note], [!warning], [!danger], [!tip], [!info] blocks rendered with redundant coding: border color + geometric shape + visible label word (not color-only; satisfies WCAG 1.4.1).```mermaid ``` blocks rendered as SVG, per-theme.slide-image code block renders as a card with a generate button; on click it calls the neighbor plugin to produce and save an image, then replaces itself with a normal embed plus a prompt comment for re-rolling later.The note and its projection. The deck renders in a side panel and carries the toolbar: theme picker, where the active theme comes from, and the two export paths.
Nine built-in themes. The same slide in each — only colour, type and accent change; the structure is theme-independent.
Twelve per-slide templates. Set one with a layout directive, or let the layout be inferred
from the slide's shape. The grid shows the nine general ones; agenda, threads and closing follow below and are described in the layout guide.
Fit-or-warn. A slide that would need text below the legibility floor is flagged in the preview instead of being silently clipped.
Accessible callouts. Meaning is carried three ways at once — border colour, geometric shape, and a visible label word.
Settings. The tab lists every valid theme: value live, including themes you drop into
the themes folder yourself.
Click the preview for the full-resolution image.
minAppVersion; API keys live in Obsidian's secret storage, which arrived with 1.11.4). From 1.13.0 the settings tab uses the declarative settings API; older versions get the same settings through a classic fallback.isDesktopOnly: false) — runs on desktop (Windows, macOS, Linux) and on mobile (iOS/iPadOS); desktop-only APIs are platform-guarded.<export-folder>/<note-name>.pdf directly, one page per slide at the slide size, without the system print dialog. If saving fails, the system print dialog opens instead (choose "Save as PDF").<export-folder>/<note-name>.html.Slide-Deck-Export/). PDF export on desktop writes into the same folder (<note-name>.pdf).Via AnySource Sideloader, which installs and updates plugins from any git forge. Subscribe to the plugin catalog once under Settings → AnySource Sideloader → Catalogs → Add:
https://git.jkaindl.de/jkaindl/obsidian-catalog/raw/branch/main/catalog.json
Slide Deck then appears in the sideloader's plugin list and updates like any other plugin. Version checks go live to this repository's releases — the catalog only lists what exists, it never serves the files itself. To install just this one plugin without the catalog, add its repository URL as a source instead: https://github.com/johannes-kaindl/slide-deck.
main.js, manifest.json, and styles.css from the latest release..obsidian/plugins/slide-deck/ inside your vault.git clone https://git.jkaindl.de/jkaindl/slide-deck.git
cd slide-deck
npm install
npm run build # produces main.js
cp main.js manifest.json styles.css /path/to/vault/.obsidian/plugins/slide-deck/
---.---
theme: kami
aspect: "16:9"
minFontPx: 24
header: My talk
paginate: true
---
# First slide
---
# Second slide
Per-slide layout is chosen with a layout directive — an HTML comment on its own line:
<!-- layout: two-column compact -->
# Heading spanning both columns
Left column content.
<!-- column -->
Right column content.
Omit the directive and the layout is inferred from the slide's shape. The full template and modifier reference is in the layout guide.
Requires the local-image-generator plugin (desktop only). Run Insert image slot (command palette), pick one of six image functions (documentary, analytical, metaphorical, emotional, navigational, decorative) — each steers the prompt with its own style suffix — and write a prompt:
```slide-image
funktion: metaphorical
A single lantern in fog, one clear light source
```
The block renders as a card with a Generate button. Clicking it asks the neighbor plugin for an image, saves it per that plugin's own settings, and replaces the block with a plain embed plus a prompt comment (so a later re-roll has something to start from):
<!-- image: metaphorical | A single lantern in fog, one clear light source -->
![[lantern-fog.png]]
Without local-image-generator installed and enabled, the card shows an empty state instead
of a button.
| Setting | Key | Default | Description |
|---|---|---|---|
| Default theme | defaultTheme |
kami |
Preset used when a note has no theme frontmatter directive |
| Minimum body font size (px) | minFontPx |
24 |
Legibility floor — slides that would need smaller text are flagged as overflowing |
| Image export scale | imageScale |
2 |
Pixel multiplier for PNG export (2 = 2×, crisp on HiDPI screens) |
| Custom CSS | customCss |
(empty) | CSS appended to the deck styles in preview and exports, for branding or tweaks |
| Image export folder | exportFolder |
Slide-Deck-Export |
Vault folder for the PNG image-series export |
| Themes folder | themesFolder |
Slide-Deck-Themes |
Vault folder scanned for user .css themes |
| Hide themes folder in file explorer | hideThemesFolder |
true |
Hide the themes folder in Obsidian's file explorer |
| Image functions | imageSuffixes |
(built-in defaults) | One editable prompt suffix per image function (blank restores the default) |
Add a YAML frontmatter block at the top of your note to control presentation-level settings:
---
theme: kogane
aspect: 16:9
minFontPx: 24
header: My talk
footer: ACME Corp
paginate: true
---
| Key | Values | Description |
|---|---|---|
theme |
kami · kogane · sumi · kairo · kurenai · crimson-dark · crimson-dark-lc · crimson-light · crimson-light-lc · user-theme-key (legacy default/dark/serif/high-contrast still resolve) |
Visual preset name; user theme key = the .css filename without the extension |
aspect |
16:9 (default), 4:3 |
Canvas size: 1280×720 (16:9) or 960×720 (4:3) |
minFontPx |
any positive number | Per-note legibility floor; overrides the plugin setting |
header |
any text | Floating header slot shown on every slide |
footer |
any text | Floating footer slot shown on every slide |
paginate |
true · yes · on |
Show a page indicator (n / N) on every slide |
Twelve per-slide templates (default, title, section, quote, image-focus, two-column, columns-3, stat, cover-image, agenda, threads, closing), combinable density modifiers (compact, code-heavy), the layout and column directives, and smart layout inference are documented in the Slide layouts & syntax guide.
Use a line containing only --- to split slides:
---
theme: kami
aspect: 16:9
---
# Slide 1
Content here.
---
# Slide 2
More content.
Note: the --- in the YAML frontmatter block is the standard YAML delimiter and is not a slide separator.
--- lines into individual slide bodies. A YAML frontmatter block (if present) sets deck-level directives.minFontPx (the legibility floor). If the content would still overflow at that scale, the slide is flagged with a warning in the preview pane rather than scaled further.modern-screenshot (domToCanvas) capture (PNG). On desktop, PDF is rendered by the kit's print module (a hidden <webview>, @page sized to the slide) and saved as a file, with the system print dialog as fallback; on mobile, a self-contained HTML file is written to the vault and handed to the OS via openWithDefaultApp.The Generate presentation from note command sends note content to an OpenAI-compatible
LLM endpoint that you configure (default http://localhost:1234, i.e. a local LM Studio).
No cloud service is involved unless you point the endpoint at one (or the LLM Endpoint Manager hands you a Claude endpoint: then the note's content goes to Anthropic) — the settings tab holds an
ordered list of endpoints, tried in order, and each row can carry its own optional API key,
so a local server and a hosted provider (e.g. OpenRouter) can sit side by side in the same list. The model is chosen per row as well; there is no separate global model setting. The Generate tab carries a model row (the model list of the active endpoint, Automatic, a refresh button and the thinking toggle): a model picked there is the same choice as in the settings, and while a deck is being generated the row is not offered.
API keys are not stored in the plugin's data.json: they go into Obsidian's secret storage (Settings → Keychain), and a plain-text key from an older version is moved there on first start.
If the LLM Endpoint Manager plugin is installed, the endpoints (and their keys) come from it instead: the settings tab then offers an endpoint and model choice, and your local list stays as a fallback for when the manager is off. The manager can also provide Claude (native Messages API) as an endpoint; it takes no temperature, so the plugin sends none, and "thinking off" means the lowest effort. With a Claude endpoint the content of the note you generate from is sent to Anthropic.
Streaming runs over XMLHttpRequest under the Obsidian origin, so the endpoint must allow
cross-origin requests. LM Studio's CORS toggle must be on; Ollama needs
OLLAMA_ORIGINS=app://obsidian.md (or *). If the endpoint answers the reachability ping but
refuses the stream, the plugin automatically falls back to a non-streaming request (you lose
the live token view, but the deck still generates).
Code: AGPL-3.0-or-later — a commercial license is available on request, see LICENSING.md.
Documentation: CC BY-SA 4.0.
Author: Johannes Kaindl — https://jkaindl.de