@strategicnerds/slide-nerds 0.1.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.
Files changed (101) hide show
  1. package/dist/cli/commands/analytics.d.ts +6 -0
  2. package/dist/cli/commands/analytics.d.ts.map +1 -0
  3. package/dist/cli/commands/analytics.js +44 -0
  4. package/dist/cli/commands/analytics.js.map +1 -0
  5. package/dist/cli/commands/create.d.ts +4 -0
  6. package/dist/cli/commands/create.d.ts.map +1 -0
  7. package/dist/cli/commands/create.js +87 -0
  8. package/dist/cli/commands/create.js.map +1 -0
  9. package/dist/cli/commands/export.d.ts +6 -0
  10. package/dist/cli/commands/export.d.ts.map +1 -0
  11. package/dist/cli/commands/export.js +109 -0
  12. package/dist/cli/commands/export.js.map +1 -0
  13. package/dist/cli/index.d.ts +3 -0
  14. package/dist/cli/index.d.ts.map +1 -0
  15. package/dist/cli/index.js +12 -0
  16. package/dist/cli/index.js.map +1 -0
  17. package/dist/cli/template-path.d.ts +4 -0
  18. package/dist/cli/template-path.d.ts.map +1 -0
  19. package/dist/cli/template-path.js +13 -0
  20. package/dist/cli/template-path.js.map +1 -0
  21. package/dist/runtime/export-api.d.ts +15 -0
  22. package/dist/runtime/export-api.d.ts.map +1 -0
  23. package/dist/runtime/export-api.js +21 -0
  24. package/dist/runtime/export-api.js.map +1 -0
  25. package/dist/runtime/index.d.ts +12 -0
  26. package/dist/runtime/index.d.ts.map +1 -0
  27. package/dist/runtime/index.js +8 -0
  28. package/dist/runtime/index.js.map +1 -0
  29. package/dist/runtime/light-table.d.ts +8 -0
  30. package/dist/runtime/light-table.d.ts.map +1 -0
  31. package/dist/runtime/light-table.js +104 -0
  32. package/dist/runtime/light-table.js.map +1 -0
  33. package/dist/runtime/presenter-view.d.ts +7 -0
  34. package/dist/runtime/presenter-view.d.ts.map +1 -0
  35. package/dist/runtime/presenter-view.js +62 -0
  36. package/dist/runtime/presenter-view.js.map +1 -0
  37. package/dist/runtime/slide-context.d.ts +16 -0
  38. package/dist/runtime/slide-context.d.ts.map +1 -0
  39. package/dist/runtime/slide-context.js +18 -0
  40. package/dist/runtime/slide-context.js.map +1 -0
  41. package/dist/runtime/slide-controls.d.ts +3 -0
  42. package/dist/runtime/slide-controls.d.ts.map +1 -0
  43. package/dist/runtime/slide-controls.js +177 -0
  44. package/dist/runtime/slide-controls.js.map +1 -0
  45. package/dist/runtime/slide-dom.d.ts +17 -0
  46. package/dist/runtime/slide-dom.d.ts.map +1 -0
  47. package/dist/runtime/slide-dom.js +89 -0
  48. package/dist/runtime/slide-dom.js.map +1 -0
  49. package/dist/runtime/slide-runtime.d.ts +7 -0
  50. package/dist/runtime/slide-runtime.d.ts.map +1 -0
  51. package/dist/runtime/slide-runtime.js +125 -0
  52. package/dist/runtime/slide-runtime.js.map +1 -0
  53. package/dist/runtime/slide-shape.d.ts +21 -0
  54. package/dist/runtime/slide-shape.d.ts.map +1 -0
  55. package/dist/runtime/slide-shape.js +115 -0
  56. package/dist/runtime/slide-shape.js.map +1 -0
  57. package/dist/runtime/types.d.ts +150 -0
  58. package/dist/runtime/types.d.ts.map +1 -0
  59. package/dist/runtime/types.js +38 -0
  60. package/dist/runtime/types.js.map +1 -0
  61. package/dist/runtime/use-presenter-mode.d.ts +14 -0
  62. package/dist/runtime/use-presenter-mode.d.ts.map +1 -0
  63. package/dist/runtime/use-presenter-mode.js +52 -0
  64. package/dist/runtime/use-presenter-mode.js.map +1 -0
  65. package/dist/runtime/use-slide-navigation.d.ts +13 -0
  66. package/dist/runtime/use-slide-navigation.d.ts.map +1 -0
  67. package/dist/runtime/use-slide-navigation.js +230 -0
  68. package/dist/runtime/use-slide-navigation.js.map +1 -0
  69. package/package.json +64 -0
  70. package/skills/accessibility/SKILL.md +236 -0
  71. package/skills/advanced-layouts/SKILL.md +429 -0
  72. package/skills/analytics/SKILL.md +97 -0
  73. package/skills/animation/SKILL.md +364 -0
  74. package/skills/brand/SKILL.md +200 -0
  75. package/skills/data-visualization/SKILL.md +533 -0
  76. package/skills/deck-templates/SKILL.md +93 -0
  77. package/skills/diagrams/SKILL.md +395 -0
  78. package/skills/export/SKILL.md +119 -0
  79. package/skills/interactive/SKILL.md +292 -0
  80. package/skills/layout/SKILL.md +178 -0
  81. package/skills/narrative-frameworks/SKILL.md +250 -0
  82. package/skills/react-component-embeds/SKILL.md +73 -0
  83. package/skills/slide-types/SKILL.md +384 -0
  84. package/skills/slidenerds-runtime/SKILL.md +163 -0
  85. package/skills/speaker-notes/SKILL.md +128 -0
  86. package/skills/strategic-frameworks/SKILL.md +392 -0
  87. package/skills/visual-design/SKILL.md +373 -0
  88. package/templates/analytics/custom.tsx.tmpl +20 -0
  89. package/templates/analytics/ga4.tsx.tmpl +15 -0
  90. package/templates/analytics/gtm.tsx.tmpl +9 -0
  91. package/templates/analytics/plausible.tsx.tmpl +10 -0
  92. package/templates/analytics/posthog.tsx.tmpl +14 -0
  93. package/templates/next-app/CLAUDE.md.tmpl +574 -0
  94. package/templates/next-app/README.md.tmpl +35 -0
  95. package/templates/next-app/app/globals.css.tmpl +274 -0
  96. package/templates/next-app/app/layout.tsx.tmpl +31 -0
  97. package/templates/next-app/app/page.tsx.tmpl +38 -0
  98. package/templates/next-app/brand.config.ts.tmpl +32 -0
  99. package/templates/next-app/package.json.tmpl +25 -0
  100. package/templates/next-app/postcss.config.mjs.tmpl +8 -0
  101. package/templates/next-app/tsconfig.json.tmpl +21 -0
