@ztffn/presentation-generator-plugin 1.2.0 → 1.3.0

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.
@@ -187,7 +187,7 @@ Replace the PLACEHOLDER string with the returned URL after upload.
187
187
  |---|---|---|
188
188
  | `presentation-content` | `content-signals` | Extract structured brief from documents |
189
189
  | `presentation-narrative` | `frameworks`, `slide-content`, `graph-topology` | Design story structure and slide content |
190
- | `presentation-design` | `node-schema`, `edge-conventions`, `layout-templates`, `positioning`, `pitch-reference` | Translate outline to valid graph JSON |
190
+ | `presentation-design` | `graph-json-spec` | Translate outline to valid graph JSON |
191
191
 
192
192
  ## Working Without Documents
193
193
 
@@ -196,3 +196,48 @@ Same content, different quality. Study what changed and why.
196
196
  | Bullets | Generic descriptions | Named roles with concrete hour counts |
197
197
  | Implication | Absent | Explicit (→ connector) |
198
198
  | Speaker notes | Repetition of screen content | Anticipation, objection routing, time guidance |
199
+
200
+ ## Visual Rhythm
201
+
202
+ Presentations that feel designed — not generated — alternate between dense and light slides. A deck of wall-to-wall bullets is exhausting. A deck of nothing but images is empty. The rhythm between them is what holds attention.
203
+
204
+ ### The Rhythm Principle
205
+
206
+ Alternate content-heavy slides with breathing-room slides. After 2-3 slides carrying bullets, data, or detailed argument, insert a visual reset: an image slide, an impact statement, or a centered single thought. This gives the audience a moment to absorb before the next dense block.
207
+
208
+ Think of it as chapters in a book. Dense paragraphs need white space between them. A presentation spine needs the same cadence.
209
+
210
+ ### Visual Intent Annotations
211
+
212
+ The narrative agent should annotate each slide in the outline with a `**Visual intent:**` line indicating the slide's visual role. These labels communicate pacing intent to the design agent without prescribing any specific layout or JSON treatment.
213
+
214
+ | Label | Purpose |
215
+ |---|---|
216
+ | `chapter-opener` | Full-bleed image, centered text, sets mood for a new section |
217
+ | `impact` | Single bold statement, centered, no bullets, emotional weight |
218
+ | `workhorse` | Standard bullets/content, the default |
219
+ | `evidence` | Data-forward: chart, table, or comparison |
220
+ | `bookend` | Cover or CTA, branded, symmetrical with its pair |
221
+ | `breathing-room` | Minimal text over image or color, resets attention after dense slides |
222
+
223
+ Example annotation in an outline:
224
+
225
+ ```
226
+ Slide 4: "Response time dropped 60% — infrastructure cost followed"
227
+ Key message: The platform delivers measurable speed and cost gains.
228
+ **Visual intent:** evidence
229
+ ```
230
+
231
+ ### Pacing Rules
232
+
233
+ 1. **No three-in-a-row.** Never place 3 or more `workhorse` slides consecutively without a visual reset (`impact`, `chapter-opener`, or `breathing-room`).
234
+
235
+ 2. **Alternate dense and light.** The spine should weave between heavy and light visual weight. `workhorse` → `evidence` → `impact` → `workhorse` is better than `workhorse` → `workhorse` → `workhorse` → `impact`.
236
+
237
+ 3. **Chapter openers at section boundaries.** When the spine moves to a new major topic, mark the transitional slide as `chapter-opener`. This signals a mood shift and gives the audience a visual cue that the argument is entering new territory.
238
+
239
+ 4. **Bookends mirror each other.** The cover slide and the closing CTA should feel symmetrical in visual weight. Both are `bookend` — they frame the presentation as a pair.
240
+
241
+ 5. **Breathing room after sustained density.** If the outline has a run of `workhorse` and `evidence` slides (detailed argument, data, comparison), follow it with a `breathing-room` or `impact` slide before continuing. The audience needs a reset.
242
+
243
+ These annotations describe intent only. How the design agent translates them into layout, background, and typography is not the narrative agent's concern.
@@ -1,97 +0,0 @@
1
- ---
2
- name: edge-conventions
3
- description: Authoritative reference for wiring navigation edges — handle IDs, bidirectional pairs, and validation checklist.
4
- ---
5
-
6
- # Edge Conventions
7
-
8
- Authoritative reference for wiring navigation edges in the presentation graph.
9
- Edges define valid navigation paths — without correct edges, arrow keys won't work.
10
-
11
- ## Handle IDs
12
-
13
- Eight handle IDs exist, four source and four target:
14
-
15
- | Handle ID | Type | Position | Navigation |
16
- |---|---|---|---|
17
- | `s-right` | source | Right side | Pressing **right arrow** follows this edge |
18
- | `s-left` | source | Left side | Pressing **left arrow** follows this edge |
19
- | `s-bottom` | source | Bottom | Pressing **down arrow** follows this edge |
20
- | `s-top` | source | Top | Pressing **up arrow** follows this edge |
21
- | `t-right` | target | Right side | Arrived via **left arrow** from source |
22
- | `t-left` | target | Left side | Arrived via **right arrow** from source |
23
- | `t-bottom` | target | Bottom | Arrived via **up arrow** from source |
24
- | `t-top` | target | Top | Arrived via **down arrow** from source |
25
-
26
- ## Bidirectional Pair Rule
27
-
28
- **Every navigation edge must have a return edge** with swapped source/target and swapped handles.
29
-
30
- If the user can press right to go from A to B, they must be able to press left to go from B back to A.
31
-
32
- ## Standard Edge Pairs
33
-
34
- ### Horizontal Forward/Back (Spine Navigation)
35
-
36
- ```json
37
- { "id": "e-a-b", "source": "a", "target": "b", "sourceHandle": "s-right", "targetHandle": "t-left" }
38
- { "id": "e-b-a", "source": "b", "target": "a", "sourceHandle": "s-left", "targetHandle": "t-right" }
39
- ```
40
-
41
- A → (right) → B and B → (left) → A
42
-
43
- ### Drill-Down / Return-to-Parent
44
-
45
- ```json
46
- { "id": "e-parent-child", "source": "parent", "target": "child", "sourceHandle": "s-bottom", "targetHandle": "t-top" }
47
- { "id": "e-child-parent", "source": "child", "target": "parent", "sourceHandle": "s-top", "targetHandle": "t-bottom" }
48
- ```
49
-
50
- Parent → (down) → Child and Child → (up) → Parent
51
-
52
- ### Horizontal Within a Drill-Down Branch
53
-
54
- Siblings within a drill-down branch use the same horizontal pattern:
55
-
56
- ```json
57
- { "id": "e-child1-child2", "source": "child1", "target": "child2", "sourceHandle": "s-right", "targetHandle": "t-left" }
58
- { "id": "e-child2-child1", "source": "child2", "target": "child1", "sourceHandle": "s-left", "targetHandle": "t-right" }
59
- ```
60
-
61
- ## Edge ID Convention
62
-
63
- Use descriptive hyphenated strings:
64
-
65
- - `e-cover-problem` — cover to problem
66
- - `e-problem-cover` — problem back to cover
67
- - `e-problem-detail` — problem drill-down to detail
68
- - `e-detail-problem` — detail return to problem
69
-
70
- Pattern: `e-{source}-{target}` using the node IDs or abbreviated forms.
71
-
72
- ## Validation Checklist
73
-
74
- Run this checklist before writing the final JSON:
75
-
76
- 1. **Every node has at least one outgoing edge** — no dead ends
77
- 2. **Every forward edge has a paired return edge** — source/target swapped, handles swapped
78
- 3. **All handle IDs are from the valid set** — only the 8 IDs listed above
79
- 4. **Source handles start with `s-`** and target handles start with `t-`
80
- 5. **The first spine node has no incoming `s-right` edge** — it's the leftmost entry point
81
- 6. **The last spine node has no outgoing `s-right` edge** (or loops back to cover)
82
- 7. **Drill-down children always have `s-top`/`t-bottom` return edge to parent**
83
- 8. **No duplicate edge IDs**
84
-
85
- ## Edge Object Structure
86
-
87
- ```json
88
- {
89
- "id": "e-cover-problem",
90
- "source": "cover",
91
- "target": "problem",
92
- "sourceHandle": "s-right",
93
- "targetHandle": "t-left"
94
- }
95
- ```
96
-
97
- All four fields (`source`, `target`, `sourceHandle`, `targetHandle`) are required. Edges without explicit handles will have direction inferred from node positions, but this is a fallback — always set handles explicitly.
@@ -1,315 +0,0 @@
1
- ---
2
- name: layout-templates
3
- description: Decision guide mapping content signals to slide type, layout, background treatment, and visual configuration.
4
- ---
5
-
6
- # Layout Templates & Design Decisions
7
-
8
- Decision guide for the design agent. Maps content signals from the slide outline
9
- to the correct visual treatment in the graph JSON.
10
-
11
- ## Slide Type Selection
12
-
13
- | Content Signal | `type` | Key Fields |
14
- |---|---|---|
15
- | Standard text, bullets, headings | `"content"` (default) | `content`, `layout` |
16
- | Full-viewport data visualization | `"chart"` | `chart` (ChartConfig) |
17
- | Interactive 3D scene | `"r3f"` | `scene` (R3FSceneConfig) |
18
-
19
- Most slides are `"content"`. Use `"chart"` or `"r3f"` only when the content is primarily a visualization.
20
-
21
- ## Layout Decisions
22
-
23
- ### When to Use `two-column`
24
-
25
- Set `layout: "two-column"` and split content on `---` when:
26
-
27
- - **Comparison:** before/after, old/new, us/them
28
- - **Pros/cons:** advantages on left, considerations on right
29
- - **Text + chart:** explanation on left, `[chart:name]` on right
30
- - **Text + media:** bullets on left, `![](image)` on right
31
- - **Dual evidence:** two independent supporting points side by side
32
-
33
- Do not force two-column when content is naturally sequential.
34
-
35
- ### When to Center
36
-
37
- Set `centered: true` for:
38
-
39
- - **Cover slides:** Title + subtitle, branded
40
- - **Call-to-action slides:** Single message, end of presentation
41
- - **Single-message impact slides:** One powerful statement or quote
42
- - **Transition slides:** Brief pause between major sections
43
-
44
- Set `centered: false` for:
45
-
46
- - **Content-heavy slides:** Bullets, tables, code, multiple paragraphs
47
- - **Data slides:** Charts with explanatory text
48
- - **Comparison slides:** Two-column layouts
49
-
50
- ### When to Use Brand Font
51
-
52
- Set `brandFont: true` for:
53
-
54
- - Cover slide (first slide)
55
- - Closing/CTA slide (last slide)
56
- - High-impact single-message slides
57
-
58
- Do not use on content-heavy or data slides — brand fonts are display fonts, not body fonts.
59
-
60
- ### When to Show Branding
61
-
62
- Set `showBranding: true` and `brandingText: "huma.energy"` (or client name) for:
63
-
64
- - Cover slide
65
- - Closing slide
66
- - Any slide where the audience might screenshot or reference later
67
-
68
- Default is `true`, so only set `showBranding: false` for immersive slides (R3F, full-bleed video) where the overlay is distracting.
69
-
70
- ## Background Treatment
71
-
72
- ### Background Image
73
-
74
- Use `backgroundImage` when the outline indicates:
75
- - A mood or atmosphere for a section opener
76
- - Visual evidence (photo of a product, facility, or result)
77
- - Impact slide where imagery reinforces the message
78
-
79
- Set `backgroundImageOverlay: true` and `lightText: true` when text appears over the image.
80
-
81
- **Image sourcing:** Use external URLs directly. Unsplash with query params works well:
82
- ```
83
- https://images.unsplash.com/photo-XXXXX?w=1920&q=80
84
- ```
85
-
86
- ### Background Video
87
-
88
- Use `backgroundVideo` for cinematic section openers or demo context.
89
-
90
- **Video sourcing is deferred.** For any slide requiring background video:
91
- 1. Set `backgroundVideo` to a placeholder: `"PLACEHOLDER: [description of needed video]"`
92
- 2. Set `backgroundVideoFit: "cover"` and `backgroundVideoLoop: true`
93
- 3. Add the slide title to the delivery summary for manual upload
94
-
95
- ### Inline Video
96
-
97
- For videos embedded in slide content (via `![alt](url)` in markdown):
98
- 1. Set the URL to a placeholder: `"PLACEHOLDER: [description]"`
99
- 2. Configure `inlineVideoControls`, `inlineVideoAutoplay`, `inlineVideoLoop` as appropriate
100
- 3. Add to delivery summary
101
-
102
- ### Text Contrast
103
-
104
- Set `lightText: true` whenever the background is dark:
105
- - Dark `style.backgroundColor`
106
- - `backgroundImage` with `backgroundImageOverlay: true`
107
- - `backgroundVideo` slides
108
- - `type: "r3f"` with dark scene background
109
-
110
- ## Chart Decisions
111
-
112
- ### Full-Viewport Chart (`type: "chart"`)
113
-
114
- Use when the data IS the slide — the chart is the primary message, not supporting evidence.
115
-
116
- ```json
117
- {
118
- "type": "chart",
119
- "chart": {
120
- "chartType": "bar",
121
- "data": [...],
122
- "config": { "xKey": "quarter", "yKeys": ["revenue", "cost"], "showGrid": true, "showLegend": true }
123
- },
124
- "content": "Optional caption below the chart"
125
- }
126
- ```
127
-
128
- ### Inline Chart (`[chart:name]` in content)
129
-
130
- Use when data supports a text argument — the chart is evidence, not the headline.
131
-
132
- ```json
133
- {
134
- "content": "## Why this approach wins\n\n[chart:comparison]\n\nAdapt to the audience. Deliver with confidence.",
135
- "charts": {
136
- "comparison": {
137
- "chartType": "radar",
138
- "data": [...],
139
- "config": { "xKey": "axis", "yKeys": ["ours", "theirs"], "showLegend": true }
140
- }
141
- }
142
- }
143
- ```
144
-
145
- ### Chart Title Rule
146
-
147
- A chart's `label` field states the insight, not the data category. The audience should understand your point before reading the chart.
148
-
149
- | Weak (category label) | Strong (insight claim) |
150
- |---|---|
151
- | "Revenue Data" | "Revenue grew 40% QoQ after the pricing change" |
152
- | "Response Time" | "Response time dropped 60% after caching rollout" |
153
- | "User Growth" | "1M users in 6 months — 2× ahead of plan" |
154
-
155
- The label is your assertion. The chart is your evidence.
156
-
157
- ### Chart Type Selection
158
-
159
- | Data Pattern | Chart Type |
160
- |---|---|
161
- | Trend over time | `"line"` or `"area"` |
162
- | Category comparison | `"bar"` |
163
- | Multi-axis comparison | `"radar"` |
164
- | Part-of-whole | `"pie"` |
165
- | Volume trend | `"area"` |
166
-
167
- ## R3F Scene Decisions
168
-
169
- Use `type: "r3f"` when the outline calls for a 3D demo or visual impact.
170
-
171
- Available scenes:
172
- - `"rotating-cube"` — interactive cube, good for tech demos. Set `scene.controls: true`.
173
- - `"particle-field"` — atmospheric particle cloud. Set `scene.controls: false`.
174
-
175
- Always set `lightText: true` for R3F slides (dark backgrounds). Content renders as an overlay on top of the 3D scene.
176
-
177
- ## Topic Badge Conventions
178
-
179
- Use `topic` to group slides by section. Format: `"NN / Section Name"` for numbered sections:
180
-
181
- - `"01 / Problem"`
182
- - `"02 / Solution"`
183
- - `"03 / Value"`
184
- - `"04 / Evidence"`
185
-
186
- Or plain text for non-numbered groupings: `"Huma Showcase"`, `"Technical Deep Dive"`.
187
-
188
- ## Slide Recipes
189
-
190
- Complete `data` field patterns for common pitch slide types. Combine with `node-schema.md` for the full field reference.
191
-
192
- ### Cover / Call to Action
193
-
194
- Cover = first spine node. CTA = last. Both: centered, branded, no bullets. The only difference is the label and content.
195
-
196
- ```json
197
- {
198
- "label": "[Title or Ask]",
199
- "topic": "[Company or Meeting Context]",
200
- "content": "One sentence: what this is and for whom. (Cover) — or — what happens next and when. (CTA)",
201
- "centered": true,
202
- "brandFont": true,
203
- "showBranding": true,
204
- "brandingText": "[company.domain]"
205
- }
206
- ```
207
-
208
- ### Standard Bullets — Workhorse
209
-
210
- Default for problem, solution, evidence, and detail nodes.
211
-
212
- ```json
213
- {
214
- "label": "Headline claim that makes the point",
215
- "topic": "01 / Problem",
216
- "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.",
217
- "notes": "Talking point not on screen. Objection signal: 'If they ask X, navigate to [node-id].' Time: 2 minutes max.",
218
- "centered": false
219
- }
220
- ```
221
-
222
- ### Impact Statement
223
-
224
- Single message, no bullets. Use for named shifts, "why now" openers, or bold claims that stand alone.
225
-
226
- ```json
227
- {
228
- "label": "The Shift",
229
- "topic": "01 / Problem",
230
- "content": "The market has permanently changed.\n\n**Batch scheduling is structurally incompatible with same-day delivery expectations.**",
231
- "notes": "Pause. Do not advance immediately. If the room agrees, the rest is inevitable.",
232
- "centered": true
233
- }
234
- ```
235
-
236
- ### Two-Column Comparison
237
-
238
- Before/after, us/them, or two parallel arguments. Content splits on `---`; left column renders first.
239
-
240
- ```json
241
- {
242
- "label": "Old Way vs. New Way",
243
- "topic": "02 / Solution",
244
- "content": "## Today\n- 3 systems, no shared state\n- 11 hours/week reconciling exports\n- Reports are always one day stale\n\n---\n\n## With [Product]\n- Single live record across all systems\n- Reports update in real time\n- Finance, ops, and leadership see the same data",
245
- "layout": "two-column",
246
- "centered": false
247
- }
248
- ```
249
-
250
- ### Text + Inline Chart
251
-
252
- Text on left makes the claim; chart on right is the evidence. Chart is supporting, not the headline.
253
-
254
- ```json
255
- {
256
- "label": "The Data Confirms It",
257
- "topic": "03 / Evidence",
258
- "content": "## Continuous monitoring outperforms batch on every metric\n\nThree field studies. Same result each time.\n\n---\n\n[chart:comparison]",
259
- "charts": {
260
- "comparison": {
261
- "chartType": "bar",
262
- "data": [{ "metric": "Uptime %", "ours": 98.2, "baseline": 91.5 }],
263
- "config": { "xKey": "metric", "yKeys": ["ours", "baseline"], "showGrid": true, "showLegend": true }
264
- }
265
- },
266
- "layout": "two-column",
267
- "centered": false
268
- }
269
- ```
270
-
271
- ### Proof Point — Customer Quote
272
-
273
- Named case study or customer quote. Blockquote (`>`) renders as a styled pull quote — lead with it before the numbers.
274
-
275
- ```json
276
- {
277
- "label": "Summit Health: Year One",
278
- "topic": "04 / Proof",
279
- "content": "## 2.3 hours of admin time eliminated per nurse per shift\n\n> \"The conflicts surfaced automatically — we'd been creating them for years without knowing it.\"\n> — VP Operations, Summit Health (42 facilities)\n\n- 38% reduction in shift coverage failures\n- Full rollout across 6 units in 11 weeks",
280
- "notes": "If they ask about rollout timeline, the drill-down below has the full breakdown.",
281
- "centered": false
282
- }
283
- ```
284
-
285
- ### Section Opener — Background Image
286
-
287
- Spine node opening a new chapter. Sets atmosphere. Max 3 bullet points on an image slide.
288
-
289
- ```json
290
- {
291
- "label": "The Opportunity",
292
- "topic": "03 / Opportunity",
293
- "content": "## A $40B market with no dominant platform\n\nEvery competitor is solving scheduling.\nNobody is solving the coordination layer.",
294
- "backgroundImage": "https://images.unsplash.com/photo-XXXXX?w=1920&q=80",
295
- "backgroundImageFit": "cover",
296
- "backgroundImageOverlay": true,
297
- "lightText": true,
298
- "centered": false
299
- }
300
- ```
301
-
302
- ## Media Delivery Summary
303
-
304
- After generating the JSON, list any slides with placeholder media:
305
-
306
- ```
307
- Slides requiring manual media upload:
308
- - "Cover" — background video: [description]
309
- - "Demo" — inline video: [description]
310
-
311
- Upload via POST /api/slide-images/upload (multipart/form-data, field: "file")
312
- Returns { ok: true, key, url } — replace placeholder with returned url
313
- Accepted: all image/*, video/mp4, video/webm, video/quicktime
314
- Max size: 50MB
315
- ```
@@ -1,135 +0,0 @@
1
- ---
2
- name: node-schema
3
- description: Authoritative reference for SlideNodeData interface — all fields, types, and defaults for graph presentation nodes.
4
- ---
5
-
6
- # Node Schema Reference
7
-
8
- Authoritative reference for the `SlideNodeData` interface.
9
- Derived from `src/types/presentation.ts`. All fields, types, and defaults documented here.
10
-
11
- ## Node Wrapper
12
-
13
- Every node in the graph has this structure:
14
-
15
- ```json
16
- {
17
- "id": "unique-slug",
18
- "type": "huma",
19
- "position": { "x": 0, "y": 0 },
20
- "data": { /* SlideNodeData fields below */ },
21
- "style": { "width": 180, "height": 70 },
22
- "measured": { "width": 180, "height": 70 }
23
- }
24
- ```
25
-
26
- - `id`: Kebab-case slug (e.g. `"cover"`, `"problem-detail"`, `"feat-3d"`)
27
- - `type`: Always `"huma"` — the custom node type with directional handles
28
- - `position`: `{ x, y }` in graph canvas coordinates (see `positioning.md`)
29
- - `style.width`: Always `180`. `style.height`: Always `70`.
30
- - `measured`: Must mirror `style` — `{ width: 180, height: 70 }`
31
- - Optional: `style.backgroundColor` — hex string for node background in the graph editor (also applied as slide background)
32
-
33
- ## SlideNodeData Fields
34
-
35
- ### Content Fields
36
-
37
- | Field | Type | Default | Description |
38
- |---|---|---|---|
39
- | `label` | `string?` | — | Slide title displayed in graph editor and as slide heading |
40
- | `topic` | `string?` | — | Section badge on the slide (e.g. `"01 / Problem"`, `"Solution"`) |
41
- | `content` | `string?` | — | Markdown body. Supports headings, bullets, bold, code, tables, `[chart:name]` embeds, `![](url)` images/videos, `[text](#nodeId)` navigation links |
42
- | `notes` | `string?` | — | Speaker notes, shown only in the presenter panel |
43
-
44
- ### Slide Type
45
-
46
- | Field | Type | Default | Description |
47
- |---|---|---|---|
48
- | `type` | `"content" \| "r3f" \| "chart" \| "custom"` | `"content"` | Slide renderer. `"content"` for standard text, `"r3f"` for 3D scene, `"chart"` for full-viewport chart |
49
-
50
- ### Layout & Display
51
-
52
- | Field | Type | Default | Description |
53
- |---|---|---|---|
54
- | `centered` | `boolean?` | `true` | Center content vertically and horizontally |
55
- | `layout` | `"single" \| "two-column"` | `"single"` | Content layout. `"two-column"` splits on `---` delimiter in content |
56
- | `lightText` | `boolean?` | `false` | Force white text for dark backgrounds |
57
- | `brandFont` | `boolean?` | `false` | Use HumaDisplay display font for the title |
58
- | `showBranding` | `boolean?` | `true` | Show branding overlay |
59
- | `brandingText` | `string?` | — | Bottom-left branding label (e.g. `"huma.energy"`) |
60
-
61
- ### Background Media
62
-
63
- | Field | Type | Default | Description |
64
- |---|---|---|---|
65
- | `backgroundImage` | `string?` | — | URL to background image |
66
- | `backgroundImageFit` | `"cover" \| "contain"` | `"cover"` | How image fills the slide |
67
- | `backgroundImageOverlay` | `boolean?` | `false` | Dark scrim over background image for text readability |
68
- | `backgroundVideo` | `string?` | — | URL to background video |
69
- | `backgroundVideoFit` | `"cover" \| "contain"` | `"cover"` | How video fills the slide |
70
- | `backgroundVideoLoop` | `boolean?` | `true` | Loop background video |
71
-
72
- ### Inline Video
73
-
74
- | Field | Type | Default | Description |
75
- |---|---|---|---|
76
- | `inlineVideoControls` | `boolean?` | `true` | Show controls on inline videos in `content` |
77
- | `inlineVideoAutoplay` | `boolean?` | `true` | Autoplay inline videos |
78
- | `inlineVideoLoop` | `boolean?` | `true` | Loop inline videos |
79
-
80
- ### R3F Scene (when `type: "r3f"`)
81
-
82
- | Field | Type | Default | Description |
83
- |---|---|---|---|
84
- | `scene.component` | `string` | — | Registry key (e.g. `"rotating-cube"`, `"particle-field"`) |
85
- | `scene.props` | `Record<string, unknown>?` | — | Props passed to the scene component |
86
- | `scene.controls` | `boolean?` | — | Enable OrbitControls for user interaction |
87
- | `scene.background` | `string?` | — | Scene background hex color |
88
-
89
- ### Charts
90
-
91
- **Full-viewport chart** (when `type: "chart"`):
92
-
93
- | Field | Type | Default | Description |
94
- |---|---|---|---|
95
- | `chart.chartType` | `"bar" \| "line" \| "area" \| "pie" \| "radar"` | — | Chart renderer |
96
- | `chart.data` | `Array<Record<string, unknown>>` | — | Data array |
97
- | `chart.config.xKey` | `string?` | — | X-axis data key |
98
- | `chart.config.yKeys` | `string[]?` | — | Y-axis data keys |
99
- | `chart.config.colors` | `string[]?` | — | Series colors |
100
- | `chart.config.showGrid` | `boolean?` | — | Show grid lines |
101
- | `chart.config.showLegend` | `boolean?` | — | Show legend |
102
-
103
- **Inline charts** (referenced via `[chart:name]` in content):
104
-
105
- | Field | Type | Default | Description |
106
- |---|---|---|---|
107
- | `charts` | `Record<string, ChartConfig>` | — | Named chart configurations. Key is referenced in content as `[chart:keyname]` |
108
-
109
- Each `ChartConfig` has the same shape as `chart` above.
110
-
111
- ## Available R3F Scene Components
112
-
113
- | Registry Key | Description |
114
- |---|---|
115
- | `rotating-cube` | Interactive rotating cube with OrbitControls |
116
- | `particle-field` | Animated particle cloud background |
117
-
118
- ## Content Markdown Features
119
-
120
- The `content` field supports:
121
-
122
- - `## Heading` — headings (ATX style only, no setext)
123
- - `- bullet` or `* bullet` — unordered lists
124
- - `1. item` — ordered lists
125
- - `` ```language ``` `` — syntax-highlighted code blocks
126
- - `> blockquote` — styled blockquotes
127
- - `**bold**` and `*italic*` — inline formatting
128
- - `| col | col |` — GFM tables
129
- - `![alt](url)` — images; `.mp4/.webm/.mov` URLs render as inline video
130
- - `[text](url)` — external links (open in new tab)
131
- - `[text](#nodeId)` — navigation links to other slides
132
- - `[chart:name]` — inline chart embed (must be on its own line)
133
- - `---` — column delimiter when `layout: "two-column"`
134
- - Single newline = visible line break (not collapsed)
135
- - Multiple blank lines = visible vertical spacing