stagecraft 0.1.0 → 0.2.1
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/AGENT.md +98 -37
- package/CHANGELOG.md +54 -0
- package/README.md +2 -2
- package/package.json +29 -6
package/AGENT.md
CHANGED
|
@@ -2,18 +2,104 @@
|
|
|
2
2
|
|
|
3
3
|
You're not filling a template. You're directing a scene.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Reach for custom JS first. Reach for the component catalog when a pattern truly fits.** The 50 components below are sugar around one tiny primitive — they are anchors, never cages. Take them apart. Write raw `render(el)` and `init(el)` functions. Use the Web Animations API. Use SVG. Use Canvas. Animation is the language of your deck — not a checkbox.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
If your slide reads like a filled-in form, you wasted the moment.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- Each slide owns its DOM, its animation, its lifecycle.
|
|
11
|
-
- The engine handles navigation, the storyboard, and transitions.
|
|
12
|
-
- If you copy-paste a component call and don't customize it, you've wasted the opportunity.
|
|
9
|
+
## 1. What a slide actually is
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
There is exactly one foundational API:
|
|
15
12
|
|
|
16
|
-
|
|
13
|
+
```js
|
|
14
|
+
Stage.register({
|
|
15
|
+
section, title,
|
|
16
|
+
render(el) { /* set up DOM */ },
|
|
17
|
+
init(el)? { /* run animation, return cleanup */ },
|
|
18
|
+
replay(el)? { /* re-run on R */ },
|
|
19
|
+
steps?, onStep? { /* internal step navigation */ }
|
|
20
|
+
});
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
That's the whole contract. Everything else — every factory you'll see below — is sugar around this primitive.
|
|
24
|
+
|
|
25
|
+
### A 100% custom slide (the canonical form)
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
Stage.register({
|
|
29
|
+
section: 2,
|
|
30
|
+
title: '02 · Custom motion',
|
|
31
|
+
render(el) {
|
|
32
|
+
el.innerHTML = `
|
|
33
|
+
<h1 style="font-size: clamp(3rem, 9vw, 8rem); font-weight: 600;
|
|
34
|
+
letter-spacing: -0.025em; text-align: center;">
|
|
35
|
+
Write <span class="accent">whatever HTML</span> you want.
|
|
36
|
+
</h1>
|
|
37
|
+
<svg id="field" viewBox="0 0 800 200"
|
|
38
|
+
style="width:min(800px,80vw); height:200px; margin-top:2rem;"></svg>
|
|
39
|
+
`;
|
|
40
|
+
},
|
|
41
|
+
init(el) {
|
|
42
|
+
// Whatever JS animation you want. Web Animations API, RAF, intervals.
|
|
43
|
+
const svg = el.querySelector('#field');
|
|
44
|
+
const id = setInterval(() => {
|
|
45
|
+
const x = Math.random() * 800;
|
|
46
|
+
Stage.emitParticle(svg, x, 200, x + (Math.random() - 0.5) * 200, -20, 2400);
|
|
47
|
+
}, 220);
|
|
48
|
+
return () => clearInterval(id); // cleanup when slide leaves
|
|
49
|
+
}
|
|
50
|
+
}, {
|
|
51
|
+
notes: 'Take this as proof: the catalog is optional. The full power lives here.'
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
That's a complete, finished slide. No factory required. You can do anything CSS, SVG, Canvas, the Web Animations API, and JS can do — which is everything.
|
|
56
|
+
|
|
57
|
+
### A factory call (sugar for common shapes)
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
Stage.register(Stage.KineticText({
|
|
61
|
+
lines: [
|
|
62
|
+
{ text: 'Sometimes', color: 'fg' },
|
|
63
|
+
{ text: 'a list of lines', color: 'dim' },
|
|
64
|
+
{ text: 'is enough.', color: 'accent' }
|
|
65
|
+
]
|
|
66
|
+
}));
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Both forms coexist. Both accept a second `meta` arg for speaker notes (`{ notes: '...' }`).
|
|
70
|
+
|
|
71
|
+
## 2. When to write custom vs. reach for a factory
|
|
72
|
+
|
|
73
|
+
**Write a fully custom slide when:**
|
|
74
|
+
- The animation IS the message (token streams, particle fields, terminal logs)
|
|
75
|
+
- You're combining motion patterns no factory covers
|
|
76
|
+
- The slide is the centerpiece of a section — it deserves the time
|
|
77
|
+
- You can see the slide in your head and the catalog can't reproduce it
|
|
78
|
+
|
|
79
|
+
**Extend a factory's `init` when:**
|
|
80
|
+
- The shape fits (a bulleted list, a quote, a stat grid) but you want extra motion on top
|
|
81
|
+
- Get a factory, then call `Object.assign(slide, { init(el) { … } })` or write a wrapping registration
|
|
82
|
+
|
|
83
|
+
**Reach for the factory plain when:**
|
|
84
|
+
- It is genuinely the right pattern — list, comparison, divider — and motion sugar via `reveal: 'staggered' | 'per-click'` is enough
|
|
85
|
+
|
|
86
|
+
A healthy deck: roughly **20–30% bespoke from scratch**, **40% factory + customized init**, **30–40% plain factories**. If your bespoke share is 0%, the deck has gone flat. Add a centerpiece.
|
|
87
|
+
|
|
88
|
+
## 3. The cookbook (start here for bespoke inspiration)
|
|
89
|
+
|
|
90
|
+
Five real bespoke slides ship in `examples/` — they are not abstract demos, they are slides from a production deck. Read them before writing your own bespoke:
|
|
91
|
+
|
|
92
|
+
- `examples/token-stream.js` — interleaved word-fill across a split panel with particle emit
|
|
93
|
+
- `examples/orchestration-graph.js` — SVG hex-graph, particles flowing from satellites to center
|
|
94
|
+
- `examples/terminal-log.js` — streaming colored log lines + a "human realization" reveal arc
|
|
95
|
+
- `examples/whoami.js` — terminal prompt cycling through identity strings
|
|
96
|
+
- `examples/closing-card.js` — QR + dedication + underline + presenter names
|
|
97
|
+
|
|
98
|
+
These show you the bar. Don't copy them — take the *technique* (the interleaved queue, the SVG particle pattern, the streaming type) and apply it to your own content.
|
|
99
|
+
|
|
100
|
+
## 4. The toolbox (Layer-2 components — reference)
|
|
101
|
+
|
|
102
|
+
Components have spare defaults on purpose. Adding animation is opt-in. Treat this whole section as a *reference* — scan when you need an anchor, ignore otherwise.
|
|
17
103
|
|
|
18
104
|
### Stage.KineticText — multi-line staggered reveal (workhorse, ~50% of slides)
|
|
19
105
|
```js
|
|
@@ -635,7 +721,7 @@ Stage.register(Stage.Marquee({
|
|
|
635
721
|
}));
|
|
636
722
|
```
|
|
637
723
|
|
|
638
|
-
##
|
|
724
|
+
## 5. The toolbox (Layer-1 primitives)
|
|
639
725
|
|
|
640
726
|
Available globally as `Stage.<name>`. Use them in any slide's `init()` to build bespoke motion.
|
|
641
727
|
|
|
@@ -649,19 +735,7 @@ Available globally as `Stage.<name>`. Use them in any slide's `init()` to build
|
|
|
649
735
|
| `sessionElapsedClock` | `({start}) → {el, stop}` | Live MM:SS clock element. |
|
|
650
736
|
| `assignStageKeys` | `(root)` | Auto-assigns `data-stage-key` for edit-mode pins (engine calls this). |
|
|
651
737
|
|
|
652
|
-
##
|
|
653
|
-
|
|
654
|
-
When you need motion that the components don't cover, **read these first** — they're the ceiling, not the floor. All in `examples/`:
|
|
655
|
-
|
|
656
|
-
- `examples/token-stream.js` — interleaved word-fill across a split panel, particle emit.
|
|
657
|
-
- `examples/orchestration-graph.js` — SVG hex-graph with particles flowing from satellites to center.
|
|
658
|
-
- `examples/terminal-log.js` — streaming colored log lines with a human realization reveal.
|
|
659
|
-
- `examples/whoami.js` — terminal prompt cycling through identity strings.
|
|
660
|
-
- `examples/closing-card.js` — QR + dedication + underline.
|
|
661
|
-
|
|
662
|
-
Don't copy them verbatim. Take the technique (the interleaved queue, the SVG particle pattern, the streaming type) and apply it to your own content.
|
|
663
|
-
|
|
664
|
-
## 5. The step model
|
|
738
|
+
## 6. The step model
|
|
665
739
|
|
|
666
740
|
A slide may declare `steps: N`. The engine:
|
|
667
741
|
|
|
@@ -688,7 +762,7 @@ Stage.register({
|
|
|
688
762
|
|
|
689
763
|
For trivial cases use `Stage.revealByDataStep`. For anything richer (glow transitions, particle emit, typewriter on each step) write `onStep` yourself — that's the point.
|
|
690
764
|
|
|
691
|
-
##
|
|
765
|
+
## 7. The transition library
|
|
692
766
|
|
|
693
767
|
In `stagecraft.config.js`, the `transition` on each slide controls how it enters:
|
|
694
768
|
|
|
@@ -715,7 +789,7 @@ Built-in (14):
|
|
|
715
789
|
|
|
716
790
|
Themes override visuals. Unknown → falls back to `fade`.
|
|
717
791
|
|
|
718
|
-
##
|
|
792
|
+
## 8. Edit mode (you-might-not-see-it, but: it exists)
|
|
719
793
|
|
|
720
794
|
When the human runs `npx stagecraft serve`, they get a browser-based editor that writes back to source. They might leave notes in slides:
|
|
721
795
|
|
|
@@ -733,19 +807,6 @@ When they say "process my notes":
|
|
|
733
807
|
|
|
734
808
|
Notes don't get a "resolved" state. Deleting them is how you mark them done.
|
|
735
809
|
|
|
736
|
-
## 8. When to register a custom slide vs. use a component
|
|
737
|
-
|
|
738
|
-
Use a component when:
|
|
739
|
-
- It's truly a list of bullets / a comparison / a section divider — boring is fine for these.
|
|
740
|
-
- The visual you want is achievable with one component + minor styling.
|
|
741
|
-
|
|
742
|
-
Write a custom slide (just `Stage.register({section, title, render, init, ...})`) when:
|
|
743
|
-
- The animation is core to the message (token-stream, orchestration graph, terminal log).
|
|
744
|
-
- You're combining motion patterns no component covers.
|
|
745
|
-
- The slide is the centerpiece of a section — it deserves the attention.
|
|
746
|
-
|
|
747
|
-
The split should be roughly: ~40% workhorse components (KineticText, SectionCard, Quote, BigNumber), ~30% structural (ImageText, Bento, Compare, Pillars, Timeline), ~15% chart/diagram for data-heavy moments (BarChart, Matrix2x2, Pyramid, Funnel, Venn, ProcessFlow, Cycle), ~15% bespoke. If the bespoke share goes below 10%, the deck has gone flat.
|
|
748
|
-
|
|
749
810
|
## 9. The full component catalog at a glance
|
|
750
811
|
|
|
751
812
|
| Family | Components |
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0 — 2026-05-23
|
|
4
|
+
|
|
5
|
+
### Themes
|
|
6
|
+
- Added **Shopware** theme — fifth official theme, sourced from the Meteor design system (`@shopware-ag/meteor-tokens` v1.4.0). Light, Inter, brand-blue `#0870ff`, semantic palette piped through. Full overrides for all 50 components and all transitions.
|
|
7
|
+
- Polished **Paper**, **Neon**, and **Brand** themes with per-family component overrides (each had been mostly inheriting Phosphor before — now they have distinct visual personalities).
|
|
8
|
+
- **Theme picker** in the storyboard toolbar lets you switch live across all 5 themes.
|
|
9
|
+
- Demo loads all 5 themes' CSS so switching is instant (no reload). Production starter loads a single theme bundle and reloads on switch.
|
|
10
|
+
|
|
11
|
+
### Editor
|
|
12
|
+
- New **'E' keypress** toggles edit-mode affordances on/off without disconnecting the dev server — present cleanly even with the server running.
|
|
13
|
+
- New **Speaker notes** field (`Stage.register(slide, {notes: '…'})`) with 🎙 button per storyboard tile. AST-aware roundtrip preserves all other slide fields.
|
|
14
|
+
- New **CRUD** in storyboard: ➕ add slide (with template choice), 🗑 delete slide.
|
|
15
|
+
- New **Process notes** button copies a ready-made agent prompt to the clipboard.
|
|
16
|
+
- New **Pin markers** on annotated elements during edit mode (yellow pulsing dots, hover for note text).
|
|
17
|
+
- Element click for inline editing changed from double-click to single click.
|
|
18
|
+
|
|
19
|
+
### Presenter view
|
|
20
|
+
- Press **P** to open a second window with the presenter view: current slide, next-slide thumbnail, speaker notes, elapsed timer, wall clock. Multi-monitor via `BroadcastChannel` sync. Laptop sees notes, beamer sees clean slide.
|
|
21
|
+
|
|
22
|
+
### Components (50 total)
|
|
23
|
+
- Phase 3 added: ImageText, FullImage, Quote, BigNumber, Stats, Bento, Pillars, Timeline, Pyramid, Cycle, Funnel, Matrix2x2, BarChart, Progress, ProcessFlow, Venn, KPI, DonutChart, LineChart, Gauge, SparkLine, Heatmap, Roadmap, SWOT, CodeBlock, CodeDiff, Pricing, Testimonial, TeamGrid, Agenda, Checklist, Steps, CTA, Callout, Tip, BeforeAfter, Statement, QandA, Manifesto, Punchline, Definition, ImageGrid, Spotlight, Marquee.
|
|
24
|
+
|
|
25
|
+
### Transitions (15 total)
|
|
26
|
+
- Added zoom-in, zoom-out, flip (3D rotateY), iris (clip-path), shutter, push, typewriter, shatter.
|
|
27
|
+
- Hover-to-play-once preview in the picker.
|
|
28
|
+
|
|
29
|
+
### Tooling
|
|
30
|
+
- **Bundle script** (`npm run build`): concatenates everything into `dist/stagecraft.bundle.{js,css}` + per-theme CSS bundles.
|
|
31
|
+
- **PDF export** (`npx stagecraft export pdf`): renders deck to PDF via Playwright + pdf-lib (optional deps).
|
|
32
|
+
- **Visual regression** harness (`tests/visual/run.js`): Playwright snapshots with optional pixelmatch diffing.
|
|
33
|
+
- **GitHub Pages CI**: `npm run build` + `scripts/deploy-build.js` produce a `deploy/` directory; `.github/workflows/deploy-pages.yml` ships it on every push to main.
|
|
34
|
+
- **Verify CI**: `.github/workflows/verify.yml` runs `npm run verify` (AST tests), syntax-checks every JS file, builds bundles, and assembles the deploy directory on every PR.
|
|
35
|
+
|
|
36
|
+
### Accessibility
|
|
37
|
+
- `prefers-reduced-motion: reduce` shortcuts the typewriter, particles, and stagger animations to their final state.
|
|
38
|
+
|
|
39
|
+
### Bug fixes
|
|
40
|
+
- CodeBlock/CodeDiff: removed redundant `<pre>` wrapper that was preserving template-string whitespace as huge inter-line gaps.
|
|
41
|
+
- Venn diagram: geometry now expressed in SVG viewBox units; labels converted to container-% on render, so they align with the circles regardless of container aspect ratio.
|
|
42
|
+
- Heatmap: x-labels wrapped in a `.hm-x-row` grid container so they run horizontally instead of stacking.
|
|
43
|
+
- Drag-to-reorder in storyboard: the synthetic click after drop no longer closes the storyboard.
|
|
44
|
+
- Click-to-advance no longer fires in edit mode (previously prevented inline editing on the first click of any potential double-click).
|
|
45
|
+
- Storyboard state persists across the file-watcher reload after a drag-drop reorder.
|
|
46
|
+
- 'cut' transition now has a picker-only preview animation (was invisible before).
|
|
47
|
+
|
|
48
|
+
## 0.1.0 — 2026-05-22
|
|
49
|
+
|
|
50
|
+
Initial release.
|
|
51
|
+
|
|
52
|
+
- Engine, primitives, 6 core components, 4 themes, 5 cookbook examples.
|
|
53
|
+
- Edit mode with slide-level notes, element-pin notes, transition picker, inline text editing.
|
|
54
|
+
- Dev server with WebSocket + AST roundtrip.
|
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Stagecraft
|
|
2
2
|
|
|
3
|
-
**Cinematic, agent-authored presentations
|
|
3
|
+
**Cinematic, agent-authored presentations. No build step.**
|
|
4
4
|
|
|
5
5
|
▶ **[Live demo](https://noegel.io/stagecraft/)** — the deck about Stagecraft, built with Stagecraft. Auto-deployed from `main` via GitHub Pages.
|
|
6
6
|
|
|
7
|
-
A small JavaScript library for
|
|
7
|
+
A small JavaScript library for animated slide decks. Source is plain JS files loaded by `<script>` tags — no bundler, no framework, opens directly in any browser. Designed so an LLM can generate a deck that doesn't look like an LLM generated it.
|
|
8
8
|
|
|
9
9
|
## Why
|
|
10
10
|
|
package/package.json
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stagecraft",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "Cinematic, agent-authored presentations
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Cinematic, agent-authored presentations. No build step.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/engine.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"stagecraft": "bin/cli.js"
|
|
9
9
|
},
|
|
10
|
+
"homepage": "https://noegel.io/stagecraft/",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/dnoegel/stagecraft.git"
|
|
14
|
+
},
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/dnoegel/stagecraft/issues"
|
|
17
|
+
},
|
|
18
|
+
"author": "Daniel Nögel",
|
|
10
19
|
"files": [
|
|
11
20
|
"src",
|
|
12
21
|
"themes",
|
|
@@ -15,7 +24,9 @@
|
|
|
15
24
|
"bin",
|
|
16
25
|
"starter",
|
|
17
26
|
"AGENT.md",
|
|
18
|
-
"README.md"
|
|
27
|
+
"README.md",
|
|
28
|
+
"LICENSE",
|
|
29
|
+
"CHANGELOG.md"
|
|
19
30
|
],
|
|
20
31
|
"scripts": {
|
|
21
32
|
"serve": "node bin/serve.js",
|
|
@@ -25,7 +36,8 @@
|
|
|
25
36
|
"build": "node scripts/bundle.js",
|
|
26
37
|
"test:visual": "node tests/visual/run.js",
|
|
27
38
|
"test:visual:update": "node tests/visual/run.js --update-baseline",
|
|
28
|
-
"export": "node bin/export.js"
|
|
39
|
+
"export": "node bin/export.js",
|
|
40
|
+
"prepublishOnly": "npm run build"
|
|
29
41
|
},
|
|
30
42
|
"dependencies": {
|
|
31
43
|
"@babel/generator": "^7.24.0",
|
|
@@ -36,6 +48,17 @@
|
|
|
36
48
|
"mime-types": "^2.1.35",
|
|
37
49
|
"ws": "^8.16.0"
|
|
38
50
|
},
|
|
39
|
-
"keywords": [
|
|
40
|
-
|
|
51
|
+
"keywords": [
|
|
52
|
+
"slides",
|
|
53
|
+
"presentation",
|
|
54
|
+
"agent",
|
|
55
|
+
"llm",
|
|
56
|
+
"stagecraft",
|
|
57
|
+
"deck",
|
|
58
|
+
"keynote"
|
|
59
|
+
],
|
|
60
|
+
"license": "MIT",
|
|
61
|
+
"engines": {
|
|
62
|
+
"node": ">=18"
|
|
63
|
+
}
|
|
41
64
|
}
|