Boxloom: Folien schreiben
Boxloom trennt Bedeutung von Aussehen. Du schreibst nur, was der Inhalt ist
(eine Liste von Punkten, ein Vergleich von Optionen, ein datierter Plan). Die Vorlage entscheidet über jede
Farbe, Schriftgröße, jeden Rand und jede Position. Du schreibst nie eine Farbe, eine Größe oder eine Koordinate
außerhalb der einen Ausnahme (shapes, letztes Mittel).
Der Zyklus ist immer:
boxloom schema– lies, was die aktuellen Vorlagen akzeptieren (zuerst ausführen).- Schreibe
deck.bx.md. boxloom check --format json deck.bx.md– korrigiere jeden Fehler, dann jede Warnung, die du kannst.- Wiederhole Schritt 3, bis
"ok": trueund keinelayout-overflow-Warnung mehr vorhanden ist. boxloom build -o deck.pptx deck.bx.md(Flags vor der Datei).
Die Befehle werden aus dem boxloom/-Verzeichnis des Repos ausgeführt:
go run ./cmd/boxloom <schema|check|build|parse> … (Go 1.24+, keine weiteren Abhängigkeiten).
1. Lies zuerst das Schema
boxloom schema [-template light|dark] gibt ein JSON-Dokument aus. Es ist die
alleinige Quelle der Wahrheit; wenn diese Datei und das Schema unterschiedlicher Meinung sind, gewinnt das Schema.
markdown.rules– die Syntaxregeln (kurze Liste; befolge alle).markdown.frontMatter– erlaubte Schlüssel im----Kopf (titleist erforderlich).templates[].blocks– die umschlossenen Blöcke (:::name), die diese Vorlage kennt, mitinside(wo sie erscheinen dürfen),contains(was darin steht) undminChildren.templates[].subsystems– die Figurentypen (```nameCodeblöcke), mitmarkdown(ihre zusätzlichen Regeln) undschema(ein JSON-Pointer inirSchema, der jeden erlaubten Schlüssel angibt).- Alles, was nicht aufgeführt ist, ist ein Fehler. Erfinde keine Blocknamen, Attribute oder Schlüssel.
- Vorlagen werden nach Name ausgewählt (
template: lightim Front Matter, oder-template dark). Eine benutzerdefinierte Vorlage ist eine Wertetabelle, die als Pfad übergeben wird:-template ./my.json(funktioniert fürschema,check,build,fonts; Beispiel:examples/templates/forest.json). Wenn die Folien mit einer benutzerdefinierten Vorlage erstellt werden, führeschemaundcheckmit demselben-templateaus – Rollennamen und Textstile kommen aus dieser Datei. variant(# Title {variant=…}) existiert in der Syntax, aber die aktuellen Vorlagen deklarieren keine Varianten (templates[].variantsist leer), also verwende es nicht.
Die Ausgabe ist groß. Um nur das Nötigste zu sehen:
go run ./cmd/boxloom schema -template light > /tmp/schema.json
python3 -c "import json;d=json.load(open('/tmp/schema.json'));print(json.dumps({'rules':d['markdown']['rules'],'blocks':d['templates'][0]['blocks'],'subsystems':[(x['name'],x['markdown']) for x in d['templates'][0]['subsystems']]},ensure_ascii=False,indent=1))"
python3 -c "import json;d=json.load(open('/tmp/schema.json'));print(json.dumps(d['irSchema']['$defs']['gantt'],ensure_ascii=False,indent=1))" # alle Gantt-Schlüssel
2. Syntax auf einen Blick
---
title: Moving the reporting service to the new cluster
subtitle: Plan and options (fictional example)
author: Platform team
date: 2026-11-11
confidential: Internal
disclaimer: All names and figures are fictional
template: light
---
# Vendor support of the old cluster
:::lead
The old cluster loses vendor support in March 2028, so the 14 services on it must move before then.
:::
- The vendor ends security fixes on **2028-03-31**
- 14 services still run there; 9 can move without code changes
- Moving takes about 6 weeks per service group
:::source
Vendor support notice of 2026-09; service inventory as of October 2026
:::
:::notes
Speaker notes go here. Plain paragraphs and bullets only.
:::
-
# Titlestartet eine Folie. Halte den Titel als kurze Überschrift, die in eine Zeile passt ("Vendor support of the old cluster"); ein Titel, der umbricht, wird gewarnt (title-wrap). Schreibe, was die Folie aussagt – die Schlussfolgerung – als Satz in:::leaddirekt nach dem Titel (1–2 Zeilen). Die Vorlage platziert den Lead unter dem Titel, außerhalb des Textkörpers. -
---ist kein Folientrenner (es ist ein Fehler).##und tiefere Überschriften sind Fehler (ein Gruppentitel wird als:::column Titlegeschrieben, nicht als Unterüberschrift). -
Textkörper: Absätze,
-/1.Aufzählungen (maximal zwei Ebenen),**emphasis**(nur eine Art von Betonung),`code`,[text](url), nachgestelltes\für einen sinnvollen Zeilenumbruch. Keine Kursivschrift, Durchstreichung, Fußnoten, HTML. -
Umschlossene Blöcke: Öffnen mit
:::nameund schließen mit der gleichen Anzahl von Doppelpunkten. Bei Verschachtelung erhält der äußere Rahmen einen Doppelpunkt mehr als der innere::::::compare ::::option Keep the old cluster :::pros - No migration work this year ::: :::cons - No security fixes after March 2028 ::: :::: ::::option Move to the new cluster :::pros - Supported until 2033 ::: :::cons - Six weeks of work per service group ::: :::: ::::: -
:::lead(die Aussage der Folie),:::notes(Sprechernachrichten) und:::source(woher die Zahlen der Folie stammen) müssen auf der obersten Ebene einer Folie stehen, jeweils einmal pro Folie.:::leadist nur für Inhaltsfolien. -
date,confidentialunddisclaimerim Front Matter werden einmal für das gesamte Deck geschrieben; die Vorlage platziert sie auf dem Deckblatt (undconfidentialin der Fußzeile). Wiederhole niemals "fiktiv" / "vertraulich" in einem:::noteauf jeder Folie. -
Figuren sind umschlossene Codeblöcke, deren Sprache der Subsystemname ist, der Inhalt in einem eingeschränkten YAML: keine Anker/Aliase (
&,*), keine Tags, keine mehrzeiligen Werte, keine|/>-Blöcke; Boolesche Werte nurtrue/false; Daten sind ZeichenkettenYYYY-MModerYYYY-MM-DD; Bereiche2027-01 .. 2027-06. Zitiere jeden Wert, der mit*,&,!beginnt oder": "enthält, z. B.text: ["**Slowest step**", 5 days on average]– ein nicht zitierter**…**am Anfang eines Listenelements wird als YAML-Alias gelesen und abgelehnt.
3. Ein Muster für jeden Inhaltstyp auswählen
Entscheide den Inhaltstyp, bevor du schreibst. Wende diese Regeln in der Reihenfolge an und verwende
den ersten, der zutrifft. (Vollständige Regelmenge mit guten/schlechten Beispielen: docs/patterns.md §4.)
Derzeit verfügbar (überprüfe mit boxloom schema – es könnten weitere hinzugekommen sein):
| Inhalt | Verwende | Hinweise |
|---|---|---|
| Ein Kapitelwechsel | # Part 2: How we migrate {type=section} | Überschriftstext ist der Kapiteltitel; nichts außer :::notes darf folgen. Kein Inhaltsverzeichnis – bei zwei oder mehr Abschnitten zeichnet die Vorlage die Kapitelliste mit dem aktuellen, hervorgehobenen Abschnitt auf jeder Abschnittsfolie selbst |
| Die Folie sagt genau einen Satz aus; die Belege sind auf anderen Folien | # Migration must move two years earlier {type=statement} | Überschriftstext ist der Satz (dies ist der einzige Folientyp, dessen Überschrift ein vollständiger Satz ist); nichts außer :::notes und :::source darf folgen. Wenn du Gründe hinzufügen würdest, verwende eine normale Folie mit einem kurzen Titel und der Schlussfolgerung als :::lead |
| 1–4 stark zu zeigende Zahlen, ohne Serie zum Vergleich | ::::stat → :::value 3 → 12 {unit=models} + einzeiliges Label im Inneren | 5+ Zahlen oder eine Zeitreihe ist ein Diagramm/eine Tabelle, kein Stat. Der Wert wird wie angegeben geschrieben und muss eine Ziffer enthalten. Wert und Einheit werden niemals in der Mitte getrennt, also halte sie kurz – 4 Karten sind schmal (stat-value) |
| Eine Zahlenreihe (3+ Punkte): Rangfolge, Veränderung im Zeitverlauf, Anteil an einem Ganzen, Verteilung, Zusammenhang zweier Größen | ```chart | compare: item / timeSeries / component / frequency / correlation – der Diagrammtyp wird für dich ausgewählt (niemals Balken/Linie/Kreis schreiben). categories: [...], series: [{name, values: [...]}] (ein Wert pro Kategorie, nicht zitierte Zahlen, maximal 3 Serien), optional unit, emphasis: [category] (eine Serie) oder emphasis: true bei einer Serie, stacked: true wenn Serien Teile eines Ganzen sind. correlation verwendet xAxis: {title, unit?}, yAxis: ... und points: [[x, y], …] anstelle von Kategorien. component (Anteil) hat 1 Serie und ≤ 6 Teile – fasse kleine Teile unter "Other" zusammen |
| Die Worte eines anderen | :::quote Quelltext + die Worte im Inneren | Der Quelltext (Überschriftstext) ist erforderlich. Zitiere niemals deine eigene Schlussfolgerung |
| Ein Satz zur Hervorhebung innerhalb einer normalen Folie | :::takeaway + ein Satz | Maximal einer pro Folie, normalerweise am Ende |
| Zeilen × Spalten aus einfachem Text oder Zahlen | GFM-Tabelle: ` | A |
| Zeilen × Spalten, in denen jede Zelle eine Bewertung ist (unterstützt / bedingt / nicht / Risiko) | ```matrix | columns: [A, B], rows: [{label, cells: [{status, text?}]}], optional legend: {support: Good}. Eine Zelle pro Spalte (matrix-cells). Die empfohlene Option: emphasis: <Spaltenkopftext> (genau wie in columns geschrieben, matrix-emphasis) – sage niemals "die blaue Spalte" im Text. Zellen, die einfacher Text oder Zahlen sind, sind eine Tabelle, kein Matrix |
| 3–7 Schritte ohne Daten, in eine Richtung (die Ausgabe eines Schritts ist die Eingabe des nächsten) | ```process | steps: [{title, detail?, status?, emphasis?}], optional caption. Nummern (1. 2. …) und Pfeile werden für dich hinzugefügt; lange Prozesse werden in eine zweite Zeile umgebrochen. Wenn du status verwendest, sage, was es bedeutet, in legend: {conditional: Needs approval} (figure-legend) |
| Zwei oder mehr Optionen, jeweils mit Vor- und Nachteilen | :::compare → :::option → :::pros / :::cons | Wenn 3+ gemeinsame Kriterien auf jede Option zutreffen, passt eine Matrix besser (oben) |
| Ein Elternteil mit Kindern (und Enkeln): Teamaufbau, Eigentumsverhältnisse | ```orgchart | root: {title, detail?}, units: [{title, detail?, members: [{title, detail?}]}]. Maximal 3 Ebenen. Ein status auf einem Kasten benötigt legend: {conditional: Two more people needed} – die Legende unter dem Diagramm erklärt ihn; erkläre keine Umrissfarben in einem :::note. Nicht für nebeneinanderstehende, nicht verwandte Teams |
| Stufen, deren Anzahl abnimmt (Besuche → Anmeldungen → Zahlende) | ```funnel | stages: [{label, value, note?}], optional unit. value ist eine Zahl oder ein Text; Balkenbreiten sind gestuft, nicht proportional. Stufenweise Konversionsraten (↓ 45%) werden für dich aus numerischen Werten berechnet – schreibe sie nicht in note; verwende note für den Grund, warum eine Stufe abfällt. status benötigt legend. Werte, die wachsen, werden gewarnt (funnel-increase) – verwende für einfache Schritte process |
| Ein datierter Plan, Zeiträume, Fristen, Status im Zeitverlauf | ```gantt | Zustände sind support, conditional, none, danger (Rollen, keine Farben). Hardware-/Support-Risikozeiträume sind eine Gruppe risk: A .. B. Anmerkungen zeigen auf eine Gruppen-/Zeilen-id über target; das Subsystem platziert sie |
| 2–3 parallele Gruppen nebeneinander ("dieses Jahr / nächstes Jahr / nicht durchführen") | ::::columns → :::column Gruppenname (2 oder 3) | Jede Gruppe enthält Absätze, Aufzählungen, eine Tabelle, ein Bild, ein ```chart oder :::note. Keine verschachtelten Spalten, Vergleiche, Galerien oder andere Figuren. Diagramm + daneben seine Lesart: Diagramm in einer Gruppe, die Erkenntnisse als Aufzählungen in der anderen. Breiten sind keine Zahlen: markiere die eine Hauptgruppe mit {role=main} (die anderen unterstützen sie) oder lasse alle gleich. 4+ einzeilige Gruppen → Aufzählungen. Nicht für ein in zwei geteiltes Argument |
| Ein Bild, das den Punkt zeigt (Screenshot, Foto, Zeichnung) | ein Absatz, der nur  enthält | Alternativtext ist erforderlich (image-alt). Der Pfad ist relativ zur Deck-Datei; keine URLs, absoluten Pfade oder .. (image-path). Nur PNG oder JPEG (image-format). Proportional erhalten, niemals beschnitten. Bild + Text nebeneinander → ::::columns mit dem Bild in einer Gruppe |
| 2–6 Bilder im Vergleich oder in einer Sequenz | ein Absatz mit 2–6  | Wird zu einer Galerie (eine Zeile für 2–3, ein Raster für 4–6). 7+ ist ein Fehler: teile die Folie auf |
| Parallele Punkte | Aufzählungen | Maximal 2 Ebenen |
| Zusammenhängender Text | Absatz | 2–3 Sätze |
| Was die Folie aussagt: ihre Schlussfolgerung in einem oder zwei Sätzen | :::lead auf der obersten Ebene einer Inhaltsfolie, ein Absatz | Jede Inhaltsfolie bekommt einen. Von der Vorlage direkt unter dem Titel platziert, außerhalb des Textkörpers; er nimmt Platz vom Textkörper weg (1 Zeile ≈ 32 pt, 2 Zeilen ≈ 57 pt). Wenn er zwei Zeilen benötigt, bricht die Engine ihn nach einem Satzende (。) oder, falls nicht vorhanden, nach einem Komma (、) um, ohne eine Zeile hinzuzufügen – also lesen sich zwei kurze Sätze am besten. Keine Zusammenfassung der Aufzählungen – die Behauptung, die sie beweisen |
| Woher die Zahlen, die Tabelle, die Abbildung oder das Zitat der Folie stammen (Quelle, Stichprobengröße, Datum) | :::source auf der obersten Ebene der Folie, ein Absatz | Jede Folie, die Zahlen, eine Tabelle, ein Diagramm oder ein Zitat zeigt, bekommt einen. Nur Inhalts- und Aussagefolien (keine Abschnitte). Von der Vorlage unter dem Textkörper, über der Fußzeile platziert; er nimmt Platz vom Textkörper weg (layout-overflow zählt ihn). Einer pro Folie: mehrere Quellen stehen in einem Absatz |
| Deck-weites Datum, Vertraulichkeit, Haftungsausschluss ("alle Zahlen sind fiktiv") | Front Matter date, confidential, disclaimer | Einmal geschrieben; auf dem Deckblatt angezeigt (und confidential in der Fußzeile) |
| Ein Vorbehalt / fußnotenartige Bemerkung | :::note | Eine kurze Zeile. Nicht für Quellen (:::source), nicht für den Deck-weiten Haftungsausschluss (Front Matter) und niemals für die Schlussfolgerung oder eine Schlüsselzahl |
| Ein Diagramm, dessen Positionen/Verbindungen Bedeutung tragen und keines der obigen passt | ```shapes | Letztes Mittel, siehe §3.1 |
Bei allen vier Figuren oben schreibst du nur Text, status (support, conditional,
none, danger) und emphasis: true; Position, Größe und Farbe kommen von der Vorlage.
In chart schreibst du nur, was verglichen wird, und die Zahlen; das Diagramm ist ein echtes
PowerPoint-Diagramm, dessen Werte bearbeitbar bleiben. Hebe den einen Punkt hervor, den der Titel macht:
compare: timeSeries
unit: " Anmeldungen"
categories: [Apr, Mai, Jun, Jul, Aug, Sep]
emphasis: [Sep]
series:
- name: Anmeldungen
values: [120, 150, 1
...
[aus Gründen der Kürze abgeschnitten]
