octocode-cli 1.3.0 → 1.5.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/README.md +129 -28
- package/out/chunks/chunk-7476PETK.js +309 -0
- package/out/chunks/chunk-CVNNNSMQ.js +26 -0
- package/out/chunks/chunk-OQBJTZWK.js +60 -0
- package/out/chunks/chunk-UCZCF3BQ.js +9 -0
- package/out/chunks/command-help-specs-JZXVSLZ5.js +8 -0
- package/out/chunks/commands-XBFPLHSQ.js +8 -0
- package/out/chunks/help-P7TCOYAJ.js +10 -0
- package/out/chunks/main-help-ULF5PAQY.js +10 -0
- package/out/chunks/prompts-5E6VKRX5.js +8 -0
- package/out/chunks/spinner-URV2OX6O.js +8 -0
- package/out/chunks/tool-command-M6VA7P2F.js +8 -0
- package/out/octocode-cli.js +1 -1
- package/package.json +5 -3
- package/skills/README.md +60 -58
- package/skills/agentic-flow-best-practices/SKILL.md +280 -0
- package/skills/agentic-flow-best-practices/references/agent-collaboration-patterns.md +75 -0
- package/skills/agentic-flow-best-practices/references/pr-review-agent-example.md +47 -0
- package/skills/agentic-flow-best-practices/references/resources.md +112 -0
- package/skills/octocode-brainstorming/.env.example +11 -0
- package/skills/octocode-brainstorming/SKILL.md +262 -0
- package/skills/octocode-brainstorming/scripts/tavily-search.mjs +138 -0
- package/skills/octocode-chrome-devtools/README.md +541 -0
- package/skills/octocode-chrome-devtools/SKILL.md +197 -0
- package/skills/octocode-chrome-devtools/agents/openai.yaml +7 -0
- package/skills/octocode-chrome-devtools/references/CDP_AGENT_REFERENCE.md +401 -0
- package/skills/octocode-chrome-devtools/references/CHROME_FLAGS.md +234 -0
- package/skills/octocode-chrome-devtools/references/INTENTS.md +108 -0
- package/skills/octocode-chrome-devtools/references/INTENTS_AUTH.md +179 -0
- package/skills/octocode-chrome-devtools/references/INTENTS_AUTOMATION.md +214 -0
- package/skills/octocode-chrome-devtools/references/INTENTS_DEBUG.md +329 -0
- package/skills/octocode-chrome-devtools/references/INTENTS_ENVIRONMENT.md +237 -0
- package/skills/octocode-chrome-devtools/references/INTENTS_INSPECT.md +263 -0
- package/skills/octocode-chrome-devtools/references/INTENTS_STORAGE_CONSENT.md +214 -0
- package/skills/octocode-chrome-devtools/references/RECOVERY.md +39 -0
- package/skills/octocode-chrome-devtools/references/SCRIPT_PATTERNS.md +43 -0
- package/skills/octocode-chrome-devtools/references/SCRIPT_PATTERNS_ASYNC_WORKERS.md +345 -0
- package/skills/octocode-chrome-devtools/references/SCRIPT_PATTERNS_BROWSER.md +403 -0
- package/skills/octocode-chrome-devtools/references/SCRIPT_PATTERNS_OBSERVE.md +275 -0
- package/skills/octocode-chrome-devtools/references/SCRIPT_PATTERNS_SPECIAL.md +18 -0
- package/skills/octocode-chrome-devtools/scripts/cdp-runner.mjs +503 -0
- package/skills/octocode-chrome-devtools/scripts/cdp-sandbox.mjs +123 -0
- package/skills/octocode-chrome-devtools/scripts/cdp-template.mjs +81 -0
- package/skills/octocode-chrome-devtools/scripts/octocode-chrome-devtools.vpn.example.json +8 -0
- package/skills/octocode-chrome-devtools/scripts/open-browser.mjs +362 -0
- package/skills/octocode-chrome-devtools/scripts/sourcemap-resolver.mjs +193 -0
- package/skills/octocode-chrome-devtools/scripts/undercover.mjs +226 -0
- package/skills/octocode-design/README.md +2 -2
- package/skills/octocode-documentation-writer/README.md +1 -1
- package/skills/octocode-engineer/README.md +1 -1
- package/skills/octocode-engineer/SKILL.md +137 -306
- package/skills/octocode-engineer/references/cli-reference.md +13 -0
- package/skills/octocode-engineer/references/output-files.md +3 -3
- package/skills/octocode-engineer/scripts/run.js +146 -146
- package/skills/octocode-engineer/src/pipeline/main.ts +1 -17
- package/skills/octocode-engineer/src/pipeline/progress.ts +4 -0
- package/skills/octocode-engineer/src/reporting/summary-md.test.ts +48 -0
- package/skills/octocode-engineer/src/reporting/summary-md.ts +43 -2
- package/skills/octocode-install/SKILL.md +1 -1
- package/skills/octocode-pull-request-reviewer/README.md +5 -5
- package/skills/octocode-pull-request-reviewer/SKILL.md +1 -1
- package/skills/octocode-research/AGENTS.md +1 -1
- package/skills/octocode-research/README.md +2 -2
- package/skills/octocode-research/docs/ARCHITECTURE.md +1 -1
- package/skills/octocode-research/scripts/server.js +184 -239
- package/skills/octocode-research/src/routes/github.ts +4 -21
- package/skills/octocode-research/src/routes/local.ts +4 -21
- package/skills/octocode-research/src/utils/fileContentTransform.ts +44 -0
- package/skills/octocode-search-skill/SKILL.md +337 -0
- package/skills/octocode-search-skill/references/agent-skills-guide.md +177 -0
- package/skills/octocode-search-skill/references/discovery-surfaces.md +162 -0
- package/skills/octocode-search-skill/references/fetch-and-create-locally.md +57 -0
- package/skills/octocode-search-skill/references/install-reference.md +130 -0
- package/skills/octocode-search-skill/references/references-template.md +27 -0
- package/skills/octocode-search-skill/references/references.md +62 -0
- package/skills/octocode-slides/README.md +307 -0
- package/skills/octocode-slides/SKILL.md +410 -0
- package/skills/octocode-slides/references/01-brief.md +156 -0
- package/skills/octocode-slides/references/02-research.md +149 -0
- package/skills/octocode-slides/references/03-outline.md +172 -0
- package/skills/octocode-slides/references/04-design.md +301 -0
- package/skills/octocode-slides/references/05-implementation.md +213 -0
- package/skills/octocode-slides/references/06-review.md +258 -0
- package/skills/octocode-slides/references/animation.md +281 -0
- package/skills/octocode-slides/references/design-system.md +316 -0
- package/skills/octocode-slides/references/html-templates.md +673 -0
- package/skills/octocode-slides/references/image-generation.md +448 -0
- package/skills/octocode-slides/references/resources.md +840 -0
- package/skills/octocode-slides/references/slide-rules.md +541 -0
- package/skills/octocode-slides/references/wireframes.md +727 -0
- package/skills/octocode-slides/scripts/animation.js +182 -0
- package/skills/octocode-slides/scripts/base.css +353 -0
- package/skills/octocode-slides/scripts/base.html +655 -0
- package/skills/octocode-slides/scripts/generate_image.py +221 -0
- package/skills/octocode-slides/scripts/navbridge.js +79 -0
- package/skills/octocode-slides/scripts/presenter.js +316 -0
- package/skills/octocode-slides/scripts/slide.html +248 -0
- package/skills/octocode-stats/SKILL.md +73 -0
- package/skills/octocode-stats/assets/template.html +1332 -0
- package/skills/octocode-stats/scripts/build_dashboard.mjs +407 -0
- package/out/chunks/chunk-LH4AZJPA.js +0 -389
- package/out/chunks/command-help-specs-CQ3RBLP6.js +0 -8
- package/out/chunks/commands-M3QTWKWE.js +0 -51
- package/out/chunks/help-XPXP46ZT.js +0 -10
- package/out/chunks/main-help-HXFAFHPG.js +0 -10
- package/out/chunks/tool-command-VHFLPIHY.js +0 -8
|
@@ -0,0 +1,840 @@
|
|
|
1
|
+
# Slide Libraries & Design Resources
|
|
2
|
+
|
|
3
|
+
CDN libraries and design references available to any slide. The agent chooses what fits the deck — nothing here is mandatory unless the slide type needs it.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Markdown Rendering
|
|
8
|
+
|
|
9
|
+
### marked.js — Markdown → HTML, zero dependencies
|
|
10
|
+
**Rating:** ★★★★☆ — solid workhorse; only needed when slide content is Markdown-sourced
|
|
11
|
+
**CDN:** `https://cdn.jsdelivr.net/npm/marked/lib/marked.umd.js`
|
|
12
|
+
**Repo:** [markedjs/marked](https://github.com/markedjs/marked) | 35k+ stars
|
|
13
|
+
**Use when:** A content slide sources text from a `.md` file, or the user provides long-form content as Markdown.
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<script src="https://cdn.jsdelivr.net/npm/marked/lib/marked.umd.js"></script>
|
|
17
|
+
<div class="slide-body" data-md>
|
|
18
|
+
# Heading
|
|
19
|
+
- point one
|
|
20
|
+
- point two
|
|
21
|
+
</div>
|
|
22
|
+
<script>
|
|
23
|
+
document.querySelectorAll('[data-md]').forEach(el => {
|
|
24
|
+
el.innerHTML = marked.parse(el.textContent.trim());
|
|
25
|
+
});
|
|
26
|
+
</script>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Configuration for presentations:**
|
|
30
|
+
```js
|
|
31
|
+
marked.setOptions({
|
|
32
|
+
breaks: true, // newline → <br>
|
|
33
|
+
gfm: true, // GitHub Flavored Markdown
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Animation
|
|
40
|
+
|
|
41
|
+
### CSS-native stagger — zero dependencies (Chrome + Safari; Firefox in progress)
|
|
42
|
+
**Rating:** ★★★★★ — best default for bullet/card stagger; no import, no bundle, adapts to DOM changes automatically
|
|
43
|
+
**Spec:** [CSS Wrapped 2025](https://chrome.dev/css-wrapped-2025/) · [Smashing Mag deep-dive](https://www.smashingmagazine.com/2025/12/state-logic-native-power-css-wrapped-2025/)
|
|
44
|
+
**Use when:** Bullets, cards, or tiles need a staggered entrance. Replaces Motion.dev stagger for most slide use cases — no import, adapts dynamically to DOM changes.
|
|
45
|
+
|
|
46
|
+
```css
|
|
47
|
+
/* Add to slide <style>. Works with any list of siblings. */
|
|
48
|
+
.bullet {
|
|
49
|
+
transition: opacity 0.25s ease, translate 0.25s ease;
|
|
50
|
+
transition-delay: calc(0.1s * (sibling-index() - 1)); /* 1-based, subtract 1 so first = 0s */
|
|
51
|
+
@starting-style {
|
|
52
|
+
opacity: 0;
|
|
53
|
+
translate: 0 0.75em;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Gate with `@supports` for older browsers:**
|
|
59
|
+
```css
|
|
60
|
+
@supports (transition-delay: calc(sibling-index() * 0s)) {
|
|
61
|
+
.bullet { /* stagger rules */ }
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
### Motion — Production-grade JS animations
|
|
68
|
+
**Rating:** ★★★★★ — essential for counters, timelines, and spring physics; nothing else matches its API quality
|
|
69
|
+
**CDN (ESM):** `https://cdn.jsdelivr.net/npm/motion@latest/+esm`
|
|
70
|
+
**Docs:** [motion.dev/docs/quick-start](https://motion.dev/docs/quick-start)
|
|
71
|
+
**Repo:** [motiondotdev/motion](https://github.com/motiondotdev/motion) | 26k+ stars
|
|
72
|
+
**Use when:** Timelines, number counters, spring physics, or slide-local transitions that CSS can't express.
|
|
73
|
+
|
|
74
|
+
**Counter / number animation:**
|
|
75
|
+
```html
|
|
76
|
+
<script type="module">
|
|
77
|
+
import { animate } from "https://cdn.jsdelivr.net/npm/motion@latest/+esm";
|
|
78
|
+
animate(0, 2_400_000, {
|
|
79
|
+
duration: 1.6,
|
|
80
|
+
easing: [0.22, 1, 0.36, 1],
|
|
81
|
+
onUpdate(v) {
|
|
82
|
+
document.getElementById('counter').textContent = Math.round(v).toLocaleString();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
</script>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Timeline sequence (title → subtitle → body):**
|
|
89
|
+
```html
|
|
90
|
+
<script type="module">
|
|
91
|
+
import { timeline } from "https://cdn.jsdelivr.net/npm/motion@latest/+esm";
|
|
92
|
+
timeline([
|
|
93
|
+
['.slide-title', { opacity: [0, 1], y: [-12, 0] }, { duration: 0.4 }],
|
|
94
|
+
['.slide-subtitle', { opacity: [0, 1] }, { duration: 0.3, at: '+0.1' }],
|
|
95
|
+
['.slide-body', { opacity: [0, 1], y: [8, 0] }, { duration: 0.4, at: '+0.1' }],
|
|
96
|
+
]);
|
|
97
|
+
</script>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Stagger (use CSS-native first; fall back to this when `sibling-index()` unsupported):**
|
|
101
|
+
```html
|
|
102
|
+
<script type="module">
|
|
103
|
+
import { animate, stagger } from "https://cdn.jsdelivr.net/npm/motion@latest/+esm";
|
|
104
|
+
animate('.bullet', { opacity: [0, 1], y: [16, 0] }, { delay: stagger(0.12), duration: 0.45, easing: [0.22, 1, 0.36, 1] });
|
|
105
|
+
</script>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
### GSAP — Complex timelines and SVG choreography
|
|
111
|
+
**Rating:** ★★★☆☆ — overkill for most slides; reach for it only when Motion.dev and CSS both fall short
|
|
112
|
+
**CDN:** `https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js`
|
|
113
|
+
**Docs:** [gsap.com/docs](https://gsap.com/docs/)
|
|
114
|
+
**Use when:** SVG path animations or complex choreography where Motion.dev is insufficient. Avoid scroll-driven patterns inside slides because slide content should remain fixed within the frame.
|
|
115
|
+
|
|
116
|
+
```html
|
|
117
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
|
|
118
|
+
<script>
|
|
119
|
+
gsap.from('.slide-body > *', { opacity: 0, y: 20, stagger: 0.12, duration: 0.5, ease: 'power2.out' });
|
|
120
|
+
</script>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
**Animation decision table:**
|
|
126
|
+
|
|
127
|
+
| Situation | Use |
|
|
128
|
+
|-----------|-----|
|
|
129
|
+
| Simple fade / slide-up on load | CSS `.fade-in`, `.slide-up` from base.css |
|
|
130
|
+
| Staggered bullets/cards (modern browsers) | CSS `sibling-index()` + `@starting-style` |
|
|
131
|
+
| Staggered bullets/cards (broad browser support) | Motion `stagger()` |
|
|
132
|
+
| Number counters, progress fills | Motion `animate(0, N, onUpdate)` |
|
|
133
|
+
| Sequenced multi-element choreography | Motion `timeline()` |
|
|
134
|
+
| SVG path animation or complex choreography | GSAP |
|
|
135
|
+
| Spring / physics-based motion | Motion spring easing |
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Slide Transitions (View Transitions API)
|
|
140
|
+
|
|
141
|
+
**Rating:** ★★★★☆ — powerful and zero-dependency; iframe caveat limits the simplest path, but SPA pattern works cleanly
|
|
142
|
+
**No library needed — browser-native.**
|
|
143
|
+
**MDN:** [Using the View Transition API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API/Using)
|
|
144
|
+
**Recipes:** [Piccalilli — practical VT examples](https://piccalil.li/blog/some-practical-examples-of-view-transitions-to-elevate-your-ui/)
|
|
145
|
+
**Toolkit:** [vtbag.dev](https://vtbag.dev/) — "Bag of Tricks" for view transitions (named patterns, debugging, demos)
|
|
146
|
+
|
|
147
|
+
**SPA path — wrap iframe swap in `index.html`:**
|
|
148
|
+
|
|
149
|
+
```js
|
|
150
|
+
// In index.html navigation controller — wrap slide change in a transition
|
|
151
|
+
function goToSlide(n) {
|
|
152
|
+
if (!document.startViewTransition) { updateSlide(n); return; }
|
|
153
|
+
document.startViewTransition(() => updateSlide(n));
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Directional transitions — modern approach (`:active-view-transition-type`):**
|
|
158
|
+
```js
|
|
159
|
+
// Pass a direction type so CSS can target forward vs backward separately
|
|
160
|
+
function goToSlide(n, direction = 'forward') {
|
|
161
|
+
if (!document.startViewTransition) { updateSlide(n); return; }
|
|
162
|
+
document.startViewTransition({
|
|
163
|
+
update: () => updateSlide(n),
|
|
164
|
+
types: [direction] // 'forward' or 'backward'
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
```css
|
|
170
|
+
/* In index.html <style> — direction-aware keyframes */
|
|
171
|
+
@keyframes slide-out-left { to { transform: translateX(-100%); opacity: 0; } }
|
|
172
|
+
@keyframes slide-in-right { from { transform: translateX( 100%); opacity: 0; } }
|
|
173
|
+
@keyframes slide-out-right { to { transform: translateX( 100%); opacity: 0; } }
|
|
174
|
+
@keyframes slide-in-left { from { transform: translateX(-100%); opacity: 0; } }
|
|
175
|
+
|
|
176
|
+
:active-view-transition-type(forward) {
|
|
177
|
+
&::view-transition-old(root) { animation: slide-out-left 0.3s ease; }
|
|
178
|
+
&::view-transition-new(root) { animation: slide-in-right 0.3s ease; }
|
|
179
|
+
}
|
|
180
|
+
:active-view-transition-type(backward) {
|
|
181
|
+
&::view-transition-old(root) { animation: slide-out-right 0.3s ease; }
|
|
182
|
+
&::view-transition-new(root) { animation: slide-in-left 0.3s ease; }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* Gate reduced-motion */
|
|
186
|
+
@media (prefers-reduced-motion: reduce) {
|
|
187
|
+
::view-transition-old(root), ::view-transition-new(root) { animation: none; }
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
> **What VT animates in this architecture:** `document.startViewTransition` in `index.html` snapshots the **parent `#stage` wrapper** (the iframe container). The slide content *inside* the iframe is captured as a pixel snapshot. This is correct and visually convincing — the animation happens at the parent level, not inside the iframe.
|
|
192
|
+
|
|
193
|
+
**MPA / cross-document path (only for non-iframe decks):**
|
|
194
|
+
```css
|
|
195
|
+
/* Only use when each slide is a top-level page (no iframe wrapper). */
|
|
196
|
+
@view-transition { navigation: auto; }
|
|
197
|
+
|
|
198
|
+
@media (prefers-reduced-motion: reduce) {
|
|
199
|
+
@view-transition { navigation: none; }
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Named shared elements (logo/title that morphs between slides):**
|
|
204
|
+
```css
|
|
205
|
+
/* Apply to the *same* element in old and new slide — must be unique per transition */
|
|
206
|
+
.slide-logo { view-transition-name: deck-logo; contain: layout; }
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
> **iframe caveat:** cross-document VT and `view-transition-name` on elements *inside* iframes do not propagate to the parent. Use the SPA path (`document.startViewTransition` in `index.html`) and name elements on the **parent** (e.g. a HUD logo or progress bar) for morphing effects.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Code Syntax Highlighting
|
|
214
|
+
|
|
215
|
+
### highlight.js — Syntax highlighting, 200+ languages
|
|
216
|
+
**Rating:** ★★★★★ — drop-in, theme-matched, no config required; mandatory for any code slide
|
|
217
|
+
**CDN:**
|
|
218
|
+
```html
|
|
219
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/styles/github-dark.min.css">
|
|
220
|
+
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11/build/highlight.min.js"></script>
|
|
221
|
+
```
|
|
222
|
+
**Repo:** [highlightjs/highlight.js](https://github.com/highlightjs/highlight.js) | 24k+ stars
|
|
223
|
+
**Use when:** A code slide needs real syntax coloring (not just a monospace block). Better than a CSS `.language-*` class alone.
|
|
224
|
+
|
|
225
|
+
```html
|
|
226
|
+
<pre><code class="language-typescript">async function fetchUser(id: string): Promise<User> {
|
|
227
|
+
const res = await fetch(`/api/users/${id}`);
|
|
228
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
229
|
+
return res.json();
|
|
230
|
+
}</code></pre>
|
|
231
|
+
<script>
|
|
232
|
+
document.querySelectorAll('pre code').forEach(el => hljs.highlightElement(el));
|
|
233
|
+
</script>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**Suggested themes by background energy — pick what fits your palette:**
|
|
237
|
+
|
|
238
|
+
| Background | Recommended | Alt |
|
|
239
|
+
|------------|-------------|-----|
|
|
240
|
+
| Dark cool / neutral | `github-dark` | `monokai-sublime` |
|
|
241
|
+
| Dark warm / very dark | `tokyo-night-dark` | `nord` |
|
|
242
|
+
| Light | `github` | `xcode` |
|
|
243
|
+
| Minimal / low-contrast | `ascetic` | `base16/one-light` |
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Data Visualization — Library Decision
|
|
248
|
+
|
|
249
|
+
Pick the lightest library that delivers the chart type needed. Avoid loading multiple chart libraries in one slide.
|
|
250
|
+
|
|
251
|
+
| Chart need | Library | Why |
|
|
252
|
+
|------------|---------|-----|
|
|
253
|
+
| Bar, line, area, donut, scatter, radar | **Chart.js** | Lightest CDN, built-in animation, official CDN support |
|
|
254
|
+
| Heatmap, geo/map, treemap, candlestick, graph | **ECharts** | Broadest type catalog; handles complex multi-panel layouts |
|
|
255
|
+
| Dense time-series, 10k+ points, perf-critical | **uPlot** | Smallest footprint, vanilla IIFE, zero dependencies |
|
|
256
|
+
| Polished multi-type with strong defaults | **ApexCharts** | SVG-based, real-time hooks, wide type catalog |
|
|
257
|
+
| Custom SVG/bespoke layouts, networks, projections | **D3.js** | Full control, no defaults; high authoring cost |
|
|
258
|
+
| CSS bar comparison (≤6 bars, static) | **CSS only** | No library needed; use `width: X%` + `--accent` bars |
|
|
259
|
+
|
|
260
|
+
**KPI / counter / progress widgets (no chart library needed):**
|
|
261
|
+
|
|
262
|
+
| Widget | Tool |
|
|
263
|
+
|--------|------|
|
|
264
|
+
| Number count-up | Motion `animate(0, N, onUpdate)` (see Animation section) |
|
|
265
|
+
| Progress bar | Motion `animate(el, { width: ['0%', 'N%'] })` or CSS `@starting-style` |
|
|
266
|
+
| Sparkline (mini trend line) | Chart.js mini canvas — see pattern below |
|
|
267
|
+
| Static bar comparison ≤6 bars | CSS only — see pattern below |
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
### CSS-only bar chart — no library needed
|
|
272
|
+
|
|
273
|
+
Use when the comparison is static, ≤6 bars, and no interactivity is required. Avoids a Chart.js import entirely.
|
|
274
|
+
|
|
275
|
+
```html
|
|
276
|
+
<div class="bar-chart">
|
|
277
|
+
<div class="bar-row">
|
|
278
|
+
<span class="bar-label">Q1</span>
|
|
279
|
+
<div class="bar-track">
|
|
280
|
+
<div class="bar-fill" style="--pct: 45%"><span>45%</span></div>
|
|
281
|
+
</div>
|
|
282
|
+
</div>
|
|
283
|
+
<div class="bar-row">
|
|
284
|
+
<span class="bar-label">Q2</span>
|
|
285
|
+
<div class="bar-track">
|
|
286
|
+
<div class="bar-fill" style="--pct: 72%"><span>72%</span></div>
|
|
287
|
+
</div>
|
|
288
|
+
</div>
|
|
289
|
+
<div class="bar-row">
|
|
290
|
+
<span class="bar-label">Q3</span>
|
|
291
|
+
<div class="bar-track">
|
|
292
|
+
<div class="bar-fill" style="--pct: 58%"><span>58%</span></div>
|
|
293
|
+
</div>
|
|
294
|
+
</div>
|
|
295
|
+
</div>
|
|
296
|
+
|
|
297
|
+
<style>
|
|
298
|
+
.bar-chart { display: grid; gap: var(--sp-3); }
|
|
299
|
+
.bar-row { display: grid; grid-template-columns: 5rem 1fr; align-items: center; gap: var(--sp-3); }
|
|
300
|
+
.bar-label { font-size: var(--t-small); color: var(--muted); text-align: right; }
|
|
301
|
+
.bar-track { background: var(--surface); border-radius: var(--r-sm); overflow: hidden; height: 2.2rem; }
|
|
302
|
+
.bar-fill {
|
|
303
|
+
width: var(--pct);
|
|
304
|
+
height: 100%;
|
|
305
|
+
background: var(--accent);
|
|
306
|
+
border-radius: var(--r-sm);
|
|
307
|
+
display: flex; align-items: center; padding-left: var(--sp-2);
|
|
308
|
+
font-size: var(--t-small); font-weight: 600; color: var(--bg);
|
|
309
|
+
/* entrance animation — no library */
|
|
310
|
+
animation: bar-grow 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
|
|
311
|
+
}
|
|
312
|
+
@keyframes bar-grow { from { width: 0; opacity: 0; } to { width: var(--pct); opacity: 1; } }
|
|
313
|
+
</style>
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
### Sparkline — mini trend line beside a KPI number
|
|
319
|
+
|
|
320
|
+
Use alongside a `stats`-type slide to show directional trend without a full chart. Requires Chart.js.
|
|
321
|
+
|
|
322
|
+
```html
|
|
323
|
+
<div class="kpi-block">
|
|
324
|
+
<span class="kpi-number" id="kpi">0</span>
|
|
325
|
+
<canvas id="spark" width="160" height="48"></canvas>
|
|
326
|
+
</div>
|
|
327
|
+
|
|
328
|
+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
329
|
+
<script type="module">
|
|
330
|
+
import { animate } from "https://cdn.jsdelivr.net/npm/motion@latest/+esm";
|
|
331
|
+
|
|
332
|
+
/* count-up */
|
|
333
|
+
animate(0, 2_847_000, {
|
|
334
|
+
duration: 1.4, easing: [0.22, 1, 0.36, 1],
|
|
335
|
+
onUpdate(v) { document.getElementById('kpi').textContent = Math.round(v).toLocaleString(); }
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
/* sparkline */
|
|
339
|
+
const accent = getComputedStyle(document.documentElement).getPropertyValue('--accent').trim();
|
|
340
|
+
new Chart(document.getElementById('spark'), {
|
|
341
|
+
type: 'line',
|
|
342
|
+
data: {
|
|
343
|
+
labels: Array(8).fill(''),
|
|
344
|
+
datasets: [{
|
|
345
|
+
data: [38, 45, 41, 60, 54, 71, 68, 82],
|
|
346
|
+
borderColor: accent,
|
|
347
|
+
borderWidth: 2,
|
|
348
|
+
tension: 0.4,
|
|
349
|
+
fill: false,
|
|
350
|
+
pointRadius: 0,
|
|
351
|
+
}]
|
|
352
|
+
},
|
|
353
|
+
options: {
|
|
354
|
+
responsive: false,
|
|
355
|
+
animation: false,
|
|
356
|
+
plugins: { legend: { display: false }, tooltip: { enabled: false } },
|
|
357
|
+
scales: { x: { display: false }, y: { display: false } },
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
</script>
|
|
361
|
+
|
|
362
|
+
<style>
|
|
363
|
+
.kpi-block { display: flex; align-items: center; gap: var(--sp-4); }
|
|
364
|
+
.kpi-number { font-size: var(--t-display); font-weight: 700; color: var(--accent); }
|
|
365
|
+
</style>
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
### Chart.js — Bar, line, area, donut, scatter, radar
|
|
371
|
+
**Rating:** ★★★★☆ — best default for standard chart types; easy theming via CSS variables; 11M weekly downloads
|
|
372
|
+
**CDN:** `https://cdn.jsdelivr.net/npm/chart.js`
|
|
373
|
+
**Repo:** [chartjs/Chart.js](https://github.com/chartjs/Chart.js) | 65k+ stars
|
|
374
|
+
**Use when:** Standard bar, line, area, donut, scatter, or radar chart. The CSS bar template is not enough. Real data with labels and animation.
|
|
375
|
+
|
|
376
|
+
```html
|
|
377
|
+
<canvas id="chart" width="800" height="380"></canvas>
|
|
378
|
+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
379
|
+
<script>
|
|
380
|
+
new Chart(document.getElementById('chart'), {
|
|
381
|
+
type: 'bar',
|
|
382
|
+
data: {
|
|
383
|
+
labels: ['Q1', 'Q2', 'Q3', 'Q4'],
|
|
384
|
+
datasets: [{
|
|
385
|
+
label: 'Revenue ($M)',
|
|
386
|
+
data: [12, 19, 8, 24],
|
|
387
|
+
backgroundColor: getComputedStyle(document.documentElement)
|
|
388
|
+
.getPropertyValue('--accent').trim(),
|
|
389
|
+
}]
|
|
390
|
+
},
|
|
391
|
+
options: {
|
|
392
|
+
responsive: false,
|
|
393
|
+
animation: { duration: 800, easing: 'easeOutQuart' },
|
|
394
|
+
plugins: { legend: { display: false } },
|
|
395
|
+
scales: { y: { grid: { color: getComputedStyle(document.documentElement).getPropertyValue('--border').trim() } } }
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
</script>
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
### ECharts — Heatmaps, geo, treemaps, complex dashboards
|
|
404
|
+
**Rating:** ★★★★☆ — broadest chart type catalog; right choice when Chart.js cannot produce the chart type; 2.7M weekly downloads
|
|
405
|
+
**CDN:** `https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js`
|
|
406
|
+
**Repo:** [apache/echarts](https://github.com/apache/echarts) | 61k+ stars
|
|
407
|
+
**Use when:** Heatmap, geo/map, treemap, candlestick, graph/network, calendar chart, or any multi-series complex layout that Chart.js cannot render.
|
|
408
|
+
|
|
409
|
+
```html
|
|
410
|
+
<div id="chart" class="chart-surface"></div>
|
|
411
|
+
<script src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script>
|
|
412
|
+
<script>
|
|
413
|
+
const chartEl = document.getElementById('chart');
|
|
414
|
+
const styles = getComputedStyle(document.documentElement);
|
|
415
|
+
const chart = echarts.init(chartEl, null, { renderer: 'canvas' });
|
|
416
|
+
chart.setOption({
|
|
417
|
+
backgroundColor: 'transparent',
|
|
418
|
+
tooltip: { trigger: 'item' },
|
|
419
|
+
series: [{
|
|
420
|
+
type: 'heatmap',
|
|
421
|
+
data: [/* [col, row, value] */],
|
|
422
|
+
label: { show: true },
|
|
423
|
+
emphasis: { itemStyle: { shadowBlur: 10 } }
|
|
424
|
+
}],
|
|
425
|
+
visualMap: {
|
|
426
|
+
min: 0, max: 100,
|
|
427
|
+
calculable: true,
|
|
428
|
+
inRange: {
|
|
429
|
+
color: [
|
|
430
|
+
styles.getPropertyValue('--surface').trim(),
|
|
431
|
+
styles.getPropertyValue('--accent').trim()
|
|
432
|
+
]
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
</script>
|
|
437
|
+
<style>
|
|
438
|
+
.chart-surface { width: 100%; height: min(58vh, 26rem); }
|
|
439
|
+
</style>
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
### uPlot — Dense time-series and performance-critical charts
|
|
445
|
+
**Rating:** ★★★★☆ — smallest footprint for time-series; vanilla IIFE, no dependencies; 694K weekly downloads
|
|
446
|
+
**CDN (JS):** `https://cdn.jsdelivr.net/npm/uplot/dist/uPlot.iife.min.js`
|
|
447
|
+
**CDN (CSS):** `https://cdn.jsdelivr.net/npm/uplot/dist/uPlot.min.css`
|
|
448
|
+
**Repo:** [leeoniya/uPlot](https://github.com/leeoniya/uPlot) | 9k+ stars
|
|
449
|
+
**Use when:** A time-series slide has many data points (100+) and Chart.js feels sluggish, or when minimal bundle footprint is critical.
|
|
450
|
+
|
|
451
|
+
```html
|
|
452
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uplot/dist/uPlot.min.css">
|
|
453
|
+
<div id="chart" class="chart-surface"></div>
|
|
454
|
+
<script src="https://cdn.jsdelivr.net/npm/uplot/dist/uPlot.iife.min.js"></script>
|
|
455
|
+
<script>
|
|
456
|
+
const chartEl = document.getElementById('chart');
|
|
457
|
+
const styles = getComputedStyle(document.documentElement);
|
|
458
|
+
const border = styles.getPropertyValue('--border').trim();
|
|
459
|
+
const accent = styles.getPropertyValue('--accent').trim();
|
|
460
|
+
const data = [
|
|
461
|
+
[1700000000, 1700003600, 1700007200], // timestamps (x)
|
|
462
|
+
[42, 58, 37], // series 1 (y)
|
|
463
|
+
];
|
|
464
|
+
new uPlot({
|
|
465
|
+
width: chartEl.clientWidth,
|
|
466
|
+
height: chartEl.clientHeight,
|
|
467
|
+
series: [
|
|
468
|
+
{},
|
|
469
|
+
{ label: 'Requests/s', stroke: accent, width: 2 }
|
|
470
|
+
],
|
|
471
|
+
axes: [
|
|
472
|
+
{ stroke: border, grid: { stroke: border } },
|
|
473
|
+
{ stroke: border, grid: { stroke: border } },
|
|
474
|
+
],
|
|
475
|
+
}, data, chartEl);
|
|
476
|
+
</script>
|
|
477
|
+
<style>
|
|
478
|
+
.chart-surface { width: 100%; height: min(54vh, 24rem); }
|
|
479
|
+
</style>
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
### ApexCharts — Polished multi-type charts with strong defaults
|
|
485
|
+
**Rating:** ★★★★☆ — SVG-based, clean defaults, real-time update API; good alternative to Chart.js when visual polish matters more than bundle size
|
|
486
|
+
**CDN:** `https://cdn.jsdelivr.net/npm/apexcharts`
|
|
487
|
+
**Repo:** [apexcharts/apexcharts.js](https://github.com/apexcharts/apexcharts.js) | 14k+ stars
|
|
488
|
+
**Use when:** You want professional-looking charts without custom styling effort — polished donut, area, radial bar, or mixed chart types.
|
|
489
|
+
|
|
490
|
+
```html
|
|
491
|
+
<div id="chart" class="chart-surface"></div>
|
|
492
|
+
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
|
|
493
|
+
<script>
|
|
494
|
+
const accent = getComputedStyle(document.documentElement).getPropertyValue('--accent').trim();
|
|
495
|
+
new ApexCharts(document.getElementById('chart'), {
|
|
496
|
+
chart: { type: 'area', height: '100%', background: 'transparent', animations: { speed: 800 } },
|
|
497
|
+
theme: { mode: 'dark' },
|
|
498
|
+
colors: [accent],
|
|
499
|
+
series: [{ name: 'Users', data: [31, 40, 28, 51, 42, 109, 100] }],
|
|
500
|
+
xaxis: { categories: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] },
|
|
501
|
+
dataLabels: { enabled: false },
|
|
502
|
+
stroke: { curve: 'smooth', width: 2 },
|
|
503
|
+
}).render();
|
|
504
|
+
</script>
|
|
505
|
+
<style>
|
|
506
|
+
.chart-surface { width: 100%; height: min(54vh, 24rem); }
|
|
507
|
+
</style>
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
---
|
|
511
|
+
|
|
512
|
+
### D3.js — Custom SVG, networks, projections, bespoke charts
|
|
513
|
+
**Rating:** ★★★☆☆ — maximum control, highest authoring cost; use only when chart libraries cannot express the visual honestly
|
|
514
|
+
**CDN (ESM):** `https://cdn.jsdelivr.net/npm/d3@7/+esm`
|
|
515
|
+
**Repo:** [d3/d3](https://github.com/d3/d3) | 109k+ stars
|
|
516
|
+
**Use when:** Custom SVG layouts, force networks, geographic projections, unusual annotations, or bespoke chart grammar.
|
|
517
|
+
|
|
518
|
+
```html
|
|
519
|
+
<svg id="chart" class="chart-surface" role="img" aria-label="{{chart description}}"></svg>
|
|
520
|
+
<script type="module">
|
|
521
|
+
import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
|
|
522
|
+
|
|
523
|
+
const svg = d3.select('#chart');
|
|
524
|
+
const styles = getComputedStyle(document.documentElement);
|
|
525
|
+
const accent = styles.getPropertyValue('--accent').trim();
|
|
526
|
+
const muted = styles.getPropertyValue('--muted').trim();
|
|
527
|
+
const width = svg.node().clientWidth;
|
|
528
|
+
const height = svg.node().clientHeight;
|
|
529
|
+
|
|
530
|
+
svg.attr('viewBox', `0 0 ${width} ${height}`);
|
|
531
|
+
svg.append('circle')
|
|
532
|
+
.attr('cx', width / 2)
|
|
533
|
+
.attr('cy', height / 2)
|
|
534
|
+
.attr('r', Math.min(width, height) / 4)
|
|
535
|
+
.attr('fill', accent);
|
|
536
|
+
svg.append('text')
|
|
537
|
+
.attr('x', width / 2)
|
|
538
|
+
.attr('y', height / 2)
|
|
539
|
+
.attr('text-anchor', 'middle')
|
|
540
|
+
.attr('fill', muted)
|
|
541
|
+
.text('{{label}}');
|
|
542
|
+
</script>
|
|
543
|
+
<style>
|
|
544
|
+
.chart-surface { width: 100%; height: min(54vh, 24rem); }
|
|
545
|
+
</style>
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
---
|
|
549
|
+
|
|
550
|
+
## Diagrams
|
|
551
|
+
|
|
552
|
+
### Mermaid.js — Diagrams from text
|
|
553
|
+
**Rating:** ★★★★★ — best-in-class for architecture/flow diagrams; text-based so content stays editable
|
|
554
|
+
**CDN:** `https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js`
|
|
555
|
+
**Repo:** [mermaid-js/mermaid](https://github.com/mermaid-js/mermaid) | 75k+ stars
|
|
556
|
+
**Use when:** A slide needs a flowchart, sequence diagram, Gantt, or architecture diagram.
|
|
557
|
+
|
|
558
|
+
```html
|
|
559
|
+
<div class="mermaid">
|
|
560
|
+
sequenceDiagram
|
|
561
|
+
Client->>+API Gateway: POST /checkout
|
|
562
|
+
API Gateway->>+Order Service: createOrder(cart)
|
|
563
|
+
Order Service-->>-API Gateway: orderId: 4821
|
|
564
|
+
API Gateway->>+Payment Service: charge(orderId)
|
|
565
|
+
Payment Service-->>-API Gateway: status: ok
|
|
566
|
+
API Gateway-->>-Client: 200 { orderId, status }
|
|
567
|
+
</div>
|
|
568
|
+
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
|
569
|
+
<script>
|
|
570
|
+
// theme: 'dark' | 'default' | 'neutral' | 'forest' | 'base'
|
|
571
|
+
// Pick based on --bg: dark themes → 'dark'; light themes → 'neutral' or 'default'
|
|
572
|
+
mermaid.initialize({
|
|
573
|
+
theme: 'dark',
|
|
574
|
+
startOnLoad: true,
|
|
575
|
+
flowchart: { curve: 'basis' }
|
|
576
|
+
});
|
|
577
|
+
</script>
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
## PDF Export
|
|
583
|
+
|
|
584
|
+
### Decktape — universal HTML slide → PDF exporter
|
|
585
|
+
**Rating:** ★★★★☆ — works with any HTML slide framework; no dependency on the slide code itself
|
|
586
|
+
**Repo:** [astefanutti/decktape](https://github.com/astefanutti/decktape) | 2.4k+ stars
|
|
587
|
+
**Use when:** User asks to export the deck to PDF for sharing, printing, or archiving.
|
|
588
|
+
|
|
589
|
+
```bash
|
|
590
|
+
# Serve the deck first (required — Decktape fetches from a live URL)
|
|
591
|
+
npx serve .octocode/slides/{{slideName}}
|
|
592
|
+
|
|
593
|
+
# Export all slides to PDF
|
|
594
|
+
npx decktape http://localhost:3000 deck.pdf
|
|
595
|
+
|
|
596
|
+
# Export with explicit size (matches 1280×720 stage)
|
|
597
|
+
npx decktape --size 1280x720 http://localhost:3000 deck.pdf
|
|
598
|
+
|
|
599
|
+
# Export specific slides (1-indexed)
|
|
600
|
+
npx decktape --slides 1-10 http://localhost:3000 deck.pdf
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
**How it works:** Decktape drives a headless Chromium via Puppeteer, advances each slide via keyboard, and prints each to a PDF page. It auto-detects Reveal.js, Impress, and generic HTML decks.
|
|
604
|
+
|
|
605
|
+
**Alternative — browser `@media print`:**
|
|
606
|
+
`base.css` already defines `@media print { .slide { width: 1280px; height: 720px; page-break-after: always; } }`. Open `index.html` in Chrome → File → Print → Save as PDF. Lower fidelity than Decktape (no JS, no charts) but requires no installation.
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
## Pointer & Click Feedback
|
|
611
|
+
|
|
612
|
+
A two-piece pointer-chrome layer that makes a live deck feel like a debugger console: a themed cursor that follows the speaker, plus a short spark on every click. Both libs are tiny, vanilla, MIT, and themable through the deck's existing CSS variables. **Default: OFF — opt-in only.** Enable only when the brief signals a live talk, demo, or dark/tech context (see `SKILL.md → Strong defaults → Pointer chrome` and `references/04-design.md` Step 5b).
|
|
613
|
+
|
|
614
|
+
> **Where they load:** parent `index.html` only — never per slide. Slides are iframes with separate documents, so loading these inside slides would create one cursor per slide and break the spark on slide chrome.
|
|
615
|
+
|
|
616
|
+
### tholman/cursor-effects — themable custom cursor (vanilla JS)
|
|
617
|
+
**Rating:** ★★★★☆ — battle-tested, ships ESM + UMD, already respects `prefers-reduced-motion` (matches the deck's animation policy)
|
|
618
|
+
**CDN (ESM):** `https://unpkg.com/cursor-effects@latest/dist/esm.js`
|
|
619
|
+
**Repo:** [tholman/cursor-effects](https://github.com/tholman/cursor-effects) | MIT
|
|
620
|
+
**Use when:** A live presentation or dark/tech deck wants a themed pointer (`followingDotCursor` / `trailingCursor` / `rainbowCursor`). Skip on print-first or async decks.
|
|
621
|
+
|
|
622
|
+
```html
|
|
623
|
+
<!-- in index.html, just before </body> -->
|
|
624
|
+
<script type="module">
|
|
625
|
+
import { followingDotCursor } from "https://unpkg.com/cursor-effects@latest/dist/esm.js";
|
|
626
|
+
const accent = getComputedStyle(document.documentElement).getPropertyValue('--accent').trim();
|
|
627
|
+
new followingDotCursor({ color: accent });
|
|
628
|
+
</script>
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
**Available effects:** `followingDotCursor`, `trailingCursor`, `rainbowCursor`, `bubbleCursor`, `fairyDustCursor`, `ghostCursor`, `springyEmojiCursor`, `emojiCursor`, `clockCursor`, `characterCursor`, `textFlag`. For a presentation default, prefer `followingDotCursor` (smallest visual footprint) or `trailingCursor` (slightly more presence on big-screen projectors).
|
|
632
|
+
|
|
633
|
+
### hexagoncircle/click-spark — `<click-spark>` Web Component (mouse-down feedback)
|
|
634
|
+
**Rating:** ★★★★★ — one file, no build step, themable via a single CSS custom property
|
|
635
|
+
**Source:** [hexagoncircle/click-spark/click-spark.js](https://github.com/hexagoncircle/click-spark/blob/main/click-spark.js) | MIT
|
|
636
|
+
**Use when:** Click feedback should reinforce live interactions — demos, button-led walkthroughs, anything where the speaker is clicking on stage.
|
|
637
|
+
|
|
638
|
+
```html
|
|
639
|
+
<!-- in index.html, just before </body> -->
|
|
640
|
+
<script type="module" src="js/vendor/click-spark.js"></script>
|
|
641
|
+
<click-spark style="--click-spark-color: var(--accent);"></click-spark>
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
**Notes for the slide deck context:**
|
|
645
|
+
- Wrap the spark element so it sits **above** slide iframes but **below** chrome (HUD, progress bar, counter): give it `position: fixed; inset: 0; pointer-events: none; z-index: 5;` and keep the HUD at `z-index: 50`.
|
|
646
|
+
- Click events fired inside an iframe are captured by the iframe's document, not the parent — the spark fires on parent-level chrome (overview thumbnails, navigation hints) which is the intended behaviour.
|
|
647
|
+
- For a focal-lane variant, use `--click-spark-color: var(--violet)` on a second `<click-spark>` scoped to a specific container.
|
|
648
|
+
|
|
649
|
+
### Wiring on `index.html` (recommended pattern)
|
|
650
|
+
```html
|
|
651
|
+
<!-- ── Pointer chrome (parent only) ────────────────────── -->
|
|
652
|
+
<click-spark style="--click-spark-color: var(--accent); position: fixed; inset: 0; pointer-events: none; z-index: 5;"></click-spark>
|
|
653
|
+
<script type="module">
|
|
654
|
+
import { followingDotCursor } from "https://unpkg.com/cursor-effects@latest/dist/esm.js";
|
|
655
|
+
import "https://cdn.jsdelivr.net/gh/hexagoncircle/click-spark/click-spark.js";
|
|
656
|
+
const accent = getComputedStyle(document.documentElement).getPropertyValue('--accent').trim();
|
|
657
|
+
if (!matchMedia('(pointer: coarse)').matches && !matchMedia('(prefers-reduced-motion: reduce)').matches) {
|
|
658
|
+
new followingDotCursor({ color: accent });
|
|
659
|
+
}
|
|
660
|
+
</script>
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
`pointer: coarse` short-circuit opts touch devices out cleanly. `prefers-reduced-motion` short-circuit honours OS settings even though the cursor library handles it internally too. For offline-friendly decks, vendor both files into `js/vendor/` and replace the two URLs with relative paths.
|
|
664
|
+
|
|
665
|
+
---
|
|
666
|
+
|
|
667
|
+
### Catppuccin — Warm pastel palette system, 4 flavors
|
|
668
|
+
**Rating:** ★★★☆☆ — strong palette for pastel/cozy aesthetics; too niche for general use
|
|
669
|
+
**Repo:** [catppuccin/catppuccin](https://github.com/catppuccin/catppuccin) | 18k+ stars
|
|
670
|
+
**Use when:** User wants soft, pastel-toned themes. 26 named colors × 4 flavors (Latte → Mocha).
|
|
671
|
+
```
|
|
672
|
+
Latte (light) · Frappe · Macchiato · Mocha (darkest)
|
|
673
|
+
Colors: Rosewater, Flamingo, Pink, Mauve, Red, Peach, Yellow, Green, Teal, Sapphire, Blue, Lavender + neutrals
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
**Mocha (dark) key values — map to CSS variable contract:**
|
|
677
|
+
```css
|
|
678
|
+
/* Catppuccin Mocha → theme.css */
|
|
679
|
+
:root {
|
|
680
|
+
--bg: #1e1e2e; /* Base */
|
|
681
|
+
--surface: #313244; /* Surface0 */
|
|
682
|
+
--border: #45475a; /* Surface1 */
|
|
683
|
+
--text: #cdd6f4; /* Text */
|
|
684
|
+
--muted: #6c7086; /* Overlay0 */
|
|
685
|
+
--accent: #cba6f7; /* Mauve — or swap: Sapphire #89b4fa, Peach #fab387 */
|
|
686
|
+
}
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
### Nord — Arctic minimal
|
|
690
|
+
**Rating:** ★★★☆☆ — iconic muted palette; works for understated tech decks, limited expressive range
|
|
691
|
+
**Repo:** [nordtheme/nord](https://github.com/nordtheme/nord) | 6k+ stars
|
|
692
|
+
16 colors: Polar Night (dark), Snow Storm (light text), Frost (accent blues), Aurora (semantic).
|
|
693
|
+
|
|
694
|
+
**Nord → theme.css:**
|
|
695
|
+
```css
|
|
696
|
+
:root {
|
|
697
|
+
--bg: #2e3440; /* Polar Night 0 */
|
|
698
|
+
--surface: #3b4252; /* Polar Night 1 */
|
|
699
|
+
--border: #434c5e; /* Polar Night 2 */
|
|
700
|
+
--text: #eceff4; /* Snow Storm 2 */
|
|
701
|
+
--muted: #4c566a; /* Polar Night 3 */
|
|
702
|
+
--accent: #88c0d0; /* Frost — or #81a1c1 for cooler blue */
|
|
703
|
+
}
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
### Coolors Contrast Checker — WCAG AA/AAA verification
|
|
707
|
+
**Rating:** ★★★★☆ — fast, visual, covers AA/AAA for normal and large text; free, no sign-in
|
|
708
|
+
**URL:** [coolors.co/contrast-checker](https://coolors.co/contrast-checker)
|
|
709
|
+
**Use when:** Review phase `06-review.md` requires WCAG AA (4.5:1 normal / 3:1 large text). Paste hex values for text and background, read ratio instantly.
|
|
710
|
+
|
|
711
|
+
Alternative: [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/) — same function, more detail on pass/fail thresholds.
|
|
712
|
+
|
|
713
|
+
> **Minimum targets for slides:** body text ≥ 4.5:1, heading text (≥24px bold) ≥ 3:1, UI labels ≥ 4.5:1. Dark-on-light and light-on-dark both need checking.
|
|
714
|
+
|
|
715
|
+
---
|
|
716
|
+
|
|
717
|
+
### Radix Colors — Perceptually uniform color scales
|
|
718
|
+
**Rating:** ★★★★☆ — best tool for building custom surface/muted/border steps from a base hue; perceptually uniform in dark + light
|
|
719
|
+
**Repo:** [radix-ui/colors](https://github.com/radix-ui/colors)
|
|
720
|
+
**CDN:** `https://cdn.jsdelivr.net/npm/@radix-ui/colors/dist/index.css`
|
|
721
|
+
Semantic + decorative color scales. Each hue has 12 steps (1=bg tint, 9=solid accent, 12=text). Automatic P3 wide-gamut.
|
|
722
|
+
|
|
723
|
+
**Pick a hue, map steps to the CSS variable contract:**
|
|
724
|
+
```css
|
|
725
|
+
/* Example: Slate (neutral) + Violet (accent) — dark theme */
|
|
726
|
+
@import "https://cdn.jsdelivr.net/npm/@radix-ui/colors/dist/dark/slate.css";
|
|
727
|
+
@import "https://cdn.jsdelivr.net/npm/@radix-ui/colors/dist/dark/violet.css";
|
|
728
|
+
|
|
729
|
+
:root {
|
|
730
|
+
--bg: var(--slate-1); /* darkest background */
|
|
731
|
+
--surface: var(--slate-3);
|
|
732
|
+
--border: var(--slate-6);
|
|
733
|
+
--text: var(--slate-12);
|
|
734
|
+
--muted: var(--slate-9);
|
|
735
|
+
--accent: var(--violet-9); /* solid accent — always WCAG AA on step-1 bg */
|
|
736
|
+
}
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
---
|
|
740
|
+
|
|
741
|
+
## Fonts
|
|
742
|
+
|
|
743
|
+
### Google Fonts (CDN, no install)
|
|
744
|
+
**Rating:** ★★★★★ — largest free library, zero install, reliable CDN; default first stop for every deck
|
|
745
|
+
```html
|
|
746
|
+
<!-- Dev / technical — JetBrains Mono heading + Inter body -->
|
|
747
|
+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Inter:wght@400;500&display=swap" rel="stylesheet">
|
|
748
|
+
|
|
749
|
+
<!-- Academic / editorial — Lora heading + Inter body -->
|
|
750
|
+
<link href="https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,700;1,400&family=Inter:wght@400;500&display=swap" rel="stylesheet">
|
|
751
|
+
|
|
752
|
+
<!-- Modern technical — Space Grotesk heading + JetBrains Mono body -->
|
|
753
|
+
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;700&family=JetBrains+Mono:wght@400&display=swap" rel="stylesheet">
|
|
754
|
+
|
|
755
|
+
<!-- Warm creative — Instrument Serif heading + Sora body -->
|
|
756
|
+
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Sora:wght@400;500&display=swap" rel="stylesheet">
|
|
757
|
+
|
|
758
|
+
<!-- Premium / keynote — Playfair Display heading + Inter body -->
|
|
759
|
+
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Inter:wght@400;500&display=swap" rel="stylesheet">
|
|
760
|
+
|
|
761
|
+
<!-- Dark bold — Bricolage Grotesque heading + DM Sans body -->
|
|
762
|
+
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@400;700&family=DM+Sans:wght@400;500&display=swap" rel="stylesheet">
|
|
763
|
+
```
|
|
764
|
+
These are starting points — research new pairings via Font Joy or Google Fonts explorer for each deck.
|
|
765
|
+
|
|
766
|
+
### Fontshare (alternative CDN, open-source)
|
|
767
|
+
**Rating:** ★★★★☆ — fewer fonts but higher design quality than Google Fonts average; good for distinctive display faces
|
|
768
|
+
```html
|
|
769
|
+
<link href="https://api.fontshare.com/v2/css?f[]=satoshi@700,400&f[]=cabinet-grotesk@700&display=swap" rel="stylesheet">
|
|
770
|
+
```
|
|
771
|
+
Notable: Satoshi, Cabinet Grotesk, Clash Display, General Sans, Switzer.
|
|
772
|
+
|
|
773
|
+
### Font Joy — ML-powered pairing discovery
|
|
774
|
+
**Rating:** ★★★☆☆ — useful research tool, not a CDN; run it during Phase 4 when standard pairings feel wrong
|
|
775
|
+
**URL:** [fontjoy.com](https://fontjoy.com/)
|
|
776
|
+
**Use when:** Browsing Google Fonts manually isn't surfacing the right pair. Font Joy generates pairings with a "generate" button — lock the heading or body font and regenerate the other. Different job than Fontshare/Google Fonts browsing.
|
|
777
|
+
|
|
778
|
+
### Type-Scale — Modular type scale calculator
|
|
779
|
+
**Rating:** ★★★★☆ — instant visual preview of any base size + ratio; generates the full CSS scale
|
|
780
|
+
**URL:** [type-scale.com](https://type-scale.com/)
|
|
781
|
+
**Use when:** Choosing heading/body/caption sizes for a new deck; pick a ratio and base, then copy the resulting `font-size` values into `base.css`.
|
|
782
|
+
|
|
783
|
+
**Recommended scales for 1280×720 slides:**
|
|
784
|
+
| Body (base) | Ratio | H1 result | Notes |
|
|
785
|
+
|-------------|-------|-----------|-------|
|
|
786
|
+
| 24px | 1.333 (Perfect Fourth) | ~57px | Clean, technical |
|
|
787
|
+
| 28px | 1.25 (Major Third) | ~55px | Balanced, editorial |
|
|
788
|
+
| 26px | 1.414 (√2) | ~74px | Bold, keynote-style |
|
|
789
|
+
|
|
790
|
+
Plug into CSS variables: `--fs-body: 26px; --fs-h2: 37px; --fs-h1: 52px; --fs-label: 18px;`
|
|
791
|
+
|
|
792
|
+
---
|
|
793
|
+
|
|
794
|
+
## Design Research (agent tool guide)
|
|
795
|
+
|
|
796
|
+
When the user wants a custom aesthetic, the agent SHOULD actively research beyond these defaults:
|
|
797
|
+
|
|
798
|
+
```
|
|
799
|
+
GitHub/Octocode repository search — search "presentation design CSS" or "slide deck aesthetic"
|
|
800
|
+
GitHub/Octocode code search — find SKILL.md files with slide design systems
|
|
801
|
+
Web search — search "best CSS presentation aesthetics {{current year}}" or "beautiful HTML deck examples"
|
|
802
|
+
Web fetch/browser — read codepen.io/trending, dribbble, awwwards for visual inspiration
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
The agent may deviate from the 5 named themes in `design-system.md` if:
|
|
806
|
+
- The user describes a specific aesthetic not covered
|
|
807
|
+
- Research reveals a clearly better match
|
|
808
|
+
- Custom brand colors are provided
|
|
809
|
+
|
|
810
|
+
When deviating: define a `/* Custom: <name> */` block at the top of `theme.css` and document the creative choices.
|
|
811
|
+
|
|
812
|
+
---
|
|
813
|
+
|
|
814
|
+
## Quick selection
|
|
815
|
+
|
|
816
|
+
| Need | Use |
|
|
817
|
+
|------|-----|
|
|
818
|
+
| Rich markdown content in slides | marked.js |
|
|
819
|
+
| Staggered bullets/cards (modern browsers) | CSS `sibling-index()` + `@starting-style` |
|
|
820
|
+
| Staggered bullets/cards (broad support) | Motion `stagger()` |
|
|
821
|
+
| Number counters, progress fills | Motion `animate(0, N)` |
|
|
822
|
+
| Sequenced multi-element choreography | Motion `timeline()` |
|
|
823
|
+
| SVG path animation or complex choreography | GSAP |
|
|
824
|
+
| Slide-to-slide transition (with animation) | View Transitions API |
|
|
825
|
+
| Real syntax highlighting | highlight.js |
|
|
826
|
+
| Bar / line / area / donut / scatter / radar | Chart.js |
|
|
827
|
+
| Heatmap / geo / treemap / complex dashboard | ECharts |
|
|
828
|
+
| Dense time-series (100+ points, perf-critical) | uPlot |
|
|
829
|
+
| Polished multi-type charts with strong defaults | ApexCharts |
|
|
830
|
+
| Custom SVG / network / bespoke layout | D3.js |
|
|
831
|
+
| Flowcharts, sequence diagrams, architecture | Mermaid.js |
|
|
832
|
+
| Soft pastel palette | Catppuccin |
|
|
833
|
+
| Arctic minimal palette | Nord |
|
|
834
|
+
| Perceptual color scales | Radix Colors |
|
|
835
|
+
| Font pairing discovery | Font Joy |
|
|
836
|
+
| Type scale (base + ratio → CSS sizes) | type-scale.com |
|
|
837
|
+
| WCAG contrast check (AA/AAA) | Coolors contrast checker |
|
|
838
|
+
| Export deck to PDF | `npx decktape http://localhost:port deck.pdf` |
|
|
839
|
+
| Themed live-presentation cursor | tholman/cursor-effects (`followingDotCursor`) |
|
|
840
|
+
| Mouse-down click spark | hexagoncircle/click-spark (`<click-spark>`) |
|