A `.slides` file is a presentation written as plain markdown: one text file, slides separated by `---`, speaker notes in a comment. Monofile renders it as a deck you can edit in a side panel, present full screen with a speaker window, and export as standalone HTML or an editable PowerPoint file.

## A deck is one markdown file

A deck is markdown with a thin convention on top, so everything that works on a markdown file works on a deck: the raw source, versions on every write, wiki-link embeds, share links, and any agent that can read and write text.

```md path="pitch.slides"
---
title: Monofile pitch
theme: midnight
size: 16:9
---

# Monofile
One filesystem for people and agents

<!-- notes
Thirty seconds on who we are, then straight to the demo.
-->

---
layout: two-column
id: numbers
---

## This quarter
- Three products shipped
- Churn down to 1.1%

<!-- column -->

![[charts/growth.png]]

<!-- step -->

**Ahead of plan.**

---
layout: section
skip: true
---

# Appendix
```

The pieces, top to bottom:

- **Headmatter** is an optional YAML block at the very top of the file. Its keys are `title`, `theme` (`default`, `midnight`, `paper`, `gradient`), `size` (`16:9` at 1280 by 720, the default; `4:3` at 1024 by 768; `16:10` at 1280 by 800; or any `WxH`), `author`, `paginate`, `style` (CSS appended to the theme), `transition` and `lang`.
- **Slides** are separated by a line that is exactly `---`. Separators inside fenced code and HTML comments do not count.
- **Slide frontmatter** is an optional YAML block right after the separator, closed by its own `---`. Its keys are `id` (a stable handle, recommended), `layout`, `class`, `background` (a colour, or an image path or URL), `html: true`, `src`, `skip` (not numbered), `transition`, `title`.
- **Body** is ordinary markdown: headings, lists, tables, code, images as `![[path]]` or `![alt](url)`. `<!-- step -->` between blocks reveals them one at a time; `<!-- column -->` splits a `two-column` slide.
- **Speaker notes** are a trailing `<!-- notes … -->` comment on the slide. The presenter window and the PowerPoint export show them.

Layouts are `default`, `title`, `section`, `two-column`, `image`, `quote`, `blank` and `free`. Each has an advisory word budget (20 for a title slide, 80 for a default one, 110 for two columns). A slide over budget still saves; the checker reports it.

The design box has the deck's `size` and scales uniformly to fit wherever the deck appears, so the filmstrip thumbnail, the editor stage, the presentation and the print output are the same picture at different sizes. Lay out each slide for that box, whatever window it will show in.

### Four kinds of slide

| Kind | How you get it | What it is good for |
|---|---|---|
| Markdown | The default | Almost everything. Native text in the export, checked by the linter, editable in the inspector |
| HTML fragment | `html: true` in the frontmatter | A designed slide: any HTML and CSS you write, inlined and style-isolated from the other slides |
| HTML document | A body that starts with `<!doctype html>` or `<html>` | A full page with its own scripts, rendered in its own sandboxed frame |
| File | `src: designs/hero.html` | An existing workspace file is the slide: an HTML artboard, a markdown note, an image or a video |

Paths are workspace-relative, with no leading slash, so a deck that references `designs/hero.html` keeps working when the deck moves. The checker reports a target that has moved or is missing.

### Free layout

`layout: free` is the one layout with positioned blocks, and it is still text. The slide is an `html: true` fragment where each line is a `div.mf-box` of kind `text`, `image` or `shape`, with its geometry in stage pixels in the `style` attribute. In the editor you drag and resize the boxes. In the file they are a handful of readable lines. In the PowerPoint export they become native text boxes, pictures and shapes.

## Editing by hand

A `.slides` file opens as a rendered deck with a filmstrip on the left. The toolbar carries **Add slide** (one template per layout), undo and redo, a slide counter, an issues indicator, **Export**, **Overview**, **Present**, a **Source** toggle (<kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>V</kbd>) that opens the raw markdown, and the inspector toggle (<kbd>I</kbd>).

You edit text in the **inspector**, a panel on the right. Press <kbd>I</kbd>, double-click a slide, or click a block on the stage, and the inspector opens with the caret in that block. The panel edits the current slide's body in a WYSIWYG editor that understands `<!-- step -->` markers and `![[embeds]]`, its notes, and its frontmatter (layout, background, skip, transition, id), plus deck-level fields (title, theme, size, slide numbers). Every control is a structural operation on the markdown, so what a person does in the panel and what an agent does with `slides_edit` produce the same text.

