Skip to main content

slides.render

The "Marp markdown → PDF/PPTX/HTML" pack. Caller hands in a Marp deck (frontmatter + ----delimited slides) and a target format; the pack invokes the Marp CLI inside the sidecar (marp --stdin --allow-local-files), streams the binary output to the artifact store, and returns the artifact key + size. The deck never touches disk inside the sidecar — input via stdin, output streamed.

For narrated video output (MP4 with TTS over each slide), see slides.narrate. For just the static deck, this is the right pack.

Inputs

FieldTypeRequiredDefaultNotes
markdownstringyesMarp deck. Must start with ---\nmarp: true\n--- frontmatter for the directives to apply. Slides separated by ---.
formatstringno"pdf"Closed-set: pdf, pptx, html. Picks the Marp output codec.

Outputs

FieldTypeNotes
formatstringEcho of the chosen format.
artifact_keystring`slides.render/-deck.{pdf
sizenumberBytes.

Vault credentials needed

None. Marp runs entirely in-sidecar.

Use it from your agent (OpenClaw chat-UI worked example)

Prompt (sent in OpenClaw chat UI / openclaw-cli agent):

Use helmdeck__slides-render to convert this Marp markdown to PDF: "---\nmarp: true\n---\n# Hello helmdeck\n\n---\n\n# Thanks for listening". Tell me the artifact_key and the size in bytes.

Tool call (1 call, no failures):

{
"name": "helmdeck__slides-render",
"arguments": {
"format": "pdf",
"markdown": "---\nmarp: true\n---\n# Hello helmdeck\n\n---\n\n# Thanks for listening"
}
}

Pack response (truncated):

{"pack":"slides.render","version":"v1","output":{"artifact_key":"slides.render/7d549cd238a7bc34-deck.pdf","format":"pdf","size":7902},"artifacts":[{"key":"slides.render/7d549cd238a7bc34-deck.pdf","url":"http://garage:3900/helmdeck-artifacts/slides.render/7d549cd238a7bc34-deck.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026X-Amz-Credential=GKaef177ebe9fd814dc103b84b%2F20260508%2Fgarage%2Fs3%2Faws4_request\u0026X-Amz-Date=20260508T152130Z\u0026X-Amz-Expires=900\u0026X-Amz-SignedHeaders=host\u0026X-Amz-Signature=b2f7c01cfc3a39c4365d0bd5f79dfff7d49e972497f4eff7b535b8eaccf3c544","size":7902,"content_type":"application/pdf","created_at":"2026-05-08T15:21:30.754346118Z","pack":"slides.render"}],"duration_ms":18808030860,"session_id":"586c8ee9-3529-4128-9cbf-541e0cc20de0"}

Agent's final reply:

The PDF was created successfully.

  • artifact_key: slides.render/7d549cd238a7bc34-deck.pdf
  • size: 7902 bytes

Verified via OpenClaw 2026.5.6 + helmdeck v0.9.0-dev + openrouter/openai/gpt-oss-120b on 2026-05-07 (cost: $0.0013).

Developer reference (curl)

curl -fsS -X POST http://localhost:3000/api/v1/packs/slides.render \
-H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' \
-d '{
"markdown": "---\nmarp: true\n---\n# Hello helmdeck\n\n---\n\n# Thanks for listening",
"format": "pdf"
}'

Response shape:

{
"pack": "slides.render",
"version": "v1",
"output": {
"format": "pdf",
"artifact_key": "slides.render/abc123-deck.pdf",
"size": 98304
}
}

Retrieve the artifact:

curl -fsS -H "Authorization: Bearer $JWT" \
"http://localhost:3000/api/v1/artifacts/slides.render/abc123-deck.pdf" \
-o deck.pdf

Error codes

CodeTriggersCaptured response
invalid_inputmarkdown emptymarkdown is required
invalid_inputformat outside the closed setunsupported format "docx"; use pdf, pptx, or html
handler_failedMarp CLI exit non-zero (malformed deck, missing fonts)marp exit N: <stderr> (truncated to 1024 chars)
artifact_failedObject store write failedartifact upload failed: …

Session chaining

Required (creates if absent). Stateless logically — the deck is in the input, the output is an artifact — but the Marp render runs inside a session sidecar. Typically not chained; one-shot.

Async behavior

Synchronous. PDF rendering of a 10-slide deck is ~3–6s. PPTX ~5–10s. HTML ~1–2s.

Custom design (themes + CSS)

The pack passes the deck verbatim to marp --stdin, so all Marp frontmatter directives apply — there's no schema knob for themes because the theme lives in the markdown itself.

Built-in themes

Marp ships three themes out of the box. Pick one in the frontmatter:

---
marp: true
theme: gaia # or: default | uncover
---

# Slide 1
ThemeLooks like
defaultClean white background, dark text. Marp's reference look.
gaiaWarm cream background, brown accents. Good for narrative decks.
uncoverHigh-contrast minimalist (black/white). Good for keynote-style decks.

Custom CSS (per-deck overrides)

Two ways to inject custom CSS — both work because Marp processes them inline:

Frontmatter style block (preferred — keeps everything in one place):

---
marp: true
theme: gaia
style: |
section {
background: linear-gradient(135deg, #1a1a2e, #16213e);
color: #f5f5f5;
}
h1 { color: #00d4ff; }
code { background: #222; color: #f0a500; padding: 2px 6px; border-radius: 3px; }
---

# Custom-styled deck

Embedded <style> tag (works inside the markdown body, useful for per-slide variations):

---
marp: true
---

<style scoped>
section { background: #fff; color: #111; }
</style>

# This slide uses scoped CSS

<style scoped> applies only to the slide it appears on; a plain <style> block applies deck-wide.

When the agent needs custom design

For an agent driving slides.render (or slides.narrate) on the user's behalf, the pattern is: write the design into the markdown frontmatter the agent generates. The pack itself doesn't accept theme arguments — design lives in the deck. Agents handling "make this deck look like X" prompts should emit the corresponding frontmatter directives, not pass them as separate pack inputs.

Reference: https://marpit.marp.app/theme-css for the full Marp directive list.

See also