@ztffn/presentation-generator-plugin 1.3.3 → 1.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +4 -3
- package/README.md +27 -17
- package/agents/presentation-content.md +1 -2
- package/agents/presentation-narrative.md +4 -4
- package/agents/presentation-style.md +196 -0
- package/hooks/enforce-style-schema.sh +70 -0
- package/hooks/hooks.json +49 -0
- package/hooks/pre-validate-presentation-json.sh +62 -0
- package/hooks/validate-presentation-json.sh +64 -0
- package/package.json +1 -1
- package/scripts/outline_to_graph.py +413 -0
- package/scripts/validate_draft.py +2 -1
- package/skills/graph-json-spec/SKILL.md +73 -620
- package/skills/presentation-generator/SKILL.md +82 -35
- package/skills/presentation-generator/presentation-guide.md +2 -2
- package/skills/slide-recipes/SKILL.md +326 -0
- package/agents/presentation-design.md +0 -187
|
@@ -9,38 +9,58 @@ description: >
|
|
|
9
9
|
|
|
10
10
|
# Presentation Generator
|
|
11
11
|
|
|
12
|
-
Orchestrates a
|
|
12
|
+
Orchestrates a two-agent + script pipeline to produce a complete, navigable presentation graph JSON from a user brief and optional source documents.
|
|
13
13
|
|
|
14
14
|
## Pipeline Overview
|
|
15
15
|
|
|
16
16
|
```
|
|
17
17
|
User Brief + Documents
|
|
18
18
|
↓
|
|
19
|
-
[1] Content Extraction
|
|
19
|
+
[1] Content Extraction → _temp/presentation-content-brief.json
|
|
20
20
|
↓
|
|
21
|
-
[2] Narrative Design
|
|
21
|
+
[2] Narrative Design → _temp/presentation-outline.md
|
|
22
22
|
↓
|
|
23
|
-
[3] User Approval
|
|
23
|
+
[3] User Approval → confirm or revise structure
|
|
24
24
|
↓
|
|
25
|
-
[4]
|
|
25
|
+
[4] Graph Generation → presentations/{slug}/{slug}.json (script)
|
|
26
26
|
↓
|
|
27
|
-
[5]
|
|
27
|
+
[5] Visual Styling → styled JSON (agent)
|
|
28
|
+
↓
|
|
29
|
+
[6] Delivery → import instructions + media checklist
|
|
28
30
|
```
|
|
29
31
|
|
|
32
|
+
## Phase 0 — Locate Plugin Root
|
|
33
|
+
|
|
34
|
+
Before any other phase, resolve the plugin root directory. Check the local project path first, then the global path:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
if [ -f ".claude/plugins/presentation-generator/scripts/outline_to_graph.py" ]; then
|
|
38
|
+
PLUGIN_ROOT=".claude/plugins/presentation-generator"
|
|
39
|
+
elif [ -f "$HOME/.claude/plugins/presentation-generator/scripts/outline_to_graph.py" ]; then
|
|
40
|
+
PLUGIN_ROOT="$HOME/.claude/plugins/presentation-generator"
|
|
41
|
+
else
|
|
42
|
+
echo "ERROR: presentation-generator-plugin not found" && exit 1
|
|
43
|
+
fi
|
|
44
|
+
echo "Plugin root: $PLUGIN_ROOT"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Store `PLUGIN_ROOT` for all subsequent phases. All skill files, scripts, and agent references use this path.
|
|
48
|
+
|
|
30
49
|
## Phase 1 — Context Gathering
|
|
31
50
|
|
|
32
|
-
Parse the user's request to
|
|
51
|
+
Parse the user's request to extract these four fields. Do NOT read or open any files — just note the paths as strings:
|
|
33
52
|
|
|
34
53
|
1. **What** is being presented (product, project, topic)
|
|
35
54
|
2. **To whom** (audience type, their background, what they care about)
|
|
36
55
|
3. **For what goal** (`pitch`, `demo`, `update`, `internal`, `exploratory`)
|
|
37
|
-
4. **Source documents** — paths
|
|
56
|
+
4. **Source documents** — file paths mentioned in the request (pass these to the content agent in Phase 2, do not read them yourself)
|
|
38
57
|
|
|
39
58
|
If no documents are provided, skip Phase 2 and construct a minimal content brief directly from the prompt. Ask the user for any missing critical information:
|
|
40
59
|
- If audience is unclear, ask who the presentation is for
|
|
41
60
|
- If goal is unclear, ask what outcome they want
|
|
42
61
|
|
|
43
62
|
## Phase 2 — Content Extraction
|
|
63
|
+
Announce to the user that you are **Executing Phase 2 — Subagent: Content Extraction**
|
|
44
64
|
|
|
45
65
|
Delegate content extraction to the specialist agent using the Task tool:
|
|
46
66
|
|
|
@@ -49,8 +69,8 @@ Task tool:
|
|
|
49
69
|
subagent_type: "presentation-content"
|
|
50
70
|
description: "Extract content brief"
|
|
51
71
|
prompt: |
|
|
52
|
-
Step 1: Load your skill file.
|
|
53
|
-
|
|
72
|
+
Step 1: Load your skill file. Read this file:
|
|
73
|
+
{PLUGIN_ROOT}/skills/content-signals/SKILL.md
|
|
54
74
|
— it defines the content brief schema, signal priorities, and validation rules.
|
|
55
75
|
|
|
56
76
|
Step 2: Read these source documents and extract a structured content brief:
|
|
@@ -88,6 +108,7 @@ After the content brief is written, read `_temp/presentation-content-brief.json`
|
|
|
88
108
|
If any check fails, ask the user ONE targeted question to fill the gap. Do not pass a weak brief to the narrative agent.
|
|
89
109
|
|
|
90
110
|
## Phase 3 — Narrative Design
|
|
111
|
+
Announce to the user that you are **Executing Phase 3 — Subagent: Narrative Design**
|
|
91
112
|
|
|
92
113
|
Delegate narrative design to the specialist agent using the Task tool:
|
|
93
114
|
|
|
@@ -96,10 +117,10 @@ Task tool:
|
|
|
96
117
|
subagent_type: "presentation-narrative"
|
|
97
118
|
description: "Design narrative outline"
|
|
98
119
|
prompt: |
|
|
99
|
-
Step 1: Load your skill files.
|
|
100
|
-
-
|
|
101
|
-
-
|
|
102
|
-
-
|
|
120
|
+
Step 1: Load your skill files. Read these three files:
|
|
121
|
+
- {PLUGIN_ROOT}/skills/frameworks/SKILL.md
|
|
122
|
+
- {PLUGIN_ROOT}/skills/slide-content/SKILL.md
|
|
123
|
+
- {PLUGIN_ROOT}/skills/graph-topology/SKILL.md
|
|
103
124
|
|
|
104
125
|
Step 2: Read the content brief at _temp/presentation-content-brief.json
|
|
105
126
|
|
|
@@ -116,6 +137,7 @@ Task tool:
|
|
|
116
137
|
The narrative agent selects a story framework, designs the spine and drill-down structure, and writes a detailed slide outline.
|
|
117
138
|
|
|
118
139
|
## Phase 4 — User Approval
|
|
140
|
+
Announce to the user that you are **Executing Phase 4 — Getting User Approval**
|
|
119
141
|
|
|
120
142
|
Read `_temp/presentation-outline.md` and render it as a folder tree for the user:
|
|
121
143
|
|
|
@@ -145,38 +167,59 @@ Wait for the user to respond:
|
|
|
145
167
|
|
|
146
168
|
This loop continues until the user explicitly approves.
|
|
147
169
|
|
|
148
|
-
## Phase
|
|
170
|
+
## Phase 5A — Graph Generation (script)
|
|
171
|
+
Announce to the user that you are **Executing Phase 5A — Generating Graph JSON from Outline**
|
|
149
172
|
|
|
150
|
-
|
|
173
|
+
Run the deterministic outline-to-graph converter directly via Bash:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
python3 "$PLUGIN_ROOT/scripts/outline_to_graph.py" _temp/presentation-outline.md -o presentations/{slug}/{slug}.json
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The script:
|
|
180
|
+
- Parses the outline markdown
|
|
181
|
+
- Generates all nodes with correct wrappers, positions, and data fields
|
|
182
|
+
- Wires all edges with bidirectional pairs
|
|
183
|
+
- Runs the validator internally
|
|
184
|
+
- Exits 0 if valid, 1 with errors
|
|
185
|
+
|
|
186
|
+
If exit non-zero, review the errors and fix the outline. If zero, proceed to Phase 5B.
|
|
187
|
+
|
|
188
|
+
## Phase 5B — Visual Styling (agent)
|
|
189
|
+
Announce to the user that you are **Executing Phase 5B — Subagent: Visual Styling**
|
|
190
|
+
|
|
191
|
+
Delegate visual styling to the specialist agent using the Task tool:
|
|
151
192
|
|
|
152
193
|
```
|
|
153
194
|
Task tool:
|
|
154
|
-
subagent_type: "presentation-
|
|
155
|
-
description: "
|
|
195
|
+
subagent_type: "presentation-style"
|
|
196
|
+
description: "Apply visual treatments"
|
|
156
197
|
prompt: |
|
|
157
|
-
Step 1: Load your skill
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
edge wiring, handle IDs, and positioning grid.
|
|
198
|
+
Step 1: Load your skill files. Read these two files:
|
|
199
|
+
- {PLUGIN_ROOT}/skills/slide-recipes/SKILL.md
|
|
200
|
+
- {PLUGIN_ROOT}/skills/graph-json-spec/SKILL.md
|
|
161
201
|
|
|
162
|
-
Step 2: Read the
|
|
202
|
+
Step 2: Read the structurally valid presentation JSON at
|
|
203
|
+
presentations/{slug}/{slug}.json
|
|
163
204
|
|
|
164
|
-
Step 3:
|
|
165
|
-
|
|
205
|
+
Step 3: Read the outline at _temp/presentation-outline.md for context
|
|
206
|
+
on each slide's purpose and visual intent.
|
|
166
207
|
|
|
167
|
-
Step 4:
|
|
208
|
+
Step 4: Apply visual treatments to each slide based on the slide-recipes
|
|
209
|
+
Visual Intent Mapping. Edit only data fields using the Edit tool.
|
|
210
|
+
Never modify node wrappers, edges, or positions.
|
|
168
211
|
|
|
169
|
-
Step 5: Run the validator script and fix any errors
|
|
170
|
-
|
|
171
|
-
python3 "$VALIDATE" presentations/{slug}/{slug}.json
|
|
212
|
+
Step 5: Run the validator script and fix any errors:
|
|
213
|
+
python3 "{PLUGIN_ROOT}/scripts/validate_draft.py" presentations/{slug}/{slug}.json
|
|
172
214
|
|
|
173
215
|
Step 6: Report back with the exact validator terminal output,
|
|
174
|
-
|
|
216
|
+
number of slides styled, and any video/image placeholders.
|
|
175
217
|
```
|
|
176
218
|
|
|
177
|
-
The
|
|
219
|
+
The styling agent reads the valid JSON and applies visual treatments (two-column layouts, centered slides, background images, charts) by editing only `data` fields. It cannot break structure.
|
|
178
220
|
|
|
179
221
|
## Phase 6 — Delivery
|
|
222
|
+
Announce to the user that you are **Executing Phase 6 — Packaging Presentation**
|
|
180
223
|
|
|
181
224
|
After `presentations/{slug}/{slug}.json` is written:
|
|
182
225
|
|
|
@@ -189,10 +232,12 @@ After `presentations/{slug}/{slug}.json` is written:
|
|
|
189
232
|
|
|
190
233
|
```
|
|
191
234
|
Import your presentation:
|
|
192
|
-
1. Open the graph editor at /present/plan
|
|
235
|
+
1. Open the graph editor at https://humagreenfield.netlify.app/present/plan
|
|
193
236
|
2. Click "New presentation"
|
|
194
237
|
3. Choose "Import JSON"
|
|
195
238
|
4. Select presentations/{slug}/{slug}.json
|
|
239
|
+
5. Click "Create presentation"
|
|
240
|
+
6. Make final adjustments and manual uploads.
|
|
196
241
|
```
|
|
197
242
|
|
|
198
243
|
3. If any slides have video placeholders, list them:
|
|
@@ -212,7 +257,9 @@ Replace the PLACEHOLDER string with the returned URL after upload.
|
|
|
212
257
|
|---|---|---|
|
|
213
258
|
| `presentation-content` | `content-signals` | Extract structured brief from documents |
|
|
214
259
|
| `presentation-narrative` | `frameworks`, `slide-content`, `graph-topology` | Design story structure and slide content |
|
|
215
|
-
| `presentation-
|
|
260
|
+
| `presentation-style` | `graph-json-spec`, `slide-recipes` | Apply visual treatments to valid graph JSON |
|
|
261
|
+
|
|
262
|
+
Note: Graph structure (nodes, edges, positions) is generated deterministically by `scripts/outline_to_graph.py` in Phase 5A. The `presentation-style` agent in Phase 5B only modifies visual `data` fields.
|
|
216
263
|
|
|
217
264
|
## Working Without Documents
|
|
218
265
|
|
|
@@ -241,9 +288,9 @@ All intermediate and output files:
|
|
|
241
288
|
| File | Created By | Read By |
|
|
242
289
|
|---|---|---|
|
|
243
290
|
| `_temp/presentation-content-brief.json` | Content agent or orchestrator | Narrative agent |
|
|
244
|
-
| `_temp/presentation-outline.md` | Narrative agent |
|
|
291
|
+
| `_temp/presentation-outline.md` | Narrative agent | Script + styling agent, orchestrator |
|
|
245
292
|
| `_temp/presentation-plan.md` | Orchestrator | User (approval) |
|
|
246
|
-
| `presentations/{slug}/{slug}.json` |
|
|
293
|
+
| `presentations/{slug}/{slug}.json` | Script (structure) + styling agent (visuals) | User (import) |
|
|
247
294
|
| `presentations/{slug}/content-brief.json` | Orchestrator (Phase 6) | Reference |
|
|
248
295
|
| `presentations/{slug}/outline.md` | Orchestrator (Phase 6) | Reference |
|
|
249
296
|
| `presentations/{slug}/plan.md` | Orchestrator (Phase 6) | Reference |
|
|
@@ -138,7 +138,7 @@ Replace bullet lists with assertion + evidence. The assertion is the headline
|
|
|
138
138
|
> *Headline:* Mid-market finance teams lose 11 hours a week reconciling what three systems can't agree on
|
|
139
139
|
> [Chart or role-by-role breakdown of where those hours go]
|
|
140
140
|
|
|
141
|
-
→ Deep dive: *Assertion-Evidence Structure* — Michael Alley; *
|
|
141
|
+
→ Deep dive: *Assertion-Evidence Structure* — Michael Alley; *Slide Recipes* — slide-recipes skill
|
|
142
142
|
|
|
143
143
|
### Headlines vs. Titles
|
|
144
144
|
|
|
@@ -301,7 +301,7 @@ For difficult questions: "That's a valid concern. Here's how we thought about it
|
|
|
301
301
|
| Start in the Middle of Action | Merci Grace — *Giving Presentations* guest insights |
|
|
302
302
|
| Make the Title the Takeaway | Andy Raskin — *Giving Presentations* guest insights |
|
|
303
303
|
| Lead a Movement, Not Just Solve a Problem | Andy Raskin — *Brand Storytelling* guest insights |
|
|
304
|
-
| Assertion-Evidence Structure | Michael Alley — *
|
|
304
|
+
| Assertion-Evidence Structure | Michael Alley — *slide-recipes* skill |
|
|
305
305
|
| State Changes Every 3–5 Slides | Wes Kao — *Giving Presentations* guest insights |
|
|
306
306
|
| Stay in Character | Tristan de Montebello — *Giving Presentations* guest insights |
|
|
307
307
|
| Accordion Method | Tristan de Montebello — *Giving Presentations* guest insights |
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: slide-recipes
|
|
3
|
+
description: >
|
|
4
|
+
Design decision guide and slide recipes for presentation JSON generation.
|
|
5
|
+
Maps content signals to slide type, layout, and visual treatment.
|
|
6
|
+
Includes a reference example with all key patterns.
|
|
7
|
+
user-invocable: false
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Slide Recipes
|
|
11
|
+
|
|
12
|
+
Design decisions and concrete patterns for presentation JSON. For node schema, edge wiring, and positioning grid, see `graph-json-spec`.
|
|
13
|
+
|
|
14
|
+
## Visual Intent Mapping
|
|
15
|
+
|
|
16
|
+
The narrative agent annotates each slide with a `**Visual intent:**` label. Map them to JSON treatments:
|
|
17
|
+
|
|
18
|
+
| Visual Intent | type | centered | layout | brandFont | Background | lightText | Notes |
|
|
19
|
+
|---|---|---|---|---|---|---|---|
|
|
20
|
+
| `bookend` | content | true | single | true | optional image/color | if dark bg | Cover and CTA slides. showBranding: true |
|
|
21
|
+
| `chapter-opener` | content | false or true | single | false | backgroundImage + overlay | true | Full-bleed image, sets section mood. Max 3 bullet points. |
|
|
22
|
+
| `impact` | content | true | single | false | optional dark color | if dark bg | Single statement, no bullets. Let whitespace do the work. |
|
|
23
|
+
| `workhorse` | content | false | single or two-column | false | none | false | Standard bullets/content. The default treatment. |
|
|
24
|
+
| `evidence` | content or chart | false | single or two-column | false | none | false | Data-forward: chart, table, or comparison. |
|
|
25
|
+
| `breathing-room` | content | true | single | false | backgroundImage + overlay OR style.backgroundColor | true | Minimal text. Visual pause. Resets audience attention. |
|
|
26
|
+
|
|
27
|
+
When the outline lacks visual intent annotations, infer them:
|
|
28
|
+
- First slide → bookend
|
|
29
|
+
- Last slide → bookend
|
|
30
|
+
- Slide after 2+ consecutive bullet-heavy slides → breathing-room or impact
|
|
31
|
+
- Slide introducing a new topic section → chapter-opener
|
|
32
|
+
- Slide with chart data or comparison → evidence
|
|
33
|
+
- Everything else → workhorse
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Design Decisions
|
|
38
|
+
|
|
39
|
+
### Slide Type Selection
|
|
40
|
+
|
|
41
|
+
| Content Signal | `type` | Key Fields |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| Standard text, bullets, headings | `"content"` (default) | `content`, `layout` |
|
|
44
|
+
| Full-viewport data visualization | `"chart"` | `chart` (ChartConfig) |
|
|
45
|
+
| Interactive 3D scene | `"r3f"` | `scene` (R3FSceneConfig) |
|
|
46
|
+
|
|
47
|
+
Most slides are `"content"`. Use `"chart"` or `"r3f"` only when the content is primarily a visualization.
|
|
48
|
+
|
|
49
|
+
### Layout Decisions
|
|
50
|
+
|
|
51
|
+
**When to use `two-column`** — set `layout: "two-column"` and split content on `---`:
|
|
52
|
+
- Comparison: before/after, old/new, us/them
|
|
53
|
+
- Pros/cons: advantages on left, considerations on right
|
|
54
|
+
- Text + chart: explanation on left, `[chart:name]` on right
|
|
55
|
+
- Text + media: bullets on left, `` on right
|
|
56
|
+
|
|
57
|
+
Do not force two-column when content is naturally sequential.
|
|
58
|
+
|
|
59
|
+
**When to center** — set `centered: true` for:
|
|
60
|
+
- Cover and CTA slides
|
|
61
|
+
- Single-message impact slides
|
|
62
|
+
- Transition slides
|
|
63
|
+
|
|
64
|
+
Set `centered: false` for content-heavy, data, and comparison slides.
|
|
65
|
+
|
|
66
|
+
**When to use brand font** — set `brandFont: true` for:
|
|
67
|
+
- Cover slide, closing/CTA slide, high-impact single-message slides
|
|
68
|
+
|
|
69
|
+
Do not use on content-heavy or data slides.
|
|
70
|
+
|
|
71
|
+
**When to show branding** — set `showBranding: true` and `brandingText` for:
|
|
72
|
+
- Cover, closing, slides likely to be screenshotted
|
|
73
|
+
|
|
74
|
+
Set `showBranding: false` for immersive slides (R3F, full-bleed video).
|
|
75
|
+
|
|
76
|
+
### Background Treatment
|
|
77
|
+
|
|
78
|
+
**Background image** — mood, atmosphere, visual evidence, or impact:
|
|
79
|
+
- Set `backgroundImageOverlay: true` and `lightText: true` when text appears over the image
|
|
80
|
+
- Use Unsplash URLs with `?w=1920&q=80`
|
|
81
|
+
|
|
82
|
+
**Background video** — cinematic section openers or demo context:
|
|
83
|
+
- Set URL to placeholder: `"PLACEHOLDER: [description of needed video]"`
|
|
84
|
+
- Set `backgroundVideoFit: "cover"`, `backgroundVideoLoop: true`
|
|
85
|
+
- Add to delivery summary
|
|
86
|
+
|
|
87
|
+
**Text contrast** — set `lightText: true` whenever background is dark:
|
|
88
|
+
- Dark `style.backgroundColor`, `backgroundImage` with overlay, `backgroundVideo`, `type: "r3f"` with dark scene
|
|
89
|
+
|
|
90
|
+
### Chart Decisions
|
|
91
|
+
|
|
92
|
+
**Chart title rule** — `label` states the insight, not the data category:
|
|
93
|
+
- Weak: "Revenue Data" → Strong: "Revenue grew 40% QoQ after the pricing change"
|
|
94
|
+
|
|
95
|
+
**Full-viewport** (`type: "chart"`) — when the data IS the slide.
|
|
96
|
+
**Inline** (`[chart:name]` in content) — when data supports a text argument.
|
|
97
|
+
|
|
98
|
+
### R3F Scene Decisions
|
|
99
|
+
|
|
100
|
+
Available scenes:
|
|
101
|
+
- `"rotating-cube"` — interactive cube, good for tech demos. Set `scene.controls: true`.
|
|
102
|
+
- `"particle-field"` — atmospheric particle cloud. Set `scene.controls: false`.
|
|
103
|
+
|
|
104
|
+
Always set `lightText: true` for R3F slides.
|
|
105
|
+
|
|
106
|
+
### Topic Badge Conventions
|
|
107
|
+
|
|
108
|
+
Format: `"NN / Section Name"` for numbered sections (`"01 / Problem"`, `"02 / Solution"`).
|
|
109
|
+
Or plain text: `"Huma Showcase"`, `"Technical Deep Dive"`.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Slide Recipes
|
|
114
|
+
|
|
115
|
+
Complete `data` field patterns. For field definitions, see `graph-json-spec`.
|
|
116
|
+
|
|
117
|
+
### Cover / Call to Action
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"label": "[Title or Ask]",
|
|
122
|
+
"topic": "[Company or Meeting Context]",
|
|
123
|
+
"content": "One sentence: what this is and for whom. (Cover) — or — what happens next. (CTA)",
|
|
124
|
+
"centered": true,
|
|
125
|
+
"brandFont": true,
|
|
126
|
+
"showBranding": true,
|
|
127
|
+
"brandingText": "[company.domain]"
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Standard Bullets
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"label": "Headline claim that makes the point",
|
|
136
|
+
"topic": "01 / Problem",
|
|
137
|
+
"content": "## Headline claim in one sentence\n\n- Specific point with a number or named entity\n- Second point — consequence or contrast\n- Third point — the implication\n\nClosing sentence bridging to the next slide.",
|
|
138
|
+
"notes": "Talking point not on screen. Time: 2 minutes max.",
|
|
139
|
+
"centered": false
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Two-Column Comparison
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"label": "Old Way vs. New Way",
|
|
148
|
+
"topic": "02 / Solution",
|
|
149
|
+
"content": "## Today\n- 3 systems, no shared state\n- 11 hours/week reconciling exports\n\n---\n\n## With [Product]\n- Single live record across all systems\n- Reports update in real time",
|
|
150
|
+
"layout": "two-column",
|
|
151
|
+
"centered": false
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Reference Example
|
|
158
|
+
|
|
159
|
+
A 7-node presentation demonstrating cover, content, two-column, inline chart, R3F, background image, and closing.
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"meta": {
|
|
164
|
+
"name": "Graph-Based Presentations"
|
|
165
|
+
},
|
|
166
|
+
"nodes": [
|
|
167
|
+
{
|
|
168
|
+
"id": "cover",
|
|
169
|
+
"type": "huma",
|
|
170
|
+
"position": { "x": 0, "y": 0 },
|
|
171
|
+
"data": {
|
|
172
|
+
"label": "Graph-Based Presentations",
|
|
173
|
+
"topic": "Huma Showcase",
|
|
174
|
+
"content": "Non-linear storytelling for technical teams.\n\nNavigate with arrow keys. Press **down** to drill into any topic.",
|
|
175
|
+
"centered": true,
|
|
176
|
+
"brandFont": true,
|
|
177
|
+
"showBranding": true,
|
|
178
|
+
"brandingText": "huma.energy"
|
|
179
|
+
},
|
|
180
|
+
"style": { "width": 180, "height": 70 },
|
|
181
|
+
"measured": { "width": 180, "height": 70 }
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"id": "problem",
|
|
185
|
+
"type": "huma",
|
|
186
|
+
"position": { "x": 240, "y": 0 },
|
|
187
|
+
"data": {
|
|
188
|
+
"label": "The Problem",
|
|
189
|
+
"topic": "01 / Problem",
|
|
190
|
+
"content": "## Linear tools break complex stories\n\n- Cannot branch based on audience questions\n- Skipping sections breaks the flow\n- No private view for speaker notes during screen share\n\nEvery meeting is different. The presentation should adapt.",
|
|
191
|
+
"notes": "Pause here and ask: 'Does this match your experience?'",
|
|
192
|
+
"centered": false
|
|
193
|
+
},
|
|
194
|
+
"style": { "width": 180, "height": 70 },
|
|
195
|
+
"measured": { "width": 180, "height": 70 }
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"id": "problem-detail",
|
|
199
|
+
"type": "huma",
|
|
200
|
+
"position": { "x": 240, "y": 150 },
|
|
201
|
+
"data": {
|
|
202
|
+
"label": "Value Breakdown",
|
|
203
|
+
"topic": "03 / Value",
|
|
204
|
+
"content": "## Flexible narratives\nAdapt flow to audience type and questions in real time\n\n---\n\n## Consistent style\nReuse front-end web styling and components directly\n\n## Professional delivery\nSpeaker notes and timing without the audience seeing them",
|
|
205
|
+
"layout": "two-column",
|
|
206
|
+
"centered": false
|
|
207
|
+
},
|
|
208
|
+
"style": { "width": 180, "height": 70 },
|
|
209
|
+
"measured": { "width": 180, "height": 70 }
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"id": "value",
|
|
213
|
+
"type": "huma",
|
|
214
|
+
"position": { "x": 480, "y": 0 },
|
|
215
|
+
"data": {
|
|
216
|
+
"label": "The Value",
|
|
217
|
+
"topic": "03 / Value",
|
|
218
|
+
"content": "## Why this approach wins\n\n[chart:value]\n\nAdapt to the audience. Reuse web components. Deliver with confidence.",
|
|
219
|
+
"charts": {
|
|
220
|
+
"value": {
|
|
221
|
+
"chartType": "radar",
|
|
222
|
+
"data": [
|
|
223
|
+
{ "axis": "Flexibility", "graph": 95, "traditional": 30 },
|
|
224
|
+
{ "axis": "Visual Quality", "graph": 90, "traditional": 50 },
|
|
225
|
+
{ "axis": "Interactivity", "graph": 85, "traditional": 20 },
|
|
226
|
+
{ "axis": "Ease of Use", "graph": 60, "traditional": 90 },
|
|
227
|
+
{ "axis": "Consistency", "graph": 85, "traditional": 40 }
|
|
228
|
+
],
|
|
229
|
+
"config": {
|
|
230
|
+
"xKey": "axis",
|
|
231
|
+
"yKeys": ["graph", "traditional"],
|
|
232
|
+
"showGrid": true,
|
|
233
|
+
"showLegend": true
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
"centered": false
|
|
238
|
+
},
|
|
239
|
+
"style": { "width": 180, "height": 70 },
|
|
240
|
+
"measured": { "width": 180, "height": 70 }
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"id": "feat-3d",
|
|
244
|
+
"type": "huma",
|
|
245
|
+
"position": { "x": 720, "y": 0 },
|
|
246
|
+
"data": {
|
|
247
|
+
"label": "3D Scenes",
|
|
248
|
+
"topic": "04 / Features",
|
|
249
|
+
"type": "r3f",
|
|
250
|
+
"scene": {
|
|
251
|
+
"component": "rotating-cube",
|
|
252
|
+
"controls": true,
|
|
253
|
+
"background": "#1a1a2e"
|
|
254
|
+
},
|
|
255
|
+
"content": "Interactive React Three Fiber scene.\n\nDrag to rotate. Scroll to zoom.",
|
|
256
|
+
"lightText": true
|
|
257
|
+
},
|
|
258
|
+
"style": { "width": 180, "height": 70 },
|
|
259
|
+
"measured": { "width": 180, "height": 70 }
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
"id": "feat-bgimage",
|
|
263
|
+
"type": "huma",
|
|
264
|
+
"position": { "x": 960, "y": 0 },
|
|
265
|
+
"data": {
|
|
266
|
+
"label": "Background Image",
|
|
267
|
+
"topic": "04 / Features",
|
|
268
|
+
"content": "## Full-bleed imagery\n\nUpload any image as a slide background. Toggle overlay for text readability.\n\n- Cover/contain fit modes\n- Dark overlay toggle\n- Light text auto-detection",
|
|
269
|
+
"backgroundImage": "https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=1920&q=80",
|
|
270
|
+
"backgroundImageFit": "cover",
|
|
271
|
+
"backgroundImageOverlay": true,
|
|
272
|
+
"lightText": true,
|
|
273
|
+
"centered": false
|
|
274
|
+
},
|
|
275
|
+
"style": { "width": 180, "height": 70 },
|
|
276
|
+
"measured": { "width": 180, "height": 70 }
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
"id": "end",
|
|
280
|
+
"type": "huma",
|
|
281
|
+
"position": { "x": 1200, "y": 0 },
|
|
282
|
+
"data": {
|
|
283
|
+
"label": "Get Started",
|
|
284
|
+
"content": "Fork this template to build your own.\n\nEvery slide, chart, and scene is editable in the graph editor.",
|
|
285
|
+
"centered": true,
|
|
286
|
+
"brandFont": true,
|
|
287
|
+
"showBranding": true,
|
|
288
|
+
"brandingText": "huma.energy"
|
|
289
|
+
},
|
|
290
|
+
"style": { "width": 180, "height": 70 },
|
|
291
|
+
"measured": { "width": 180, "height": 70 }
|
|
292
|
+
}
|
|
293
|
+
],
|
|
294
|
+
"edges": [
|
|
295
|
+
{ "id": "e-cover-problem", "source": "cover", "target": "problem", "sourceHandle": "s-right", "targetHandle": "t-left" },
|
|
296
|
+
{ "id": "e-problem-cover", "source": "problem", "target": "cover", "sourceHandle": "s-left", "targetHandle": "t-right" },
|
|
297
|
+
{ "id": "e-problem-value", "source": "problem", "target": "value", "sourceHandle": "s-right", "targetHandle": "t-left" },
|
|
298
|
+
{ "id": "e-value-problem", "source": "value", "target": "problem", "sourceHandle": "s-left", "targetHandle": "t-right" },
|
|
299
|
+
{ "id": "e-problem-detail", "source": "problem", "target": "problem-detail", "sourceHandle": "s-bottom", "targetHandle": "t-top" },
|
|
300
|
+
{ "id": "e-detail-problem", "source": "problem-detail", "target": "problem", "sourceHandle": "s-top", "targetHandle": "t-bottom" },
|
|
301
|
+
{ "id": "e-value-3d", "source": "value", "target": "feat-3d", "sourceHandle": "s-right", "targetHandle": "t-left" },
|
|
302
|
+
{ "id": "e-3d-value", "source": "feat-3d", "target": "value", "sourceHandle": "s-left", "targetHandle": "t-right" },
|
|
303
|
+
{ "id": "e-3d-bgimage", "source": "feat-3d", "target": "feat-bgimage", "sourceHandle": "s-right", "targetHandle": "t-left" },
|
|
304
|
+
{ "id": "e-bgimage-3d", "source": "feat-bgimage", "target": "feat-3d", "sourceHandle": "s-left", "targetHandle": "t-right" },
|
|
305
|
+
{ "id": "e-bgimage-end", "source": "feat-bgimage", "target": "end", "sourceHandle": "s-right", "targetHandle": "t-left" },
|
|
306
|
+
{ "id": "e-end-bgimage", "source": "end", "target": "feat-bgimage", "sourceHandle": "s-left", "targetHandle": "t-right" }
|
|
307
|
+
]
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Media Delivery Summary Format
|
|
314
|
+
|
|
315
|
+
After generating the JSON, list any slides with placeholder media:
|
|
316
|
+
|
|
317
|
+
```
|
|
318
|
+
Slides requiring manual media upload:
|
|
319
|
+
- "Cover" — background video: [description]
|
|
320
|
+
- "Demo" — inline video: [description]
|
|
321
|
+
|
|
322
|
+
Upload via POST /api/slide-images/upload (multipart/form-data, field: "file")
|
|
323
|
+
Returns { ok: true, key, url } — replace placeholder with returned url
|
|
324
|
+
Accepted: all image/*, video/mp4, video/webm, video/quicktime
|
|
325
|
+
Max size: 50MB
|
|
326
|
+
```
|