- **Images** are workspace files. The Image button, and dropping a file on the body editor, upload into an `assets/` folder next to the deck and insert `![[assets/<name>]]`. Pasted absolute URLs stay as `![alt](url)`.
- **Reorder** by dragging in the filmstrip; **delete** from the filmstrip; **undo** reverts a whole typing burst in one step.
- **Free layout** slides get a block overlay instead: **Add Text, Image or Rectangle**, drag and resize with handles (<kbd>Shift</kbd> keeps the aspect ratio, <kbd>Alt</kbd> resizes from the centre), nudge with the arrow keys (<kbd>Shift</kbd> for 10 pixels), bring forward, send backward, duplicate and delete. **Convert to free layout** turns a markdown slide into one; the conversion is one way, with an undo entry.

Saving is automatic, and every write captures a version.

## Presenting

**Present** takes the deck full screen. The keys inside a presentation:

| Key | Action |
|---|---|
| <kbd>→</kbd>, <kbd>↓</kbd>, <kbd>Space</kbd>, <kbd>Enter</kbd>, <kbd>PageDown</kbd>, <kbd>n</kbd> | Next step or slide |
| <kbd>←</kbd>, <kbd>↑</kbd>, <kbd>Backspace</kbd>, <kbd>PageUp</kbd>, <kbd>p</kbd> | Previous |
| <kbd>Home</kbd>, <kbd>End</kbd> | First and last slide |
| <kbd>O</kbd> | Overview grid |
| <kbd>S</kbd> | Open the speaker window |
| <kbd>F</kbd> | Toggle fullscreen |
| <kbd>B</kbd> or <kbd>.</kbd> | Black out the screen |
| <kbd>Esc</kbd> | Leave the overview, or exit |

The **speaker window** is a second browser window at `/present/<file id>` showing the current slide, the next slide, the notes, an elapsed timer with a reset, and the clock. It follows the presentation over a same-browser channel, so put it on the laptop screen and the presentation on the projector; a reopened window picks the state back up.

## How agents build decks

Because a deck is markdown, `write` and `edit` already work. An agent can author a whole deck in one `write`, and the CLI's `monofile write` and `monofile edit` do the same. Four dedicated tools cover the structural work, mirroring the canvas tools; the built-in assistant uses the same four. The request envelope is described in [[Calling Tools]].

### create_slides

Creates a deck from a structured spec in one call. Each slide takes `content` (markdown, or raw HTML with `html: true`, or a full HTML document), optional `notes`, `layout`, `id`, `background`, `src`, `skip` and the other frontmatter keys. Slides without an `id` get one minted. Scope `files:write`.

```http
POST /api/tools/create_slides
{
  "path": "/decks/pitch.slides",
  "title": "Monofile pitch",
  "theme": "midnight",
  "slides": [
    { "id": "intro", "layout": "title", "content": "# Monofile\nOne filesystem for people and agents", "notes": "Thirty seconds on who we are." },
    { "id": "numbers", "layout": "two-column", "content": "## This quarter\n- Three products shipped\n\n<!-- column -->\n\n![[charts/growth.png]]", "notes": "Point at the curve." }
  ]
}
```

```bash tab="CLI"
monofile slides create /decks/pitch.slides --from ./deck.json --theme midnight
```
```bash tab="curl"
curl -X POST "https://www.monofile.ai/api/tools/create_slides" \
  -H "Authorization: Bearer $MONOFILE_API_KEY" \
  -H "Content-Type: application/json" \
  -d @deck.json
```

The response carries the slide count, the created ids, a compact slide list (number, id, title, kind, layout, whether it has notes) and a `contentHash` for the next edit. A referenced file that does not exist yet is a warning, so you can write a deck and its assets in either order.

### slides_edit

Applies a batch of operations to a deck, in order, atomically: `insert_slide`, `update_slide`, `delete_slides`, `move_slide` and `set_deck`. Slides are addressed by 1-based number, by `#id`, or by `$n` and `$ref` for slides inserted earlier in the same batch. Pass the previous result's `contentHash` as `ifHash` to refuse the write if someone changed the deck in between. Scope `files:write`.

```http
POST /api/tools/slides_edit
{
  "path": "/decks/pitch.slides",
  "ops": [
    { "op": "insert_slide", "after": "#numbers", "slide": { "id": "next", "content": "## Next steps\n- Ship the desktop beta", "notes": "Close on the ask." } },
    { "op": "update_slide", "slide": "#intro", "set": { "frontmatter": { "background": "#0b0b0f" } } },
    { "op": "move_slide", "slide": "$1", "to": 2 }
  ],
  "ifHash": "1a2b3c4d-k9"
}
```

```bash tab="CLI"
monofile slides edit /decks/pitch.slides --ops ./ops.json --if-hash 1a2b3c4d-k9
```
```bash tab="curl"
curl -X POST "https://www.monofile.ai/api/tools/slides_edit" \
  -H "Authorization: Bearer $MONOFILE_API_KEY" \
  -H "Content-Type: application/json" \
  -d @ops.json
```

Inserting a slide whose `id` already exists is a no-op with a warning, so a retried step does not duplicate a slide. Errors name the operation that failed (`UNKNOWN_REF`, `SLIDE_NOT_FOUND`, `INVALID_POSITION`, `TOO_MANY_SLIDES`), and a batch with a failed operation writes nothing.

