@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.
- package/dist/cli/commands/analytics.d.ts +6 -0
- package/dist/cli/commands/analytics.d.ts.map +1 -0
- package/dist/cli/commands/analytics.js +44 -0
- package/dist/cli/commands/analytics.js.map +1 -0
- package/dist/cli/commands/create.d.ts +4 -0
- package/dist/cli/commands/create.d.ts.map +1 -0
- package/dist/cli/commands/create.js +87 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/export.d.ts +6 -0
- package/dist/cli/commands/export.d.ts.map +1 -0
- package/dist/cli/commands/export.js +109 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +12 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/template-path.d.ts +4 -0
- package/dist/cli/template-path.d.ts.map +1 -0
- package/dist/cli/template-path.js +13 -0
- package/dist/cli/template-path.js.map +1 -0
- package/dist/runtime/export-api.d.ts +15 -0
- package/dist/runtime/export-api.d.ts.map +1 -0
- package/dist/runtime/export-api.js +21 -0
- package/dist/runtime/export-api.js.map +1 -0
- package/dist/runtime/index.d.ts +12 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +8 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/light-table.d.ts +8 -0
- package/dist/runtime/light-table.d.ts.map +1 -0
- package/dist/runtime/light-table.js +104 -0
- package/dist/runtime/light-table.js.map +1 -0
- package/dist/runtime/presenter-view.d.ts +7 -0
- package/dist/runtime/presenter-view.d.ts.map +1 -0
- package/dist/runtime/presenter-view.js +62 -0
- package/dist/runtime/presenter-view.js.map +1 -0
- package/dist/runtime/slide-context.d.ts +16 -0
- package/dist/runtime/slide-context.d.ts.map +1 -0
- package/dist/runtime/slide-context.js +18 -0
- package/dist/runtime/slide-context.js.map +1 -0
- package/dist/runtime/slide-controls.d.ts +3 -0
- package/dist/runtime/slide-controls.d.ts.map +1 -0
- package/dist/runtime/slide-controls.js +177 -0
- package/dist/runtime/slide-controls.js.map +1 -0
- package/dist/runtime/slide-dom.d.ts +17 -0
- package/dist/runtime/slide-dom.d.ts.map +1 -0
- package/dist/runtime/slide-dom.js +89 -0
- package/dist/runtime/slide-dom.js.map +1 -0
- package/dist/runtime/slide-runtime.d.ts +7 -0
- package/dist/runtime/slide-runtime.d.ts.map +1 -0
- package/dist/runtime/slide-runtime.js +125 -0
- package/dist/runtime/slide-runtime.js.map +1 -0
- package/dist/runtime/slide-shape.d.ts +21 -0
- package/dist/runtime/slide-shape.d.ts.map +1 -0
- package/dist/runtime/slide-shape.js +115 -0
- package/dist/runtime/slide-shape.js.map +1 -0
- package/dist/runtime/types.d.ts +150 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +38 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/runtime/use-presenter-mode.d.ts +14 -0
- package/dist/runtime/use-presenter-mode.d.ts.map +1 -0
- package/dist/runtime/use-presenter-mode.js +52 -0
- package/dist/runtime/use-presenter-mode.js.map +1 -0
- package/dist/runtime/use-slide-navigation.d.ts +13 -0
- package/dist/runtime/use-slide-navigation.d.ts.map +1 -0
- package/dist/runtime/use-slide-navigation.js +230 -0
- package/dist/runtime/use-slide-navigation.js.map +1 -0
- package/package.json +64 -0
- package/skills/accessibility/SKILL.md +236 -0
- package/skills/advanced-layouts/SKILL.md +429 -0
- package/skills/analytics/SKILL.md +97 -0
- package/skills/animation/SKILL.md +364 -0
- package/skills/brand/SKILL.md +200 -0
- package/skills/data-visualization/SKILL.md +533 -0
- package/skills/deck-templates/SKILL.md +93 -0
- package/skills/diagrams/SKILL.md +395 -0
- package/skills/export/SKILL.md +119 -0
- package/skills/interactive/SKILL.md +292 -0
- package/skills/layout/SKILL.md +178 -0
- package/skills/narrative-frameworks/SKILL.md +250 -0
- package/skills/react-component-embeds/SKILL.md +73 -0
- package/skills/slide-types/SKILL.md +384 -0
- package/skills/slidenerds-runtime/SKILL.md +163 -0
- package/skills/speaker-notes/SKILL.md +128 -0
- package/skills/strategic-frameworks/SKILL.md +392 -0
- package/skills/visual-design/SKILL.md +373 -0
- package/templates/analytics/custom.tsx.tmpl +20 -0
- package/templates/analytics/ga4.tsx.tmpl +15 -0
- package/templates/analytics/gtm.tsx.tmpl +9 -0
- package/templates/analytics/plausible.tsx.tmpl +10 -0
- package/templates/analytics/posthog.tsx.tmpl +14 -0
- package/templates/next-app/CLAUDE.md.tmpl +574 -0
- package/templates/next-app/README.md.tmpl +35 -0
- package/templates/next-app/app/globals.css.tmpl +274 -0
- package/templates/next-app/app/layout.tsx.tmpl +31 -0
- package/templates/next-app/app/page.tsx.tmpl +38 -0
- package/templates/next-app/brand.config.ts.tmpl +32 -0
- package/templates/next-app/package.json.tmpl +25 -0
- package/templates/next-app/postcss.config.mjs.tmpl +8 -0
- package/templates/next-app/tsconfig.json.tmpl +21 -0
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
# {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
A slidenerds presentation deck. Built with Next.js and `@strategicnerds/slide-nerds`.
|
|
4
|
+
|
|
5
|
+
## First steps when starting a new deck
|
|
6
|
+
|
|
7
|
+
1. **Ask what kind of presentation this is.** Use the `narrative-frameworks` skill to pick the right structure (SCQA for board decks, PAS for sales, Sparkline for keynotes, etc.).
|
|
8
|
+
2. **Set the brand.** Edit `brand.config.ts` with the user's colors, fonts, and spacing. Then update derived colors in `app/globals.css`. See the `brand` skill for the exact workflow.
|
|
9
|
+
3. **Build slides in `app/page.tsx`.** Each `<section data-slide="">` is one slide.
|
|
10
|
+
|
|
11
|
+
## Branding workflow
|
|
12
|
+
|
|
13
|
+
`brand.config.ts` is the single source of truth. The layout reads it and injects CSS custom properties on `<html>`. Change this file to rebrand the entire deck.
|
|
14
|
+
|
|
15
|
+
After editing `brand.config.ts`, update these derived CSS variables in `app/globals.css`:
|
|
16
|
+
|
|
17
|
+
```css
|
|
18
|
+
:root {
|
|
19
|
+
--color-accent-dim: rgba(R, G, B, 0.12); /* accent at 12% opacity */
|
|
20
|
+
--color-text-secondary: rgba(R, G, B, 0.6); /* text at 60% opacity */
|
|
21
|
+
--color-text-tertiary: rgba(R, G, B, 0.4); /* text at 40% opacity */
|
|
22
|
+
--color-border: rgba(255, 255, 255, 0.06); /* white at 6% for dark themes */
|
|
23
|
+
--color-surface-elevated: #222228; /* one step above surface */
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
If using custom web fonts, add `@import` rules at the top of `globals.css` before `@import 'tailwindcss'`.
|
|
28
|
+
|
|
29
|
+
Never hardcode hex colors in slide content. Always use `var(--color-accent)`, `var(--color-text)`, etc.
|
|
30
|
+
|
|
31
|
+
## File structure
|
|
32
|
+
|
|
33
|
+
| File | Purpose |
|
|
34
|
+
|------|---------|
|
|
35
|
+
| `brand.config.ts` | Colors, fonts, spacing. Single source of truth for brand. |
|
|
36
|
+
| `app/layout.tsx` | Root layout. Reads brand.config.ts and injects CSS variables. |
|
|
37
|
+
| `app/globals.css` | Structural CSS, animations, derived color tokens, font imports. |
|
|
38
|
+
| `app/page.tsx` | The slide deck. All slides live here. |
|
|
39
|
+
|
|
40
|
+
## Data conventions
|
|
41
|
+
|
|
42
|
+
| Attribute | Purpose |
|
|
43
|
+
|-----------|---------|
|
|
44
|
+
| `data-slide` | Marks a `<section>` as a slide |
|
|
45
|
+
| `data-step` | Progressive reveal. Hidden until the presenter advances. |
|
|
46
|
+
| `data-notes` | Speaker notes. Hidden in presentation, shown in Speaker Notes window. |
|
|
47
|
+
| `data-magic-id` | Shared identity for Magic Move animation between consecutive slides. |
|
|
48
|
+
|
|
49
|
+
## Keyboard controls
|
|
50
|
+
|
|
51
|
+
| Key | Action |
|
|
52
|
+
|-----|--------|
|
|
53
|
+
| Space / Right arrow | Next step or slide |
|
|
54
|
+
| Left arrow / Backspace | Previous step or slide |
|
|
55
|
+
| P | Speaker Notes (opens new window with notes, timer, slide count) |
|
|
56
|
+
| L | Light Table (thumbnail overview of all slides) |
|
|
57
|
+
| F | Fullscreen |
|
|
58
|
+
| Escape | Exit Light Table or fullscreen |
|
|
59
|
+
|
|
60
|
+
## Animation classes
|
|
61
|
+
|
|
62
|
+
### Step animations (click-to-reveal)
|
|
63
|
+
|
|
64
|
+
Add these to `data-step` or `data-auto-step` elements. Runtime adds `step-visible` on click (or auto-timer).
|
|
65
|
+
|
|
66
|
+
| Class | Effect |
|
|
67
|
+
|-------|--------|
|
|
68
|
+
| `step-fade` | Fade in (350ms) |
|
|
69
|
+
| `step-move-up` | Slide up + fade in (420ms) |
|
|
70
|
+
| `step-scale-in` | Scale up + fade in (350ms) |
|
|
71
|
+
| `step-pop` | Scale up with overshoot bounce (400ms) |
|
|
72
|
+
| `step-wipe-right` | Clip-path reveal left to right (500ms) |
|
|
73
|
+
| `step-emphasis` | Spring-scale entrance for big stats (500ms) |
|
|
74
|
+
|
|
75
|
+
### Auto-build animations (trigger on slide load)
|
|
76
|
+
|
|
77
|
+
Add these classes directly to elements (no `data-step` needed). They animate when the slide becomes active. Use `style={{ animationDelay: '200ms' }}` for staggered entrances.
|
|
78
|
+
|
|
79
|
+
| Class | Effect |
|
|
80
|
+
|-------|--------|
|
|
81
|
+
| `auto-fade` | Fade in (350ms) |
|
|
82
|
+
| `auto-pop` | Scale up with overshoot bounce (400ms) |
|
|
83
|
+
| `auto-wipe-right` | Clip-path reveal left to right (500ms) |
|
|
84
|
+
| `auto-slide-down` | Slide down from above + fade (500ms) |
|
|
85
|
+
| `auto-slide-up` | Slide up from below + fade (500ms) |
|
|
86
|
+
|
|
87
|
+
### Exit animations (trigger when leaving a slide)
|
|
88
|
+
|
|
89
|
+
Add these classes to elements that should animate out when navigating away. The runtime adds `.exiting` to the slide and waits 400ms before transitioning.
|
|
90
|
+
|
|
91
|
+
| Class | Effect |
|
|
92
|
+
|-------|--------|
|
|
93
|
+
| `exit-fade` | Fade out (400ms) |
|
|
94
|
+
| `exit-scale-out` | Scale down + fade out (400ms) |
|
|
95
|
+
| `exit-slide-up` | Slide up + fade out (400ms) |
|
|
96
|
+
| `exit-slide-down` | Slide down + fade out (400ms) |
|
|
97
|
+
| `exit-wipe-left` | Clip-path collapse right to left (400ms) |
|
|
98
|
+
|
|
99
|
+
For sequenced exits, use `data-exit-step` on elements. The runtime reveals exit steps one per click after all entrance steps are done, then transitions to the next slide.
|
|
100
|
+
|
|
101
|
+
### Auto-step sequencing
|
|
102
|
+
|
|
103
|
+
Use `data-auto-step="300ms"` instead of `data-step` for steps that should reveal automatically on a timer. Mix with `data-step` for hybrid sequences: auto-steps play first, then manual steps wait for clicks.
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
<div data-auto-step="200ms" className="step-fade">Auto-reveals after 200ms</div>
|
|
107
|
+
<div data-auto-step="300ms" className="step-fade">Auto-reveals after 300ms more</div>
|
|
108
|
+
<div data-step="" className="step-fade">Waits for click</div>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Step groups
|
|
112
|
+
|
|
113
|
+
Use `data-step-group="name"` on consecutive `data-step` elements to reveal them all with a single click. Control stagger with `animationDelay`:
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
<div data-step="" data-step-group="row1" className="step-fade" style={{ animationDelay: '0ms' }}>A</div>
|
|
117
|
+
<div data-step="" data-step-group="row1" className="step-fade" style={{ animationDelay: '100ms' }}>B</div>
|
|
118
|
+
<div data-step="" data-step-group="row1" className="step-fade" style={{ animationDelay: '200ms' }}>C</div>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
One click reveals A, B, and C together with staggered timing.
|
|
122
|
+
|
|
123
|
+
## Shape system
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
import { SlideShape } from '@strategicnerds/slide-nerds'
|
|
127
|
+
|
|
128
|
+
<SlideShape shape="hexagon" size={100}
|
|
129
|
+
fill="var(--color-surface)" stroke="var(--color-accent)" strokeWidth={1.5}>
|
|
130
|
+
<p>Text inside</p>
|
|
131
|
+
</SlideShape>
|
|
132
|
+
|
|
133
|
+
<SlideShape shape="circle" size={140}
|
|
134
|
+
imageSrc="/photo.jpg" stroke="var(--color-accent)" strokeWidth={2} />
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Available shapes: `circle`, `square`, `rounded-square`, `triangle`, `diamond`, `pentagon`, `hexagon`, `octagon`, `star`, `plus`, `cloud`, `arrow-right`, `arrow-left`, `chevron-right`, `pill`.
|
|
138
|
+
|
|
139
|
+
## Skills reference
|
|
140
|
+
|
|
141
|
+
Skills are installed in `.slidenerds/skills/`. Each skill is a directory containing a `SKILL.md` file. Read the relevant skills before building slides.
|
|
142
|
+
|
|
143
|
+
### Structure and narrative
|
|
144
|
+
- **narrative-frameworks**: SCQA, Minto Pyramid, PAS, BAB, Sparkline, Monroe's. Pick one per deck.
|
|
145
|
+
- **deck-templates**: Complete slide sequences for investor pitch, product launch, board deck, sales deck, conference talk.
|
|
146
|
+
|
|
147
|
+
### Visual design
|
|
148
|
+
- **visual-design**: Typography scale, spacing hierarchy, composition rules, content density limits.
|
|
149
|
+
- **brand**: How to edit brand.config.ts and globals.css. Palette derivation, font pairing, rebranding checklist.
|
|
150
|
+
- **layout**: Basic alignment, grids, centering, two-up, hero+body.
|
|
151
|
+
- **advanced-layouts**: Dashboard (KPI grid), pricing comparison, before/after, icon grid, logo wall, agenda, appendix.
|
|
152
|
+
|
|
153
|
+
### Content types
|
|
154
|
+
- **slide-types**: Title, big stat, quote, code, table, chart, team, timeline, image, two-up.
|
|
155
|
+
- **data-visualization**: 13 chart types with Recharts. Bar, line, area, pie, radar, waterfall, funnel, gauge, sparkline, combo.
|
|
156
|
+
- **strategic-frameworks**: SWOT, 2x2 matrix, TAM/SAM/SOM, process chevrons, pyramid, risk matrix, maturity model.
|
|
157
|
+
- **diagrams**: Flowcharts, org charts, sequence diagrams, journey maps, mind maps, state diagrams, Venn, swim lanes.
|
|
158
|
+
|
|
159
|
+
### Animation and interaction
|
|
160
|
+
- **animation**: Step reveals, Magic Move, transition overlays, emphasis pulse.
|
|
161
|
+
- **interactive**: Video embeds, QR codes, clickable links, iframe embeds, click-to-zoom.
|
|
162
|
+
|
|
163
|
+
### Quality
|
|
164
|
+
- **accessibility**: WCAG contrast, prefers-reduced-motion, screen reader support, color-blind safe palettes.
|
|
165
|
+
- **speaker-notes**: How to write and place speaker notes.
|
|
166
|
+
|
|
167
|
+
### Output
|
|
168
|
+
- **analytics**: GTM, GA4, PostHog, Plausible integration.
|
|
169
|
+
- **export**: PDF, PPTX, Google Slides export.
|
|
170
|
+
|
|
171
|
+
## Slide authoring reference
|
|
172
|
+
|
|
173
|
+
Everything that can go inside a slide lives within a `<section data-slide="">` element in `app/page.tsx`. This is the complete reference.
|
|
174
|
+
|
|
175
|
+
### Critical layout rule
|
|
176
|
+
|
|
177
|
+
**The default layout for every content slide is top-left anchored.** Title and content start from a consistent position near the top of the slide and flow downward. Content is NOT vertically centered.
|
|
178
|
+
|
|
179
|
+
Only these specific slide types use centered layout:
|
|
180
|
+
- Big stat (single number, centered)
|
|
181
|
+
- Section divider (section name, centered)
|
|
182
|
+
- Quote (blockquote, centered, max-w-3xl)
|
|
183
|
+
- Closing (contact info, centered)
|
|
184
|
+
|
|
185
|
+
Everything else -- charts, tables, text slides, timelines, dashboards, diagrams, team slides, process flows, comparisons -- anchors content to the top-left with the title at a consistent position across all slides.
|
|
186
|
+
|
|
187
|
+
### Default slide structure (top-left anchored)
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
<section data-slide="">
|
|
191
|
+
<div className="bg-mesh-warm flex flex-col w-full"
|
|
192
|
+
style={{ padding: '4rem 6rem' }}>
|
|
193
|
+
|
|
194
|
+
{/* Section label -- same position on every content slide */}
|
|
195
|
+
<p className="section-label mb-3">Revenue</p>
|
|
196
|
+
|
|
197
|
+
{/* Title -- same Y position on every content slide */}
|
|
198
|
+
<h2 className="text-[2.5rem] font-bold mb-10">ARR trajectory</h2>
|
|
199
|
+
|
|
200
|
+
{/* Content flows below the title */}
|
|
201
|
+
<div data-step="" className="step-fade">
|
|
202
|
+
{/* Charts, tables, text, shapes, diagrams -- whatever the slide needs */}
|
|
203
|
+
</div>
|
|
204
|
+
|
|
205
|
+
{/* Annotation below the content */}
|
|
206
|
+
<div data-step="" className="step-move-up mt-5 flex items-center gap-3">
|
|
207
|
+
<div className="w-1.5 h-1.5 rounded-full" style={{ background: 'var(--color-accent)' }} />
|
|
208
|
+
<p className="text-base" style={{ color: 'var(--color-text-secondary)' }}>
|
|
209
|
+
Key insight or annotation about the content above.
|
|
210
|
+
</p>
|
|
211
|
+
</div>
|
|
212
|
+
|
|
213
|
+
<div data-notes="">Speaker notes here.</div>
|
|
214
|
+
</div>
|
|
215
|
+
</section>
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
The section-label, title, and content start from the same top-left position on every content slide. This consistency is what makes a deck feel designed rather than assembled.
|
|
219
|
+
|
|
220
|
+
### Data attributes
|
|
221
|
+
|
|
222
|
+
| Attribute | Element | Purpose |
|
|
223
|
+
|-----------|---------|---------|
|
|
224
|
+
| `data-slide=""` | `<section>` | Marks the element as a slide. Required. |
|
|
225
|
+
| `data-step=""` | Any element | Hides the element until the presenter advances. Revealed in DOM order. |
|
|
226
|
+
| `data-notes=""` | `<div>` | Speaker notes. Hidden during presentation, visible in Speaker Notes window (press P). Place inside the slide section. |
|
|
227
|
+
| `data-magic-id="name"` | Any element | Pairs elements across consecutive slides for FLIP animation. Elements with the same `data-magic-id` on adjacent slides animate position, size, and scale when transitioning. |
|
|
228
|
+
|
|
229
|
+
### CSS variables (from brand.config.ts)
|
|
230
|
+
|
|
231
|
+
These are injected on `<html>` by the layout and available everywhere:
|
|
232
|
+
|
|
233
|
+
| Variable | Source | Usage |
|
|
234
|
+
|----------|--------|-------|
|
|
235
|
+
| `--color-primary` | `brand.colors.primary` | Section divider backgrounds, darkest surfaces |
|
|
236
|
+
| `--color-accent` | `brand.colors.accent` | Highlights, stats, labels, shape strokes, chart fills, active states |
|
|
237
|
+
| `--color-background` | `brand.colors.background` | Slide canvas background |
|
|
238
|
+
| `--color-surface` | `brand.colors.surface` | Card backgrounds (charts, tables, code) |
|
|
239
|
+
| `--color-text` | `brand.colors.text` | Primary text color |
|
|
240
|
+
| `--slide-padding` | `brand.spacing.slide` | Outer slide padding |
|
|
241
|
+
| `--font-heading` | `brand.fonts.heading` | Heading font stack |
|
|
242
|
+
| `--font-body` | `brand.fonts.body` | Body text font stack |
|
|
243
|
+
| `--font-mono` | `brand.fonts.mono` | Monospace font stack |
|
|
244
|
+
|
|
245
|
+
Derived variables (set in `globals.css`):
|
|
246
|
+
|
|
247
|
+
| Variable | Value | Usage |
|
|
248
|
+
|----------|-------|-------|
|
|
249
|
+
| `--color-accent-dim` | Accent at 12% opacity | Pill backgrounds, badges, shape fills |
|
|
250
|
+
| `--color-text-secondary` | Text at 60% opacity | Body text, descriptions, labels |
|
|
251
|
+
| `--color-text-tertiary` | Text at 40% opacity | Captions, metadata, timestamps |
|
|
252
|
+
| `--color-border` | White at 6% opacity | Card borders, dividers, table rules |
|
|
253
|
+
| `--color-surface-elevated` | One step above surface | Table headers, elevated cards |
|
|
254
|
+
|
|
255
|
+
### Animation classes
|
|
256
|
+
|
|
257
|
+
Add to any `data-step` element. The runtime adds `step-visible` class when the step is active.
|
|
258
|
+
|
|
259
|
+
| Class | Effect | Duration |
|
|
260
|
+
|-------|--------|----------|
|
|
261
|
+
| `step-fade` | Opacity 0 to 1 | 350ms |
|
|
262
|
+
| `step-move-up` | Translate Y 24px to 0 + fade | 420ms |
|
|
263
|
+
| `step-scale-in` | Scale 0.92 to 1 + fade | 350ms |
|
|
264
|
+
| `step-emphasis` | Spring scale 0.82 to 1.02 to 1 | 500ms |
|
|
265
|
+
|
|
266
|
+
Example:
|
|
267
|
+
|
|
268
|
+
```tsx
|
|
269
|
+
<div data-step="" className="step-move-up">
|
|
270
|
+
<p>This slides up and fades in when the presenter advances.</p>
|
|
271
|
+
</div>
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Utility CSS classes
|
|
275
|
+
|
|
276
|
+
These are defined in `globals.css` and available on any slide:
|
|
277
|
+
|
|
278
|
+
| Class | What it does |
|
|
279
|
+
|-------|-------------|
|
|
280
|
+
| `section-label` | Small uppercase text in accent color with wide tracking. Use for section labels above titles. |
|
|
281
|
+
| `card-surface` | Rounded container with surface background and subtle border. Use around charts, tables, code. |
|
|
282
|
+
| `accent-line` | 40x3px accent-colored line. Use as a decorative divider. |
|
|
283
|
+
| `stat-glow` | Text shadow glow in accent color. Use on large stat numbers. |
|
|
284
|
+
| `bg-mesh-warm` | Subtle warm radial gradient background. Use on content slides. |
|
|
285
|
+
| `bg-mesh-cool` | Subtle cool radial gradient background. Alternate with warm for variety. |
|
|
286
|
+
| `bg-section` | Linear gradient from primary to surface. Use on section divider slides. |
|
|
287
|
+
| `slide-table` | Table styling with uppercase headers, accent highlights, and border rules. |
|
|
288
|
+
| `timeline-track` | Horizontal 2px line for timeline slides. |
|
|
289
|
+
| `timeline-dot` | 16px accent circle with glow for timeline nodes. |
|
|
290
|
+
| `timeline-dot-future` | Muted version of timeline-dot for future milestones. |
|
|
291
|
+
| `sr-only` | Visually hidden but screen-reader accessible. Use for chart data tables. |
|
|
292
|
+
|
|
293
|
+
### Components from @strategicnerds/slide-nerds
|
|
294
|
+
|
|
295
|
+
```tsx
|
|
296
|
+
import { SlideRuntime, SlideShape, SlideControls, PresenterView, LightTable, useSlideState } from '@strategicnerds/slide-nerds'
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**SlideRuntime** -- wraps the entire app in `layout.tsx`. Provides navigation, keyboard controls, and context.
|
|
300
|
+
|
|
301
|
+
**SlideShape** -- SVG shape with text or image content:
|
|
302
|
+
|
|
303
|
+
```tsx
|
|
304
|
+
// Shape with text inside
|
|
305
|
+
<SlideShape shape="hexagon" size={100}
|
|
306
|
+
fill="var(--color-surface)" stroke="var(--color-accent)" strokeWidth={1.5}>
|
|
307
|
+
<p className="text-lg font-bold">42</p>
|
|
308
|
+
</SlideShape>
|
|
309
|
+
|
|
310
|
+
// Shape with image mask
|
|
311
|
+
<SlideShape shape="circle" size={140}
|
|
312
|
+
imageSrc="/photo.jpg" stroke="var(--color-accent)" strokeWidth={2} />
|
|
313
|
+
|
|
314
|
+
// Shape with custom dimensions
|
|
315
|
+
<SlideShape shape="pill" width={200} height={48}
|
|
316
|
+
fill="var(--color-accent-dim)" stroke="none">
|
|
317
|
+
<p className="text-sm">Label</p>
|
|
318
|
+
</SlideShape>
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Props:
|
|
322
|
+
|
|
323
|
+
| Prop | Type | Default | Description |
|
|
324
|
+
|------|------|---------|-------------|
|
|
325
|
+
| `shape` | ShapeType | required | One of 15 shape types (see list below) |
|
|
326
|
+
| `size` | number | 120 | Width and height (square). Overridden by width/height. |
|
|
327
|
+
| `width` | number | size | Width in pixels |
|
|
328
|
+
| `height` | number | size | Height in pixels |
|
|
329
|
+
| `fill` | string | `var(--color-surface)` | Fill color (CSS value) |
|
|
330
|
+
| `stroke` | string | `var(--color-border)` | Stroke color (CSS value or "none") |
|
|
331
|
+
| `strokeWidth` | number | 1 | Stroke width in pixels |
|
|
332
|
+
| `opacity` | number | undefined | Overall opacity |
|
|
333
|
+
| `imageSrc` | string | undefined | Image URL. Clips image to shape via SVG clipPath. |
|
|
334
|
+
| `children` | ReactNode | undefined | Content rendered centered inside the shape. |
|
|
335
|
+
| `data-magic-id` | string | undefined | For Magic Move transitions. |
|
|
336
|
+
| `data-step` | string | undefined | For progressive reveal. |
|
|
337
|
+
| `className` | string | undefined | Additional CSS classes. |
|
|
338
|
+
|
|
339
|
+
Shape types: `circle`, `square`, `rounded-square`, `triangle`, `diamond`, `pentagon`, `hexagon`, `octagon`, `star`, `plus`, `cloud`, `arrow-right`, `arrow-left`, `chevron-right`, `pill`.
|
|
340
|
+
|
|
341
|
+
**useSlideState** -- React hook for reading slide context:
|
|
342
|
+
|
|
343
|
+
```tsx
|
|
344
|
+
const { currentSlide, currentStep, totalSlides, goToSlide, nextStep, previousStep, isLightTable, toggleLightTable } = useSlideState()
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Content types you can put on a slide
|
|
348
|
+
|
|
349
|
+
**Text**: headings (h1-h3), paragraphs, lists, blockquotes. Use Tailwind classes for sizing and the font CSS variables for families.
|
|
350
|
+
|
|
351
|
+
**Images**: `<img>` tags. Use `object-cover` for full-bleed, `object-contain` for screenshots. Always include `alt` text.
|
|
352
|
+
|
|
353
|
+
**Charts** (Recharts): Bar, line, area, pie/donut, radar, scatter, combo, treemap. Wrap in a `card-surface` container with `ResponsiveContainer` at a fixed pixel height (300-420px). See the `data-visualization` skill.
|
|
354
|
+
|
|
355
|
+
```tsx
|
|
356
|
+
import { BarChart, Bar, XAxis, YAxis, ResponsiveContainer } from 'recharts'
|
|
357
|
+
|
|
358
|
+
<div className="card-surface p-8">
|
|
359
|
+
<ResponsiveContainer width="100%" height={400}>
|
|
360
|
+
<BarChart data={data}>
|
|
361
|
+
<XAxis dataKey="name" stroke="transparent"
|
|
362
|
+
tick={{ fill: 'rgba(255,255,255,0.5)', fontSize: 13 }}
|
|
363
|
+
tickLine={false} axisLine={false} />
|
|
364
|
+
<YAxis stroke="transparent"
|
|
365
|
+
tick={{ fill: 'rgba(255,255,255,0.35)', fontSize: 12 }}
|
|
366
|
+
tickLine={false} axisLine={false} />
|
|
367
|
+
<Bar dataKey="value" fill="var(--color-accent)"
|
|
368
|
+
radius={[6, 6, 0, 0]} animationDuration={800} />
|
|
369
|
+
</BarChart>
|
|
370
|
+
</ResponsiveContainer>
|
|
371
|
+
</div>
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
**Shapes** (SlideShape): Any of the 18 SVG shapes with optional text, images, or Magic Move. See above.
|
|
375
|
+
|
|
376
|
+
**Tables**: HTML `<table>` with the `slide-table` class on the wrapper. Reveal rows one at a time with `data-step`.
|
|
377
|
+
|
|
378
|
+
```tsx
|
|
379
|
+
<div className="card-surface overflow-hidden">
|
|
380
|
+
<table className="slide-table w-full text-left">
|
|
381
|
+
<thead>
|
|
382
|
+
<tr style={{ background: 'var(--color-surface-elevated)' }}>
|
|
383
|
+
<th>Feature</th><th>Us</th><th>Them</th>
|
|
384
|
+
</tr>
|
|
385
|
+
</thead>
|
|
386
|
+
<tbody>
|
|
387
|
+
<tr data-step="" className="step-fade">
|
|
388
|
+
<td>Speed</td>
|
|
389
|
+
<td style={{ color: 'var(--color-accent)' }}>Fast</td>
|
|
390
|
+
<td style={{ color: 'var(--color-text-tertiary)' }}>Slow</td>
|
|
391
|
+
</tr>
|
|
392
|
+
</tbody>
|
|
393
|
+
</table>
|
|
394
|
+
</div>
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
**Diagrams** (Mermaid): Flowcharts, sequence diagrams, journey maps, mind maps, state diagrams, C4 architecture. Requires installing `mermaid` and `dompurify`. See the `diagrams` skill.
|
|
398
|
+
|
|
399
|
+
**Video**: YouTube/Vimeo iframes or `<video>` elements. Wrap in `card-surface` with 16:9 aspect ratio. See the `interactive` skill.
|
|
400
|
+
|
|
401
|
+
**QR codes**: Using `qrcode.react`. Place on the right side of the slide with the URL in plain text beside it. See the `interactive` skill.
|
|
402
|
+
|
|
403
|
+
**Links**: Styled as pill buttons with an external-link icon. Use `target="_blank"` and `rel="noopener noreferrer"`.
|
|
404
|
+
|
|
405
|
+
**Strategic frameworks**: SWOT matrices, 2x2 grids, TAM/SAM/SOM circles, process chevrons, pyramids, risk matrices. All built with HTML/CSS. See the `strategic-frameworks` skill.
|
|
406
|
+
|
|
407
|
+
**Custom SVG**: Venn diagrams, gauge charts, cycle diagrams, any visualization Recharts or Mermaid does not cover.
|
|
408
|
+
|
|
409
|
+
### Slide layout patterns
|
|
410
|
+
|
|
411
|
+
Every slide is a `<section data-slide="">` containing a single `<div>` that controls the layout. The CSS rule `[data-slide] > * { min-height: 100%; width: 100%; }` ensures the inner div always fills the slide.
|
|
412
|
+
|
|
413
|
+
**Top-left anchored with text content** (DEFAULT for: bullet lists, numbered lists, text paragraphs, tables):
|
|
414
|
+
|
|
415
|
+
```tsx
|
|
416
|
+
<section data-slide="">
|
|
417
|
+
<div className="bg-mesh-cool flex flex-col w-full"
|
|
418
|
+
style={{ padding: '4rem 6rem' }}>
|
|
419
|
+
<p className="section-label mb-3">Section name</p>
|
|
420
|
+
<h2 className="text-[2.5rem] font-bold mb-10">Slide title</h2>
|
|
421
|
+
{/* Text content anchored below the title, flows downward */}
|
|
422
|
+
<ul className="space-y-4 text-lg">
|
|
423
|
+
<li data-step="" className="step-fade">First point</li>
|
|
424
|
+
<li data-step="" className="step-fade">Second point</li>
|
|
425
|
+
</ul>
|
|
426
|
+
</div>
|
|
427
|
+
</section>
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Text, bullets, and tables stay anchored below the title. The bottom of the slide is breathing room. Do NOT vertically center text content.
|
|
431
|
+
|
|
432
|
+
**Top-left title with centered visual** (for: diagrams, charts, process flows, shapes, frameworks, team grids, icon grids, timelines, dashboards/KPIs):
|
|
433
|
+
|
|
434
|
+
```tsx
|
|
435
|
+
<section data-slide="">
|
|
436
|
+
<div className="flex flex-col w-full"
|
|
437
|
+
style={{ padding: '4rem 6rem' }}>
|
|
438
|
+
<p className="section-label mb-3">Section name</p>
|
|
439
|
+
<h2 className="text-[2.5rem] font-bold mb-8">Slide title</h2>
|
|
440
|
+
{/* Visual content centered in the remaining space below the title */}
|
|
441
|
+
<div className="flex-1 flex items-center justify-center">
|
|
442
|
+
{/* Diagram, chart, shape layout, framework, etc. */}
|
|
443
|
+
</div>
|
|
444
|
+
</div>
|
|
445
|
+
</section>
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
The title stays top-left anchored. The visual fills and centers within the remaining space below it. Use `flex-1 flex items-center justify-center` on the visual container.
|
|
449
|
+
|
|
450
|
+
**Centered** (for: big stat, section divider, quote, closing, or any slide with a small centered cluster of content like badges, KPI grids, or short bullet lists):
|
|
451
|
+
|
|
452
|
+
```tsx
|
|
453
|
+
<section data-slide="">
|
|
454
|
+
<div className="flex flex-col items-center justify-center w-full"
|
|
455
|
+
style={{ paddingBottom: '4rem' }}>
|
|
456
|
+
{/* Content is centered horizontally and vertically */}
|
|
457
|
+
</div>
|
|
458
|
+
</section>
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
**Bottom-aligned** (ONLY for: title slide):
|
|
462
|
+
|
|
463
|
+
```tsx
|
|
464
|
+
<section data-slide="">
|
|
465
|
+
<div className="flex flex-col justify-end w-full"
|
|
466
|
+
style={{ padding: '5rem 5.5rem' }}>
|
|
467
|
+
{/* Content anchored to the bottom-left */}
|
|
468
|
+
</div>
|
|
469
|
+
</section>
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
**Two-column split** (before/after, quote + data):
|
|
473
|
+
|
|
474
|
+
```tsx
|
|
475
|
+
<section data-slide="">
|
|
476
|
+
<div className="grid grid-cols-2 w-full">
|
|
477
|
+
<div style={{ padding: '4rem' }}>{/* Left column */}</div>
|
|
478
|
+
<div style={{ padding: '4rem' }}>{/* Right column */}</div>
|
|
479
|
+
</div>
|
|
480
|
+
</section>
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
For mirrored comparison splits (e.g., "old vs new", "DIY vs product"), right-align the left column and left-align the right column so content faces the center divide. Use fixed-height containers for headers (`flex items-end`, same height on both sides) and fixed-height rows for bullets so content aligns horizontally across the split.
|
|
484
|
+
|
|
485
|
+
**Asymmetric split** (text + visual, 5:7 ratio):
|
|
486
|
+
|
|
487
|
+
```tsx
|
|
488
|
+
<section data-slide="">
|
|
489
|
+
<div className="grid grid-cols-12 gap-8 items-center w-full"
|
|
490
|
+
style={{ padding: '4rem 6rem' }}>
|
|
491
|
+
<div className="col-span-5">{/* Text */}</div>
|
|
492
|
+
<div className="col-span-7">{/* Visual */}</div>
|
|
493
|
+
</div>
|
|
494
|
+
</section>
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
### Magic Move between slides
|
|
498
|
+
|
|
499
|
+
Give elements the same `data-magic-id` on two consecutive slides. When navigating between them, the runtime captures positions and animates the transition using FLIP.
|
|
500
|
+
|
|
501
|
+
```tsx
|
|
502
|
+
{/* Slide A: metrics are large and centered */}
|
|
503
|
+
<section data-slide="">
|
|
504
|
+
<div data-magic-id="revenue" className="text-6xl font-bold">$4.2M</div>
|
|
505
|
+
<div data-magic-id="growth" className="text-6xl font-bold">142%</div>
|
|
506
|
+
</section>
|
|
507
|
+
|
|
508
|
+
{/* Slide B: same metrics are small and top-left, chart appears below */}
|
|
509
|
+
<section data-slide="">
|
|
510
|
+
<div data-magic-id="revenue" className="text-xl font-bold">$4.2M</div>
|
|
511
|
+
<div data-magic-id="growth" className="text-xl font-bold">142%</div>
|
|
512
|
+
<div data-step="" className="step-fade">
|
|
513
|
+
{/* New content that appears after the move */}
|
|
514
|
+
</div>
|
|
515
|
+
</section>
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
### Slide type recipes
|
|
519
|
+
|
|
520
|
+
| Type | Layout | Key elements |
|
|
521
|
+
|------|--------|-------------|
|
|
522
|
+
| Title | **Bottom-left** | accent-line, h1, subtitle, metadata row. Top 55% is empty. |
|
|
523
|
+
| Section divider | **Centered** | Section number label, h2. bg-section background. |
|
|
524
|
+
| Big stat | **Centered** | Large number with stat-glow, label, delta badge. |
|
|
525
|
+
| Text / bullet list | **Top-left text** | section-label, h2, bullets anchored below title. |
|
|
526
|
+
| Comparison table | **Top-left text** | section-label, h2, card-surface with slide-table. |
|
|
527
|
+
| Chart | **Top-left + centered visual** | section-label, h2 anchored top-left. Chart centered in remaining space. |
|
|
528
|
+
| Diagram | **Top-left + centered visual** | section-label, h2 anchored top-left. Diagram centered below. |
|
|
529
|
+
| Process flow | **Top-left + centered visual** | section-label, h2. Shapes centered in remaining space. |
|
|
530
|
+
| Team | **Top-left + centered visual** | section-label, h2. Avatar grid centered below. |
|
|
531
|
+
| Icon grid | **Top-left + centered visual** | section-label, h2. 3x2 grid centered below. |
|
|
532
|
+
| Dashboard | **Top-left + centered visual** | section-label, h2. KPI grid centered in remaining space. |
|
|
533
|
+
| Timeline | **Top-left + centered visual** | section-label, h2. Timeline track centered in remaining space. |
|
|
534
|
+
| Before/after | **Split** | grid-cols-2 with different backgrounds per side. |
|
|
535
|
+
| Quote | **Centered** | Open-quote glyph, blockquote (max-w-3xl), attribution. |
|
|
536
|
+
| Closing | **Centered** | accent-line, h2, contact info. |
|
|
537
|
+
| Case study grid | **Top-left + centered visual** | 3x2 or 3x3 grid of cards. Each card: company logo (light variant), key stat in accent, label, description. Top row `auto-slide-down`, bottom row `auto-slide-up`. |
|
|
538
|
+
|
|
539
|
+
**Two layout sub-types for top-left anchored slides:**
|
|
540
|
+
- **Top-left text**: Text, bullets, tables, KPIs stay anchored directly below the title. No vertical centering.
|
|
541
|
+
- **Top-left + centered visual**: Title stays top-left. The visual (chart, diagram, shapes) is centered both horizontally and vertically in the remaining space below the title using `flex-1 flex items-center justify-center`.
|
|
542
|
+
|
|
543
|
+
## Brand logo watermark
|
|
544
|
+
|
|
545
|
+
Add a subtle brand logo to the corner of each slide using the `.slide-logo` CSS class:
|
|
546
|
+
|
|
547
|
+
```tsx
|
|
548
|
+
function SlideLogo() {
|
|
549
|
+
return (
|
|
550
|
+
<img
|
|
551
|
+
src="/logo.svg"
|
|
552
|
+
alt=""
|
|
553
|
+
className="slide-logo"
|
|
554
|
+
width={28}
|
|
555
|
+
height={28}
|
|
556
|
+
aria-hidden="true"
|
|
557
|
+
/>
|
|
558
|
+
)
|
|
559
|
+
}
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
Place `<SlideLogo />` inside each slide's inner div (which must have `className="relative"`). The logo appears at 25% opacity in the bottom-right corner. Omit from title and closing slides where the logo appears prominently.
|
|
563
|
+
|
|
564
|
+
## Tips
|
|
565
|
+
|
|
566
|
+
- Run `npm run dev` for hot reload while editing.
|
|
567
|
+
- One idea per slide. If a slide says two things, make two slides.
|
|
568
|
+
- Reveal content progressively with `data-step` to control pacing, or use `auto-*` classes for elements that should animate in without clicks.
|
|
569
|
+
- Charts go inside `card-surface` containers. Use fixed pixel heights (300-420px) on `ResponsiveContainer`.
|
|
570
|
+
- Test at projection distance: if you cannot read it from 2 meters on a laptop, it fails on a projector.
|
|
571
|
+
- Never hardcode hex colors. Always use CSS variables from the brand system.
|
|
572
|
+
- Section labels (`section-label` class) go above every content slide title to show where the audience is in the deck.
|
|
573
|
+
- Keep text above 16pt. Below that it disappears on projectors.
|
|
574
|
+
- Customer logos need light (white-on-transparent) variants for dark-themed decks. Store originals in `public/logos/` and light variants in `public/logos/light/`.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
A presentation built with [slidenerds](https://github.com/strategicnerds/slidenerds).
|
|
4
|
+
|
|
5
|
+
## Local development
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install
|
|
9
|
+
npm run dev
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Open [http://localhost:3000](http://localhost:3000) to see your deck.
|
|
13
|
+
|
|
14
|
+
## How to build slides
|
|
15
|
+
|
|
16
|
+
Open a second terminal and talk to Claude Code (or your preferred LLM). The CLAUDE.md file in this project teaches the LLM the slidenerds conventions. Hot reload updates your browser as the LLM writes code.
|
|
17
|
+
|
|
18
|
+
## Keyboard shortcuts
|
|
19
|
+
|
|
20
|
+
| Key | Action |
|
|
21
|
+
|-----|--------|
|
|
22
|
+
| Space / Right arrow | Next step or slide |
|
|
23
|
+
| Left arrow / Backspace | Previous step or slide |
|
|
24
|
+
| P | Presenter mode |
|
|
25
|
+
| L | Light table |
|
|
26
|
+
| F | Fullscreen |
|
|
27
|
+
| Escape | Exit fullscreen |
|
|
28
|
+
|
|
29
|
+
## Deploy
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
vercel --prod
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or deploy to any platform that supports Next.js.
|