@@ -0,0 +1,533 @@
1
+ ---
2
+ name: data-visualization
3
+ description: Chart types, KPI cards, dashboard patterns, and data styling rules for slidenerds slides using Recharts
4
+ ---
5
+
6
+ # Data visualization skill
7
+
8
+ Use this skill when a slide needs charts, graphs, KPI displays, or any quantitative data visualization. All patterns use Recharts (React charting library) with brand-aware styling.
9
+
10
+ ## Recharts setup
11
+
12
+ Install Recharts in the deck project:
13
+
14
+ ```bash
15
+ npm install recharts
16
+ ```
17
+
18
+ Import components as needed:
19
+
20
+ ```tsx
21
+ import {
22
+ BarChart, Bar, LineChart, Line, AreaChart, Area,
23
+ PieChart, Pie, Cell, RadarChart, Radar, PolarGrid,
24
+ PolarAngleAxis, ScatterChart, Scatter,
25
+ XAxis, YAxis, CartesianGrid, Tooltip,
26
+ ResponsiveContainer, ComposedChart,
27
+ } from 'recharts'
28
+ ```
29
+
30
+ ## Global chart styling rules
31
+
32
+ Every chart on a slide must follow these rules for consistency and projection readability.
33
+
34
+ ### Axes
35
+
36
+ ```tsx
37
+ <XAxis
38
+ dataKey="name"
39
+ stroke="transparent"
40
+ tick={{ fill: 'rgba(255,255,255,0.5)', fontSize: 13, fontFamily: 'var(--font-heading)' }}
41
+ tickLine={false}
42
+ axisLine={false}
43
+ />
44
+ <YAxis
45
+ stroke="transparent"
46
+ tick={{ fill: 'rgba(255,255,255,0.35)', fontSize: 12 }}
47
+ tickLine={false}
48
+ axisLine={false}
49
+ width={50}
50
+ />
51
+ ```
52
+
53
+ - Remove axis lines and tick lines. They add noise.
54
+ - X-axis labels at 50% opacity. Y-axis labels at 35%.
55
+ - Use the heading font for x-axis labels (they are category names the audience reads).
56
+ - Set explicit `width` on YAxis to prevent layout shifts.
57
+
58
+ ### Grid
59
+
60
+ ```tsx
61
+ <CartesianGrid strokeDasharray="3 3" stroke="rgba(255,255,255,0.04)" />
62
+ ```
63
+
64
+ - Barely visible. 4% white opacity. The grid orients the eye without competing with data.
65
+ - Always dashed, never solid.
66
+
67
+ ### Tooltip
68
+
69
+ ```tsx
70
+ <Tooltip
71
+ contentStyle={{
72
+ background: 'var(--color-surface-elevated)',
73
+ border: '1px solid var(--color-border)',
74
+ borderRadius: 10,
75
+ }}
76
+ labelStyle={{ color: 'rgba(255,255,255,0.5)' }}
77
+ itemStyle={{ color: 'var(--color-accent)' }}
78
+ />
79
+ ```
80
+
81
+ ### Container
82
+
83
+ Always wrap charts in a card surface and use `ResponsiveContainer`:
84
+
85
+ ```tsx
86
+ <div className="card-surface p-8">
87
+ <ResponsiveContainer width="100%" height={400}>
88
+ {/* Chart */}
89
+ </ResponsiveContainer>
90
+ </div>
91
+ ```
92
+
93
+ - Fixed pixel height (300-420px). Never use `height="100%"` -- it breaks when the parent is hidden.
94
+ - Card surface provides visual containment and depth.
95
+
96
+ ### Animation
97
+
98
+ ```tsx
99
+ <Bar animationDuration={800} animationEasing="ease-out" />
100
+ ```
101
+
102
+ - Duration: 600-800ms. Fast enough for presentation pacing, slow enough to be noticed.
103
+ - Easing: `ease-out` (decelerating). Never `linear`.
104
+ - Reveal the chart with `data-step` so the animation plays when the presenter advances.
105
+
106
+ ### Color
107
+
108
+ - Primary data series: `var(--color-accent)` or the accent hex value.
109
+ - Secondary series: Use opacity variants (80%, 60%, 40%) of the accent.
110
+ - For multi-series charts, use the color-blind safe palette from the accessibility skill.
111
+ - Maximum 4 data series per chart. More is unreadable.
112
+
113
+ ### Data point limits
114
+
115
+ | Chart type | Max data points | Why |
116
+ |---|---|---|
117
+ | Bar chart | 8-10 bars | Labels overlap beyond 10 |
118
+ | Line chart | 12-15 points | More becomes a dense mess |
119
+ | Pie / donut | 5-6 slices | Small slices are meaningless |
120
+ | Radar | 5-8 axes | More creates visual noise |
121
+ | Scatter | 20-30 points | More requires a dashboard, not a slide |
122
+
123
+ ## Bar chart
124
+
125
+ Use for: comparisons across categories, revenue by quarter, feature usage.
126
+
127
+ ### Vertical bar chart
128
+
129
+ ```tsx
130
+ <ResponsiveContainer width="100%" height={400}>
131
+ <BarChart data={data} barCategoryGap="20%">
132
+ <CartesianGrid strokeDasharray="3 3" stroke="rgba(255,255,255,0.04)" />
133
+ <XAxis dataKey="name" stroke="transparent"
134
+ tick={{ fill: 'rgba(255,255,255,0.5)', fontSize: 13 }}
135
+ tickLine={false} axisLine={false} />
136
+ <YAxis stroke="transparent"
137
+ tick={{ fill: 'rgba(255,255,255,0.35)', fontSize: 12 }}
138
+ tickLine={false} axisLine={false} width={50} />
139
+ <Tooltip contentStyle={{ background: '#222228', border: '1px solid rgba(255,255,255,0.06)', borderRadius: 10 }} />
140
+ <Bar dataKey="value" fill="var(--color-accent)" radius={[6, 6, 0, 0]}
141
+ animationDuration={800} />
142
+ </BarChart>
143
+ </ResponsiveContainer>
144
+ ```
145
+
146
+ - `radius={[6, 6, 0, 0]}` rounds top corners. Looks modern.
147
+ - `barCategoryGap="20%"` gives bars breathing room.
148
+
149
+ ### Horizontal bar chart
150
+
151
+ Use for: rankings, survey results, comparisons where labels are long.
152
+
153
+ ```tsx
154
+ <BarChart data={data} layout="vertical" barCategoryGap="25%">
155
+ <XAxis type="number" stroke="transparent"
156
+ tick={{ fill: 'rgba(255,255,255,0.35)', fontSize: 12 }}
157
+ tickLine={false} axisLine={false} />
158
+ <YAxis type="category" dataKey="name" stroke="transparent"
159
+ tick={{ fill: 'rgba(255,255,255,0.5)', fontSize: 13 }}
160
+ tickLine={false} axisLine={false} width={120} />
161
+ <Bar dataKey="value" fill="var(--color-accent)" radius={[0, 6, 6, 0]}
162
+ animationDuration={800} />
163
+ </BarChart>
164
+ ```
165
+
166
+ ### Stacked bar chart
167
+
168
+ Use for: composition breakdown (revenue by segment, traffic by source).
169
+
170
+ ```tsx
171
+ <BarChart data={data}>
172
+ {/* ... axes */}
173
+ <Bar dataKey="segment1" stackId="a" fill="var(--color-accent)" />
174
+ <Bar dataKey="segment2" stackId="a" fill="rgba(245,158,11,0.6)" />
175
+ <Bar dataKey="segment3" stackId="a" fill="rgba(245,158,11,0.3)"
176
+ radius={[6, 6, 0, 0]} />
177
+ </BarChart>
178
+ ```
179
+
180
+ - Only the top bar gets `radius`. Lower bars have flat tops.
181
+ - Use opacity variants of the accent for segment colors.
182
+ - Max 3-4 segments. More is noise.
183
+
184
+ ## Line chart
185
+
186
+ Use for: trends over time, growth trajectories, comparisons across time periods.
187
+
188
+ ```tsx
189
+ <ResponsiveContainer width="100%" height={380}>
190
+ <LineChart data={data}>
191
+ <CartesianGrid strokeDasharray="3 3" stroke="rgba(255,255,255,0.04)" />
192
+ <XAxis dataKey="month" stroke="transparent"
193
+ tick={{ fill: 'rgba(255,255,255,0.5)', fontSize: 12 }}
194
+ tickLine={false} axisLine={false} />
195
+ <YAxis stroke="transparent"
196
+ tick={{ fill: 'rgba(255,255,255,0.35)', fontSize: 12 }}
197
+ tickLine={false} axisLine={false} width={50} />
198
+ <Line type="monotone" dataKey="value" stroke="var(--color-accent)"
199
+ strokeWidth={2.5} dot={{ fill: 'var(--color-accent)', r: 4, strokeWidth: 0 }}
200
+ animationDuration={800} />
201
+ </LineChart>
202
+ </ResponsiveContainer>
203
+ ```
204
+
205
+ ### Multi-line chart
206
+
207
+ ```tsx
208
+ <Line type="monotone" dataKey="revenue" stroke="#f59e0b" strokeWidth={2.5}
209
+ dot={{ r: 3 }} />
210
+ <Line type="monotone" dataKey="costs" stroke="rgba(255,255,255,0.3)" strokeWidth={1.5}
211
+ dot={{ r: 2 }} strokeDasharray="5 5" />
212
+ ```
213
+
214
+ - Primary metric: solid line, thick (2.5px), accent color, larger dots.
215
+ - Secondary metric: dashed line, thin (1.5px), muted color, smaller dots.
216
+ - Max 3 lines. Beyond that, use separate slides.
217
+
218
+ ## Area chart
219
+
220
+ Use for: volume over time, emphasizing magnitude, cumulative data.
221
+
222
+ ```tsx
223
+ <AreaChart data={data}>
224
+ <defs>
225
+ <linearGradient id="areaGrad" x1="0" y1="0" x2="0" y2="1">
226
+ <stop offset="0%" stopColor="var(--color-accent)" stopOpacity={0.25} />
227
+ <stop offset="100%" stopColor="var(--color-accent)" stopOpacity={0} />
228
+ </linearGradient>
229
+ </defs>
230
+ <CartesianGrid strokeDasharray="3 3" stroke="rgba(255,255,255,0.04)" />
231
+ {/* ... axes */}
232
+ <Area type="monotone" dataKey="users" stroke="var(--color-accent)"
233
+ strokeWidth={2.5} fill="url(#areaGrad)" animationDuration={800}
234
+ dot={{ fill: 'var(--color-accent)', r: 4, strokeWidth: 0 }} />
235
+ </AreaChart>
236
+ ```
237
+
238
+ - Always use a gradient fill (accent color fading to transparent).
239
+ - The gradient creates visual weight that says "this is growing."
240
+
241
+ ## Pie / donut chart
242
+
243
+ Use for: market share, budget allocation, composition at a point in time.
244
+
245
+ ```tsx
246
+ const COLORS = ['#f59e0b', 'rgba(245,158,11,0.6)', 'rgba(245,158,11,0.35)', 'rgba(255,255,255,0.15)']
247
+
248
+ <ResponsiveContainer width="100%" height={350}>
249
+ <PieChart>
250
+ <Pie data={data} dataKey="value" nameKey="name"
251
+ cx="50%" cy="50%" innerRadius={80} outerRadius={130}
252
+ paddingAngle={2} animationDuration={800}>
253
+ {data.map((_, i) => (
254
+ <Cell key={i} fill={COLORS[i % COLORS.length]} />
255
+ ))}
256
+ </Pie>
257
+ <Tooltip contentStyle={{ background: '#222228', border: '1px solid rgba(255,255,255,0.06)', borderRadius: 10 }} />
258
+ </PieChart>
259
+ </ResponsiveContainer>
260
+ ```
261
+
262
+ - Use donut (with `innerRadius`) rather than full pie. Donuts look more modern and leave space for a central label.
263
+ - Max 5-6 slices. Group small slices into "Other."
264
+ - `paddingAngle={2}` adds visual separation between slices.
265
+
266
+ ### Central label for donut
267
+
268
+ ```tsx
269
+ <text x="50%" y="48%" textAnchor="middle" dominantBaseline="middle"
270
+ fill="var(--color-text)" fontSize={28} fontWeight={700}>
271
+ 100%
272
+ </text>
273
+ <text x="50%" y="58%" textAnchor="middle" dominantBaseline="middle"
274
+ fill="rgba(255,255,255,0.4)" fontSize={12}>
275
+ Total allocation
276
+ </text>
277
+ ```
278
+
279
+ ## Radar / spider chart
280
+
281
+ Use for: multi-dimensional comparison, team assessment, product scoring.
282
+
283
+ ```tsx
284
+ <ResponsiveContainer width="100%" height={350}>
285
+ <RadarChart data={data}>
286
+ <PolarGrid stroke="rgba(255,255,255,0.08)" />
287
+ <PolarAngleAxis dataKey="axis"
288
+ tick={{ fill: 'rgba(255,255,255,0.5)', fontSize: 12 }} />
289
+ <Radar dataKey="score" stroke="var(--color-accent)" strokeWidth={2}
290
+ fill="var(--color-accent)" fillOpacity={0.15} animationDuration={800} />
291
+ </RadarChart>
292
+ </ResponsiveContainer>
293
+ ```
294
+
295
+ - 5-8 axes maximum. Fewer looks sparse. More creates visual noise.
296
+ - Use `fillOpacity={0.15}` for a subtle area fill.
297
+
298
+ ## Scatter / bubble chart
299
+
300
+ Use for: correlation analysis, competitive positioning, portfolio mapping.
301
+
302
+ ```tsx
303
+ <ResponsiveContainer width="100%" height={400}>
304
+ <ScatterChart>
305
+ <CartesianGrid strokeDasharray="3 3" stroke="rgba(255,255,255,0.04)" />
306
+ <XAxis dataKey="x" name="Revenue" stroke="transparent"
307
+ tick={{ fill: 'rgba(255,255,255,0.5)', fontSize: 12 }}
308
+ tickLine={false} axisLine={false} />
309
+ <YAxis dataKey="y" name="Growth" stroke="transparent"
310
+ tick={{ fill: 'rgba(255,255,255,0.35)', fontSize: 12 }}
311
+ tickLine={false} axisLine={false} />
312
+ <Scatter data={data} fill="var(--color-accent)" animationDuration={800}>
313
+ {data.map((entry, i) => (
314
+ <Cell key={i} r={entry.size || 8} />
315
+ ))}
316
+ </Scatter>
317
+ </ScatterChart>
318
+ </ResponsiveContainer>
319
+ ```
320
+
321
+ For bubble charts, vary the `r` (radius) prop on each `Cell` based on a third data dimension.
322
+
323
+ ## Combo chart (bar + line)
324
+
325
+ Use for: revenue bars with margin line, volume with average overlay.
326
+
327
+ ```tsx
328
+ <ResponsiveContainer width="100%" height={400}>
329
+ <ComposedChart data={data}>
330
+ <CartesianGrid strokeDasharray="3 3" stroke="rgba(255,255,255,0.04)" />
331
+ {/* ... axes */}
332
+ <Bar dataKey="revenue" fill="var(--color-accent)" radius={[6, 6, 0, 0]}
333
+ animationDuration={800} />
334
+ <Line type="monotone" dataKey="margin" stroke="rgba(255,255,255,0.6)"
335
+ strokeWidth={2} dot={{ r: 3, fill: 'rgba(255,255,255,0.6)' }}
336
+ strokeDasharray="5 5" />
337
+ </ComposedChart>
338
+ </ResponsiveContainer>
339
+ ```
340
+
341
+ - Bar is the primary metric (solid, accent color).
342
+ - Line is the secondary metric (dashed, muted color).
343
+ - Requires a second Y-axis if scales differ: `<YAxis yAxisId="right" orientation="right" />`.
344
+
345
+ ## Waterfall chart
346
+
347
+ Use for: revenue bridges, P&L walks, budget variance analysis.
348
+
349
+ Recharts does not have a native waterfall component. Build with calculated offsets:
350
+
351
+ ```tsx
352
+ const waterfallData = [
353
+ { name: 'Q4 Revenue', value: 3100, isTotal: false },
354
+ { name: 'New customers', value: 800, isTotal: false },
355
+ { name: 'Expansion', value: 450, isTotal: false },
356
+ { name: 'Churn', value: -350, isTotal: false },
357
+ { name: 'Q1 Revenue', value: 4000, isTotal: true },
358
+ ]
359
+
360
+ // Calculate offsets for stacking
361
+ const processedData = waterfallData.reduce((acc, item, i) => {
362
+ if (item.isTotal) {
363
+ acc.push({ ...item, offset: 0, fill: 'var(--color-accent)' })
364
+ } else if (i === 0) {
365
+ acc.push({ ...item, offset: 0, fill: 'var(--color-accent)' })
366
+ } else {
367
+ const prevTop = acc[i - 1].offset + Math.abs(acc[i - 1].value)
368
+ const offset = item.value >= 0 ? prevTop : prevTop - Math.abs(item.value)
369
+ acc.push({
370
+ ...item,
371
+ offset: item.value >= 0 ? prevTop : offset,
372
+ fill: item.value >= 0 ? '#22c55e' : '#ef4444',
373
+ })
374
+ }
375
+ return acc
376
+ }, [] as Array<typeof waterfallData[0] & { offset: number; fill: string }>)
377
+ ```
378
+
379
+ Use stacked bars: an invisible "offset" bar + the visible "value" bar:
380
+
381
+ ```tsx
382
+ <BarChart data={processedData}>
383
+ <Bar dataKey="offset" stackId="a" fill="transparent" />
384
+ <Bar dataKey="value" stackId="a" radius={[4, 4, 0, 0]}>
385
+ {processedData.map((entry, i) => (
386
+ <Cell key={i} fill={entry.fill} />
387
+ ))}
388
+ </Bar>
389
+ </BarChart>
390
+ ```
391
+
392
+ ## Funnel chart
393
+
394
+ Use for: sales pipeline, conversion rates, user activation funnel.
395
+
396
+ Recharts does not have a native funnel. Build with CSS trapezoids:
397
+
398
+ ```tsx
399
+ <div className="flex flex-col items-center gap-1" style={{ maxWidth: 500 }}>
400
+ {[
401
+ { label: 'Visitors', value: '10,000', width: '100%' },
402
+ { label: 'Signups', value: '2,400', width: '75%' },
403
+ { label: 'Activated', value: '1,100', width: '50%' },
404
+ { label: 'Paid', value: '420', width: '30%' },
405
+ ].map((stage, i) => (
406
+ <div key={stage.label} data-step="" className="step-fade text-center"
407
+ style={{ width: stage.width }}>
408
+ <div className="py-3 rounded-lg flex items-center justify-between px-6"
409
+ style={{
410
+ background: `rgba(245,158,11,${0.4 - i * 0.08})`,
411
+ border: '1px solid var(--color-accent)',
412
+ borderColor: `rgba(245,158,11,${0.6 - i * 0.1})`,
413
+ }}>
414
+ <span className="text-sm font-semibold">{stage.label}</span>
415
+ <span className="text-sm font-bold" style={{ color: 'var(--color-accent)' }}>{stage.value}</span>
416
+ </div>
417
+ </div>
418
+ ))}
419
+ </div>
420
+ ```
421
+
422
+ ## Gauge / radial progress
423
+
424
+ Use for: NPS scores, completion percentages, health indicators.
425
+
426
+ Build with custom SVG:
427
+
428
+ ```tsx
429
+ const GaugeChart: React.FC<{ value: number; max: number; label: string }> = ({ value, max, label }) => {
430
+ const pct = value / max
431
+ const circumference = Math.PI * 80 // half-circle, radius 80
432
+ const offset = circumference * (1 - pct)
433
+
434
+ return (
435
+ <svg width={200} height={120} viewBox="0 0 200 120">
436
+ {/* Background arc */}
437
+ <path d="M 20,100 A 80,80 0 0,1 180,100"
438
+ fill="none" stroke="rgba(255,255,255,0.08)" strokeWidth={12} strokeLinecap="round" />
439
+ {/* Value arc */}
440
+ <path d="M 20,100 A 80,80 0 0,1 180,100"
441
+ fill="none" stroke="var(--color-accent)" strokeWidth={12} strokeLinecap="round"
442
+ strokeDasharray={`${circumference}`}
443
+ strokeDashoffset={offset}
444
+ style={{ transition: 'stroke-dashoffset 800ms ease-out' }} />
445
+ {/* Value text */}
446
+ <text x="100" y="85" textAnchor="middle" fill="var(--color-text)"
447
+ fontSize={28} fontWeight={700}>{value}</text>
448
+ <text x="100" y="105" textAnchor="middle" fill="rgba(255,255,255,0.4)"
449
+ fontSize={11}>{label}</text>
450
+ </svg>
451
+ )
452
+ }
453
+ ```
454
+
455
+ ## KPI card with sparkline
456
+
457
+ Use for: dashboard slides where each metric needs a trend indicator.
458
+
459
+ ```tsx
460
+ <div className="card-surface p-5 flex items-end justify-between">
461
+ <div>
462
+ <p className="text-xs font-semibold tracking-[0.15em] uppercase"
463
+ style={{ color: 'var(--color-text-tertiary)' }}>Revenue</p>
464
+ <p className="text-3xl font-bold mt-2"
465
+ style={{ fontFamily: 'var(--font-heading)' }}>$4.2M</p>
466
+ <p className="text-sm mt-1" style={{ color: '#22c55e' }}>+142% YoY</p>
467
+ </div>
468
+ <ResponsiveContainer width={80} height={40}>
469
+ <LineChart data={sparkData}>
470
+ <Line type="monotone" dataKey="v" stroke="var(--color-accent)"
471
+ strokeWidth={1.5} dot={false} />
472
+ </LineChart>
473
+ </ResponsiveContainer>
474
+ </div>
475
+ ```
476
+
477
+ - Sparkline has no axes, no grid, no tooltip. Just the line.
478
+ - Width: 60-100px. Height: 30-50px.
479
+ - The sparkline shows direction, not values. The number beside it shows the value.
480
+
481
+ ## Chart selection guide
482
+
483
+ | Question to answer | Chart type | Why |
484
+ |---|---|---|
485
+ | How does X compare across categories? | Bar chart (vertical) | Direct comparison |
486
+ | How does X rank? | Bar chart (horizontal) | Long labels fit better |
487
+ | What is the trend over time? | Line chart | Shows direction and velocity |
488
+ | What is the volume over time? | Area chart | Emphasizes magnitude |
489
+ | What is the composition? | Pie/donut or stacked bar | Shows parts of a whole |
490
+ | How do two metrics correlate? | Scatter chart | Shows relationship |
491
+ | How does X score across dimensions? | Radar chart | Multi-axis comparison |
492
+ | What are the revenue drivers? | Waterfall chart | Shows additive/subtractive components |
493
+ | What is the conversion rate? | Funnel chart | Shows progressive narrowing |
494
+ | What is the health score? | Gauge chart | Single metric with context |
495
+ | What is the trend direction? | Sparkline (in KPI card) | Inline trend indicator |
496
+ | Bar + line overlay? | Combo chart | Two metrics, different scales |
497
+
498
+ ## Annotation patterns
499
+
500
+ ### Callout annotation
501
+
502
+ Add a text annotation next to a specific data point:
503
+
504
+ ```tsx
505
+ <text x={dataPointX} y={dataPointY - 15}
506
+ fill="var(--color-accent)" fontSize={12} fontWeight={600}
507
+ textAnchor="middle">Peak: $4.2M</text>
508
+ ```
509
+
510
+ ### Trend line / target line
511
+
512
+ Add a horizontal reference line:
513
+
514
+ ```tsx
515
+ import { ReferenceLine } from 'recharts'
516
+
517
+ <ReferenceLine y={3000} stroke="rgba(255,255,255,0.2)"
518
+ strokeDasharray="5 5" label={{
519
+ value: 'Target',
520
+ fill: 'rgba(255,255,255,0.3)',
521
+ fontSize: 11,
522
+ position: 'right',
523
+ }} />
524
+ ```
525
+
526
+ ## What to avoid
527
+
528
+ - More than one chart per slide (except dashboard slides).
529
+ - Pie charts for more than 6 categories.
530
+ - 3D effects on any chart. They distort data.
531
+ - Legend below the chart when labels on the chart itself would work.
532
+ - `height="100%"` on ResponsiveContainer. Use fixed pixel heights.
533
+ - Animating charts that are already visible. Only animate on reveal via `data-step`.
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: deck-templates
3
+ description: Narrative outlines and slide structures for common presentation types
4
+ ---
5
+
6
+ # Deck templates skill
7
+
8
+ Scaffolding outlines for common deck types. Use these as a starting structure and fill content with the user.
9
+
10
+ ## Investor pitch
11
+
12
+ 10-12 slides. 15-20 minutes. Every slide should advance the narrative toward the ask.
13
+
14
+ 1. **Title** -- company name, tagline, presenter name
15
+ 2. **Problem** -- the pain point, who feels it, how big it is
16
+ 3. **Solution** -- what you build, one sentence
17
+ 4. **Demo / product** -- screenshots or live product, keep it to 2-3 screens
18
+ 5. **Market size** -- TAM, SAM, SOM with sources
19
+ 6. **Traction** -- metrics that prove momentum (revenue, users, growth rate)
20
+ 7. **Business model** -- how you make money, pricing, unit economics
21
+ 8. **Competition** -- positioning matrix, why you win
22
+ 9. **Team** -- founders and key hires, relevant experience
23
+ 10. **Financials** -- projections, burn rate, runway
24
+ 11. **Ask** -- how much, what for, expected milestones
25
+ 12. **Contact** -- email, website, calendar link
26
+
27
+ ### Seed variant
28
+
29
+ Focus on vision and team. Less emphasis on financials (you probably don't have much data yet). Replace the financials slide with a "Why now" slide explaining market timing.
30
+
31
+ ### Series A variant
32
+
33
+ Focus on traction and unit economics. Add a slide after traction showing cohort analysis or retention curves. The financials slide should show a clear path to profitability or next fundraise.
34
+
35
+ ## Product launch
36
+
37
+ 6-8 slides. 10-15 minutes. Build to the "aha" moment, then make adoption easy.
38
+
39
+ 1. **Title** -- product name, launch date
40
+ 2. **Context** -- the world before this product, what's hard today
41
+ 3. **Problem** -- specific pain, with a story or data point
42
+ 4. **Solution** -- the product, what it does in one line
43
+ 5. **Demo** -- 3-5 screenshots or a video embed showing the flow
44
+ 6. **How it works** -- technical or conceptual overview, keep it simple
45
+ 7. **Adoption path** -- how to get started, pricing if applicable
46
+ 8. **Call to action** -- one clear next step
47
+
48
+ ## Internal metrics review
49
+
50
+ 5-7 slides. 10 minutes. Honest, data-driven, forward-looking.
51
+
52
+ 1. **Title** -- team name, review period, date
53
+ 2. **Context** -- what we set out to do this quarter
54
+ 3. **Key results** -- 3-5 metrics, actual vs. target, with trend
55
+ 4. **What worked** -- 2-3 wins with supporting data
56
+ 5. **What didn't** -- 2-3 misses, honest root causes
57
+ 6. **Learnings** -- what we'd do differently
58
+ 7. **Next quarter** -- goals and priorities
59
+
60
+ ## Conference talk
61
+
62
+ 8-15 slides. 20-30 minutes. Teach one thing well.
63
+
64
+ 1. **Title** -- talk title, speaker name, event name
65
+ 2. **Hook** -- a surprising fact, a question, or a demo that gets attention in the first 30 seconds
66
+ 3. **Thesis** -- the one thing the audience should remember
67
+ 4. **Argument 1** -- first supporting point with evidence
68
+ 5. **Argument 2** -- second supporting point with evidence
69
+ 6. **Argument 3** -- third supporting point with evidence
70
+ 7. **Demo** (optional) -- live demonstration that proves the thesis
71
+ 8. **Counterargument** -- acknowledge the strongest objection, address it
72
+ 9. **Takeaways** -- 3 bullet points the audience can act on Monday
73
+ 10. **Q&A / Contact** -- how to reach you, resources
74
+
75
+ ### Pacing notes
76
+
77
+ - Spend 60% of time on arguments 1-3
78
+ - Keep the demo under 5 minutes
79
+ - Leave 5 minutes for Q&A
80
+ - One slide per 2-3 minutes is a good cadence
81
+
82
+ ## Sales deck
83
+
84
+ 6-8 slides. 15-20 minutes. Customer-centric, not product-centric.
85
+
86
+ 1. **Title** -- your company, their company, date
87
+ 2. **Their problem** -- research their specific pain, show you understand
88
+ 3. **Proof points** -- logos, case studies, metrics from similar customers
89
+ 4. **Solution** -- how your product solves their specific problem
90
+ 5. **How it works** -- enough technical detail to build confidence, not so much it overwhelms
91
+ 6. **Pricing** -- transparent, with clear tiers
92
+ 7. **Next steps** -- specific actions and timeline
93
+ 8. **Appendix** -- detailed specs, security docs, compliance certs (don't present these, have them ready)