### slides_check

Reports what is wrong with a deck before anyone presents it: files that `src:`, `background:` or an image embed point at and that are missing or have moved, empty slides, duplicate ids, unknown keys, slides without notes and slides over their word budget. With `repair: true` it rewrites moved references in place. Scope `files:read`, plus `files:write` for a repair.

```http
POST /api/tools/slides_check
{ "path": "/decks/pitch.slides", "repair": true }
```

```bash tab="CLI"
monofile slides check /decks/pitch.slides --repair
```
```bash tab="curl"
curl -X POST "https://www.monofile.ai/api/tools/slides_check" \
  -H "Authorization: Bearer $MONOFILE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"path": "/decks/pitch.slides", "repair": true}'
```

The CLI exits non-zero only on an error, which today means a `src:` slide that points at nothing. Run it before calling a deck done.

:::details What the checker reports
| Code | Severity | Meaning |
|---|---|---|
| `SRC_MISSING` | error | A `src:` slide points at nothing and renders as a hole; the deck is `ok: false` |
| `SRC_STALE` | warning | The file moved (a unique match by name); repairable |
| `SRC_UNSUPPORTED` | warning | The file cannot be a slide, for example a `.canvas` board |
| `UNKNOWN_KEY`, `INVALID_VALUE`, `EMPTY_SLIDE`, `DUPLICATE_ID`, `INVALID_ID`, `HEAD_INVALID_YAML`, `FRONTMATTER_INVALID_YAML` | warning | Structure |
| `BOX_OUT_OF_STAGE`, `BOX_STYLE_NONCANONICAL` | warning, info | A free-layout box outside the stage or below its minimum size, or with a style the editor cannot read |
| `NO_NOTES`, `TOO_MANY_WORDS` | info | Advice |

A missing image in a markdown slide is a warning. The response also counts references as `total`, `ok`, `stale`, `missing` and `unsupported`.
:::

### slides_export

Turns a deck into a file in the workspace. `format` is `html` or `pptx`; `output` defaults to the deck's path with the new extension and must end in that extension; `overwrite` replaces an existing output instead of failing with `FILE_EXISTS`. Scope `files:write`.

```http
POST /api/tools/slides_export
{ "path": "/decks/pitch.slides", "format": "pptx", "output": "/exports/pitch.pptx", "overwrite": true }
```

```bash tab="CLI"
monofile slides export /decks/pitch.slides --format pptx --output /exports/pitch.pptx --overwrite
```
```bash tab="curl"
curl -X POST "https://www.monofile.ai/api/tools/slides_export" \
  -H "Authorization: Bearer $MONOFILE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"path": "/decks/pitch.slides", "format": "pptx", "output": "/exports/pitch.pptx", "overwrite": true}'
```

## Exporting

| Format | Where | What you get |
|---|---|---|
| Standalone HTML | **Export** in the editor, or `slides_export` with `format: "html"` | One self-contained document from the same renderer as the editor, with file and image references resolved. It keeps `#/3` style deep links |
| PDF | **Export** then **Print / PDF** in the editor | The deck printed one slide per page from inside the frame. Choose "Save as PDF" in the dialog; Chrome gives the best result |
| PowerPoint | `slides_export` with `format: "pptx"`, or `monofile slides export --format pptx` | An editable `.pptx`: markdown slides become native text boxes with the theme colours and speaker notes, images are placed, free-layout boxes become real text, pictures and shapes |

A `.pptx` export is an attachment file in your workspace, shown as a download card. HTML fragment, HTML document and `src: *.html` slides cannot become native PowerPoint objects, so each becomes a titled text placeholder in the file and a warning in the response. PDF comes from the editor's print dialog only; the export tool does not produce it.

> [!NOTE]
> A deck holds at most 300 slides, 2 MB per slide and 8 MB in total. Well before that limit, a shorter deck reads better: one idea per slide, detail in the notes.

> [!WARNING]
> Four parser rules for writing a deck by hand. A file that starts with `---` has a headmatter, so a deck cannot begin with a slide's frontmatter. A `---` directly after the headmatter means "the slides start here", not an empty first slide. Two separators in a row in the middle of a deck do make an empty slide, and the checker reports it. A `key: value` first line is only frontmatter when a closing `---` follows with no blank line in between; otherwise it is body text.

## Next steps

:::cards
- [[Canvas Boards]] — Spatial boards of live file nodes, notes, links, groups and labelled edges.
- [[HTML Files]] — HTML files with live preview, and artboard rendering on canvas.
- [[Supported File Types]] — The full extension to editor map, and what each editor can do.
- [[CLI Commands]] — Every command, flag, JSON output shape and exit code.
- [[The AI Assistant]] — What the built-in assistant is, what it can touch, and the two modes.
:::
