<!-- plank help: deck | updated 2026-09-18 | summary: The build route for a slide deck in one short page: download the builders into /workspace/scripts/deck/, put the build script beside them, run the QA before handing anything over, and never write a file under the builders' names yourself. -->

# Build a deck: the route

The whole route, in one block. Everything below explains it.

```bash
mkdir -p /workspace/scripts/deck
curl -sSfL -o /workspace/scripts/deck/plank_deck.py    https://plank.md/help/assets/plank_deck.py
curl -sSfL -o /workspace/scripts/deck/plank_deck_qa.py https://plank.md/help/assets/plank_deck_qa.py
# write /workspace/scripts/deck/build_<name>.py, importing `from plank_deck import *`
python3 /workspace/scripts/deck/build_<name>.py
python3 /workspace/scripts/deck/plank_deck_qa.py /workspace/<name>.pptx   # must exit 0
```

The build route for a slide deck, start to finish. The house style, the slide primitives and the palettes are on the long page — [How Plank builds a slide deck](/help/presentations.md). This page is the route: get the builder, run it, check it, hand it over.

## 1. The builders live in `/workspace/scripts/deck/`

Download [plank.md/help/assets/plank_deck.py](https://plank.md/help/assets/plank_deck.py) and [plank.md/help/assets/plank_deck_qa.py](https://plank.md/help/assets/plank_deck_qa.py) with `curl -sSfL -o` into /workspace/scripts/deck/ — always that directory, never the current one — a bash call does not inherit the previous call's working directory, so a bare `curl -o plank_deck.py` lands wherever that one call happened to start and the next call cannot find it.

```bash
mkdir -p /workspace/scripts/deck
curl -sSfL -o /workspace/scripts/deck/plank_deck.py     https://plank.md/help/assets/plank_deck.py
curl -sSfL -o /workspace/scripts/deck/plank_deck_qa.py  https://plank.md/help/assets/plank_deck_qa.py
```

Add `plank_slides.py` for the HTML → PDF route, and `plank_deck_edit.py` when you are editing a deck somebody else designed:

```bash
curl -sSfL -o /workspace/scripts/deck/plank_slides.py    https://plank.md/help/assets/plank_slides.py
curl -sSfL -o /workspace/scripts/deck/plank_deck_edit.py https://plank.md/help/assets/plank_deck_edit.py
```

`/workspace/scripts/deck/` is a workspace folder, so it persists across restarts and both a private and a shared chat see it. Re-run the downloads at the start of every deck job. They are cheap, they overwrite in place, and a copy from three weeks ago may be stale — do not skip them because the file looks like it is already there.

## 2. Never write these files yourself

`plank_deck.py`, `plank_slides.py`, `plank_deck_edit.py` and `plank_deck_qa.py` come from plank.md/help/assets/ and from nowhere else. If an import fails, re-run the download into `/workspace/scripts/deck/` and read the error.

Do **not** write your own file under one of those names, not even a small one to get unblocked, and not even inside a project folder. A hand-written module wearing our name is worse than no module: it passes `import`, it measures nothing, and every later build in that workspace silently picks it up instead of the real builder. If you cannot download it, say so and build the deck with plain `python-pptx` under a different filename.

## 3. Put the build script in `/workspace/scripts/deck/` too

Keep your `build_*.py` beside the builder. Then the import resolves with no `PYTHONPATH` and no `cd`, from any call:

```bash
curl -sSfL -o /workspace/scripts/deck/plank_deck.py https://plank.md/help/assets/plank_deck.py
python3 /workspace/scripts/deck/build_acme_deck.py
```

```python
# /workspace/scripts/deck/build_acme_deck.py
from plank_deck import *

prs = new_deck(theme="studio")          # or theme="report" for a light, printable deck
set_brand(prs, meta=(("brand", "ACME"),), city="Almaty", year="2026")
cover(prs, "Warehouse counts without the clipboard", subtitle="Q4 proposal")
save(prs, "/workspace/acme-proposal.pptx")
```

A `DeckError` means the slide is carrying too much text, not that the type should be smaller. The call drew nothing and left nothing to clean up: cut the copy, split the slide, or move the detail into the notes.

## 4. Run the QA before you hand anything over

```bash
curl -sSfL -o /workspace/scripts/deck/plank_deck_qa.py https://plank.md/help/assets/plank_deck_qa.py
python3 /workspace/scripts/deck/plank_deck_qa.py /workspace/acme-proposal.pptx
```

It takes `.pptx` or `.html`, renders the deck, reads where the words actually landed, and also writes the PDF into `<deck>-qa/`. It exits non-zero when anything is an **error**.

**An error is not a warning and is not a known quirk.** Text outside its shape, text off the slide, words on top of words, a blank slide, a picture that did not decode, text illegible over its own photograph — each of those is a reader seeing something broken. Fix it and run the QA again.

If you decide to hand over a deck that still has errors, say so in the message, with the count and which ones you left: *"QA reports 45 errors — 16 text overflows and 24 low-contrast titles — which I have not fixed."* Delivering a deck the QA condemned without repeating the number is the one thing this step exists to prevent.

## 5. A workspace skill does not replace this route

A skill, a template or an `AGENTS.md` in this workspace may own the **look** — the brand colours, the typeface, the tone, which slides to include. That is what it is for, and you follow it.

It does not own the **toolchain**. Unless it names a different builder and explains why, the deck is still built with `/workspace/scripts/deck/plank_deck.py` and still checked with `/workspace/scripts/deck/plank_deck_qa.py`. A skill that is silent about how to build is not choosing a different route; it simply never mentioned this one.

## Which format

`.pptx` when the deck will be re-cut, re-branded or opened in PowerPoint. HTML → PDF (`plank_slides.py`, which needs `plank_deck.py` beside it in `/workspace/scripts/deck/`) when it has to look art-directed and nobody will edit it. Ask the user when the request does not answer it. The full argument, and everything each format gives up: [How Plank builds a slide deck](/help/presentations.md).
