# MarpUI

A single-user web application for creating, managing, editing, and presenting [MARP](https://marp.app/) markdown slide presentations. Built by [squarecows](https://squarecows.com).

## Features

- **Monaco code editor** — Write MARP markdown with syntax highlighting, autocompletion, and live single-slide preview
- **Extended markdown** — Subscript, superscript, highlights, footnotes, definition lists, task lists, abbreviations, and more via markdown-it plugins
- **Mermaid diagrams** — Embed flowcharts, sequence diagrams, gantt charts, and more using [Mermaid](https://mermaid.js.org/) syntax
- **GitHub-style alerts** — NOTE, TIP, IMPORTANT, WARNING, and CAUTION callout blocks
- **Syntax highlighting** — Code blocks with highlight.js in the preview
- **Theme management** — Ships with all official MARP themes (default, gaia, uncover) plus custom CSS theme import with live editing and auto-detected theme classes
- **Multi-format export** — Export to HTML, PDF, and PowerPoint (PPTX) via `@marp-team/marp-cli` with custom theme support
- **Dual-screen presentation** — Fullscreen slideshow in one window, presenter view with speaker notes, next slide preview, and timer in another. Synced via BroadcastChannel
- **Speaker notes** — Add `<!-- notes -->` comments in your markdown, visible in the presenter view with a pause/reset timer
- **Application menu bar** — File, Preferences, Insert, Image, Layout, Theme, and Help menus with keyboard shortcuts
- **Slide management** — Thumbnail strip with drag-to-reorder, add slide, and click-to-navigate
- **Content overflow detection** — Warning badge when slide content exceeds the slide boundary
- **Plugin support** — Install and manage markdown-it plugins to extend MARP capabilities
- **AI integration (MCP)** — Built-in Model Context Protocol server lets AI assistants like Claude Desktop create, edit, and manage slide decks remotely
- **Fully offline** — All assets (fonts, icons, mermaid.js) bundled locally. No external network requests after install
- **Per-deck directories** — Each new deck gets its own folder, keeping images and assets isolated. Legacy flat decks are supported transparently with an optional migrate button
- **Bundled theme fonts and assets** — Drop `.woff2` / `.woff` / `.ttf` / `.otf` files into a theme's `fonts/` folder (or a deck's) for auto-discovered `@font-face` rules; drop images into a theme's `assets/` folder and reference them as `url('./assets/X')` from your theme CSS
- **Cross-platform** — Runs on macOS, Linux, and Windows; stores files in your Documents folder by default

## Screenshots

### Editor with live preview
Split-pane view with Monaco code editor and live slide preview. The slide strip at the bottom lets you navigate, reorder, and add slides.

![MarpUI Editor - title slide](https://codeberg.org/ric_harvey/marp-ui/raw/branch/main/docs/screenshots/editor-1.png)

![MarpUI Editor - two-column layout](https://codeberg.org/ric_harvey/marp-ui/raw/branch/main/docs/screenshots/editor-2.png)

### Presenter view
Dual-screen presenter mode with current slide, next slide preview, speaker notes, and a timer with pause/reset controls.

![MarpUI Presenter View](https://codeberg.org/ric_harvey/marp-ui/raw/branch/main/docs/screenshots/presenter.png)

## Install

```bash
npm install -g marp-ui
```

That's it. MarpUI builds automatically and creates a desktop shortcut:

- **macOS** — MarpUI.app in /Applications with a menu bar icon to stop the server
- **Windows** — Start Menu shortcut
- **Linux** — .desktop entry in your applications menu

### Launch

```bash
marp-ui
```

Or launch from your applications menu / Launchpad / Start Menu. Your browser opens automatically at `http://localhost:3000`.

### Requirements

- **Node.js** 20 or later
- **A modern browser** for the editor UI (Chrome, Firefox, Edge, Safari)
- **Chrome, Edge, or Firefox** installed locally for PDF and PPTX export
- **Xcode Command Line Tools** (macOS only, for the menu bar helper)

### Uninstall

```bash
npm uninstall -g marp-ui
```

This removes the desktop shortcut and stops any running server.

## Development

```bash
# Clone and install
git clone https://codeberg.org/ric_harvey/marp-ui.git
cd marp-ui
npm install
cd client && npm install && cd ..

# Development mode (hot-reload)
npm run dev
```

The frontend opens at `http://localhost:5173`. The Express API runs on port 3000 and is proxied by Vite.

### Production Build

```bash
npm run build
npm start
```

In production, Express serves both the API and the built frontend on port 3000.

## Usage

### Creating a Deck

1. Navigate to the **Decks** page (home)
2. Enter a title and click **Create**
3. The editor opens with a starter slide

### Editing

- **Code editor** — Write MARP markdown in the left pane. Slides are separated by `---`
- **Preview** — The right pane shows a live-rendered preview of the current slide
- **Save** — Ctrl/Cmd+S for manual save, or auto-saves every 30 seconds (configurable)
- **Navigate slides** — Ctrl/Cmd+Up/Down to jump between slides, or click thumbnails in the slide strip
- **Insert menu** — Quick-insert markdown syntax, alerts, diagrams, and speaker notes
- **Image menu** — Insert images with sizing, filters (blur, brightness, grayscale, etc.), and background options
- **Layout menu** — Slide directives (pagination, headers, footers), backgrounds, and style classes

### Presenting

Click the **Present** button in the menu bar to choose:

- **Fullscreen** — Opens a new window with just the slides. Click anywhere to enter fullscreen, click to advance, use arrow keys to navigate, Escape to exit
- **Presenter View** — Opens the slideshow in a new window AND shows the presenter view in the current tab with current slide, next slide preview, speaker notes, and a timer with pause/reset

Both windows stay synchronised — navigate from either one.

### Speaker Notes

Add HTML comments anywhere in a slide to create speaker notes:

```markdown
# My Slide

Content here

<!-- These are speaker notes visible only in the presenter view -->
```

### Mermaid Diagrams

Use fenced code blocks with the `mermaid` language tag:

````markdown
```mermaid
flowchart TD
    A[Start] --> B{Decision}
    B -->|Yes| C[Action]
    B -->|No| D[End]
```
````

> Note: Mermaid diagrams render in the preview and presentation but may not appear in PDF/PPTX exports. A warning dialog appears when exporting decks containing mermaid blocks.

### Exporting

Use **File > Export as HTML/PDF/PPTX** from the menu bar. Files download automatically.

> PDF and PPTX export require a locally installed browser (Chrome, Edge, or Firefox). Custom themes are included in exports automatically.

### Themes

- Select a theme from the **Theme** menu while editing
- Go to **Preferences > Themes** to import custom CSS themes or edit existing ones
- Theme classes are auto-detected and available in the **Layout > Style** column
- The theme editor previews your live (unsaved) CSS against one slide per detected variant class (`title`, `inverse`, `accent`, etc.) so you can see all the variants at once

#### Custom Fonts

Drop font files into a fonts folder and they're auto-discovered — no manual `@font-face` writing required:

- **Per-theme fonts** — `~/Documents/MarpUI/themes/{theme-name}/fonts/Inter-Bold.woff2`. Every deck using that theme inherits the font.
- **Per-deck fonts** — `~/Documents/MarpUI/decks/{deck-stem}/fonts/Inter-Bold.woff2`. Scoped to that deck only. Deck-local fonts override theme fonts of the same family/weight/style.

Supported formats: `.woff2`, `.woff`, `.ttf`, `.otf`. Filename conventions drive weight/style detection (Google Fonts naming works):

| Filename | Family | Weight | Style |
|---|---|---|---|
| `Inter-Regular.woff2` | Inter | 400 | normal |
| `Inter-Bold.woff2` | Inter | 700 | normal |
| `Inter-BoldItalic.woff2` | Inter | 700 | italic |
| `Inter-700italic.woff2` | Inter | 700 | italic |
| `knile-bold-webfont.woff2` | knile | 700 | normal |

Each font is registered under both the parsed family (`font-family: "Inter"; font-weight: 700`) and the literal filename stem (`font-family: "Inter-Bold"`), so either CSS pattern works. The `-webfont` and `-web` suffixes are stripped.

Fonts work in editor preview, deck-list thumbnails, presentation views, and HTML/PDF/PPTX exports.

#### Theme Assets (images, icons, backgrounds)

Bundle images with a theme and reference them in the theme CSS:

```
~/Documents/MarpUI/themes/{theme-name}/
├── {theme-name}.css
├── fonts/                  ← auto-discovered fonts
└── assets/                 ← image files
    ├── background.png
    ├── logo.svg
    └── icon-warning.png
```

In your theme CSS:

```css
section.title {
  background-image: url('./assets/background.png');
}
.warning::before {
  content: url('./assets/icon-warning.png');
}
```

Supported formats: `.png`, `.jpg`, `.jpeg`, `.gif`, `.svg`, `.webp`, `.bmp`, `.ico`.

The theme editor has a bottom **Assets** strip — drag-and-drop image files to upload, click a thumbnail to copy the `url('./assets/...')` CSS reference to your clipboard, or click `×` to delete.

Asset references resolve correctly in every render path: editor preview, deck-list thumbnails, presentation views, and exports. HTML exports embed assets as data URIs so the file is self-contained.

> **Note:** Built-in themes (`default`, `gaia`, `uncover`) cannot bundle fonts or assets. Create or import a custom theme first. Legacy flat themes (`themes/{name}.css`) auto-migrate to subdirectory layout the first time you upload a font or asset.

### Plugins

- Go to **Preferences > Plugins** and enter an npm package name (e.g., `markdown-it-footnote`)
- Click **Install** — the plugin is loaded into the MARP rendering pipeline
- Toggle plugins on/off or remove them without restarting

## AI Integration (MCP Server)

MarpUI includes a built-in [Model Context Protocol](https://modelcontextprotocol.io/) server that lets AI assistants like Claude Desktop create, edit, and manage your slide decks.

### Enabling

Enable via either method (restart required):

1. **Settings UI** — Go to Preferences > Settings and tick "Enable MCP server"
2. **Environment variable** — Start with `MARP_MCP_ENABLED=1 marp-ui`

Once enabled, the MCP endpoint is available at `http://localhost:3000/mcp` using Streamable HTTP transport.

### Connecting from Claude Desktop

Add this to your Claude Desktop MCP configuration (`claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "marp-ui": {
      "command": "npx",
      "args": ["mcp-remote", "http://localhost:3000/mcp"]
    }
  }
}
```

### Available Tools

| Tool | Description |
|------|-------------|
| `list_decks` | List all slide decks with metadata |
| `get_deck` | Read the full markdown of a deck |
| `create_deck` | Create a new slide deck |
| `update_deck` | Update deck markdown content |
| `delete_deck` | Delete a deck (moves to trash) |
| `rename_deck` | Rename a deck (updates title and filename) |
| `list_themes` | List available themes |
| `get_theme` | Read custom theme CSS |
| `create_theme` | Import a new custom theme |
| `update_theme` | Update custom theme CSS |
| `delete_theme` | Delete a custom theme |
| `migrate_theme` | Migrate a legacy flat theme into subdirectory layout |
| `upload_image` | Upload a base64-encoded image (optionally scoped to a deck) |
| `list_images` | List image files (optionally scoped to a deck) |
| `list_fonts` | List fonts available for a deck (deck-local + active theme) with parsed family/weight/style |
| `upload_deck_font` | Upload a base64-encoded font to a deck's `fonts/` folder |
| `upload_theme_font` | Upload a base64-encoded font to a theme's `fonts/` folder (auto-migrates flat themes) |
| `list_theme_assets` | List image assets bundled with a theme |
| `upload_theme_asset` | Upload a base64-encoded image to a theme's `assets/` folder (auto-migrates flat themes) |
| `delete_theme_asset` | Delete a single theme asset by filename |
| `render_markdown` | Render MARP markdown to HTML/CSS |

### Example Usage

Once connected, you can ask Claude to:

- "Create a 10-slide deck about Kubernetes architecture"
- "Add speaker notes to all slides in my-deck.md"
- "Create a custom dark theme with blue accents"
- "Add a diagram showing our CI/CD pipeline to the DevOps deck"

## Keyboard Shortcuts

| Action | Shortcut |
|--------|----------|
| Save | Ctrl+S |
| Next slide (editor) | Ctrl+Down |
| Previous slide (editor) | Ctrl+Up |
| Keyboard shortcuts | Ctrl+/ |
| Next slide (presentation) | Right / Space / PageDown |
| Previous slide (presentation) | Left / PageUp |
| Exit presentation | Escape |

## Configuration

Settings are stored in `~/Documents/MarpUI/config.json` and can be edited via **Preferences > Settings**:

| Setting | Default | Description |
|---------|---------|-------------|
| `storagePath` | `~/Documents/MarpUI` | Root directory for decks, themes, plugins |
| `autoSaveInterval` | `30` | Auto-save interval in seconds |
| `preferredBrowser` | `auto` | Browser for PDF/PPTX export (`chrome`, `edge`, `firefox`, `auto`) |
| `defaultTheme` | `default` | Theme applied to new decks |
| `mcpEnabled` | `false` | Enable the MCP server endpoint at `/mcp` |
| `editor.fontSize` | `14` | Editor font size |
| `editor.tabSize` | `2` | Editor tab size |
| `editor.wordWrap` | `true` | Enable word wrap in editor |

You can also set `MARP_UI_STORAGE` environment variable to override the storage path, `PORT` to change the API server port, or `MARP_MCP_ENABLED=1` to enable the MCP server.

### Deck Storage Layout

New decks are created in their own subdirectory with images stored alongside:

```
~/Documents/MarpUI/decks/
  my-presentation/
    my-presentation.md
    diagram.png
  another-deck/
    another-deck.md
    photo.jpg
```

Legacy flat decks (`decks/my-deck.md`) are still supported. Use the **Migrate** button on the deck card to move a legacy deck into its own folder — referenced images are copied or moved automatically.

## Project Structure

```
server/                Express.js backend (TypeScript)
  index.ts             Entry point — server startup, routing, graceful shutdown
  mcp.ts               MCP server — tools, transport, and Express handlers
  lib/                 Config, storage, browser detection, plugin loader
  lib/plugins/         Custom markdown-it plugins (GitHub alerts, syntax highlight, mermaid)
  routes/              REST API (decks, render, export, themes, plugins, settings)
client/                React SPA (Vite + TypeScript + Tailwind CSS)
  src/pages/           DeckList, Editor, Slideshow, PresenterView, ThemesPage, etc.
  src/components/ui/   Radix NavigationMenu (shadcn pattern)
  src/lib/             API client, editor context, utilities
  public/vendor/       Bundled offline assets (Font Awesome, Inter, JetBrains Mono)
openspec/              Design documents and specs
```

## Built With

- [MARP](https://marp.app/) — Markdown to slide conversion
- [Mermaid](https://mermaid.js.org/) — Diagram rendering
- [Monaco Editor](https://microsoft.github.io/monaco-editor/) — Code editor
- [React](https://react.dev/) + [Vite](https://vite.dev/) — Frontend
- [Express](https://expressjs.com/) — Backend
- [Radix UI](https://www.radix-ui.com/) — Menu components
- [Tailwind CSS](https://tailwindcss.com/) — Utility styles
- [Font Awesome](https://fontawesome.com/) — Icons
- [highlight.js](https://highlightjs.org/) — Syntax highlighting

## License

MIT
