@hypersocial/decks-cli 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -4
- package/package.json +1 -1
- package/skills/hyperdecks/SKILL.md +297 -13
- package/skills/hyperdecks/chat.md +49 -0
- package/src/check.mjs +110 -240
- package/src/checkRules.mjs +558 -0
- package/src/commands.mjs +200 -10
- package/src/files.mjs +35 -0
- package/src/guide.mjs +55 -0
- package/src/hosted.mjs +74 -0
- package/src/importer.mjs +1 -1
- package/src/init.mjs +605 -0
- package/src/layouts.mjs +71 -0
- package/src/narrate.mjs +4 -13
- package/src/ops.mjs +101 -7
- package/src/runtime.mjs +73 -14
- package/src/scaffold.mjs +23 -22
- package/src/source.mjs +69 -0
- package/src/voice.mjs +11 -0
- package/templates/first-deck/character.json +26 -0
- package/templates/first-deck/self.json +26 -0
- package/templates/layouts/_deck.html +102 -0
- package/templates/layouts/chart.html +39 -0
- package/templates/layouts/closer.html +28 -0
- package/templates/layouts/compare.html +33 -0
- package/templates/layouts/features.html +35 -0
- package/templates/layouts/hero.html +35 -0
- package/templates/layouts/number.html +29 -0
- package/templates/layouts/product.html +57 -0
- package/templates/layouts/quote.html +31 -0
- package/templates/layouts/team.html +37 -0
- package/templates/layouts/timeline.html +39 -0
- package/templates/narrated-deck.html +57 -11
- package/templates/script.md +11 -3
package/README.md
CHANGED
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
Command-line client for Hypersocial Decks live analytics and share management.
|
|
4
4
|
|
|
5
|
-
Most users should
|
|
5
|
+
Most users should start with the friendlier package name:
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npx hyperdecks
|
|
8
|
+
npx hyperdecks init
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
`init` signs you in, installs the skill into your agents, sets up a voice,
|
|
12
|
+
builds and narrates a three-slide hello deck and prints its link. Re-running it
|
|
13
|
+
resumes where it stopped; `--json --yes` is the agent form.
|
|
14
|
+
|
|
11
15
|
This package targets production by default:
|
|
12
16
|
|
|
13
17
|
```bash
|
|
@@ -108,7 +112,7 @@ credits per second, refunded if fal fails to produce the clip.
|
|
|
108
112
|
## Narration
|
|
109
113
|
|
|
110
114
|
`narrate` turns a deck's `script.md` into voiced clips in your own voice, word-timed
|
|
111
|
-
captions
|
|
115
|
+
captions and a deck manifest (the player's live head lip-syncs from the audio). Rendering runs on the Hyperdecks
|
|
112
116
|
backend with the platform's ElevenLabs key; the CLI only sends the script and polls.
|
|
113
117
|
Each line is cached by a hash of its spoken text and voice, so after an edit only the
|
|
114
118
|
slides whose words changed re-render.
|
|
@@ -128,7 +132,7 @@ normalize: hyper desk=hyperdecks
|
|
|
128
132
|
---
|
|
129
133
|
|
|
130
134
|
## hello
|
|
131
|
-
hold: 1.
|
|
135
|
+
hold: 1.5
|
|
132
136
|
presenter: wave
|
|
133
137
|
|
|
134
138
|
Hi, I'm Selçuk's mini avatar. [wave] This is Hyperdecks. [mood: excited]
|
|
@@ -137,6 +141,7 @@ Hi, I'm Selçuk's mini avatar. [wave] This is Hyperdecks. [mood: excited]
|
|
|
137
141
|
- `## <slide-id>` is the slide's `<section id>` in `index.html`. Text before the first
|
|
138
142
|
heading is notes for people and is ignored.
|
|
139
143
|
- `hold`, `presenter` and `voice` lines directly under a heading are slide options.
|
|
144
|
+
`hold` is the pause in seconds after the line before the next slide (0.4 by default).
|
|
140
145
|
- Sentences are the caption units, 4–85 characters each.
|
|
141
146
|
- Stage tags (`[wave]`, `[mood: x]`, `[emote: x]`, `[reveal: x]`, `[play: x]`,
|
|
142
147
|
`[pause: s]`, `[custom: name …]`) are not spoken. Each becomes a cue at the start
|
package/package.json
CHANGED
|
@@ -11,6 +11,32 @@ Hyperdecks is the CLI and MCP surface for Hypersocial Decks live analytics,
|
|
|
11
11
|
recipient links, and deck activity. Treat real recipient activity, live deck
|
|
12
12
|
stats, customer-facing links, and "what happened" questions as production work.
|
|
13
13
|
|
|
14
|
+
## First run
|
|
15
|
+
|
|
16
|
+
When `hyperdecks whoami` says not authenticated, or `hyperdecks voice list`
|
|
17
|
+
shows no ready voice, run the first-run command instead of working around it:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx hyperdecks init --json --yes [--voice dash] [--name "<name>" --about "<one line>" --ask "<the ask>"]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
It signs in, installs this skill, scaffolds a three-slide hello deck from the
|
|
24
|
+
three answers, narrates it, releases one QA link and prints one JSON object
|
|
25
|
+
(`status`, `steps`, `slug`, `deckDir`, `shareUrl`, `next`). Re-running it
|
|
26
|
+
resumes where it stopped. Signed out, it first opens the sign-in page in the
|
|
27
|
+
user's browser and waits up to 3 minutes: tell them to finish signing in there
|
|
28
|
+
(a new account can be made on that page) before you run it, or have them run
|
|
29
|
+
`npx hyperdecks login` first. Inside a git repository it puts the deck in
|
|
30
|
+
`~/hyperdecks` rather than committing into that repository; `--dir` picks the
|
|
31
|
+
folder. Relay every step whose `status` is `needs-human` to the user, word for
|
|
32
|
+
word, and wait for them:
|
|
33
|
+
|
|
34
|
+
- deck: it needs `--name`, `--about` and `--ask`; ask the user, do not invent them;
|
|
35
|
+
- voice: cloning needs them to type their consent in a terminal (`hyperdecks
|
|
36
|
+
voice clone <file> --name <name>`), or to agree to the statement before you
|
|
37
|
+
call `clone_voice`. Never type or confirm consent for them. `--voice dash`
|
|
38
|
+
lets D.A.S.H., a character voice, present instead.
|
|
39
|
+
|
|
14
40
|
## Target Selection
|
|
15
41
|
|
|
16
42
|
- Prefer production for real-world questions and actions. The published CLI is
|
|
@@ -53,13 +79,18 @@ Hyperdecks server; use the CLI where you have a shell and the tool otherwise.
|
|
|
53
79
|
|
|
54
80
|
| Step | CLI | MCP tool |
|
|
55
81
|
|---|---|---|
|
|
56
|
-
| Scaffold | `hyperdecks deck new <slug> "<title>" --narrated` | `new_deck` |
|
|
82
|
+
| Scaffold | `hyperdecks deck new <slug> "<title>" --narrated [--layouts hero,product,number,closer]` | `new_deck` (`layouts`) |
|
|
57
83
|
| Images | `hyperdecks gen-image "<prompt>" --slug <slug>` | `generate_image` |
|
|
58
84
|
| Video clips | `hyperdecks gen-video "<prompt>" --slug <slug>` | `generate_video` |
|
|
85
|
+
| Product screenshot | `hyperdecks screenshot <url> --slug <slug>` | `capture_url` |
|
|
86
|
+
| Chart from numbers | `hyperdecks chart <spec.json> --slug <slug>` | `render_chart` |
|
|
87
|
+
| Icon set | `hyperdecks icons <subject...> --style "<style>" --slug <slug>` | `generate_icon_set` |
|
|
88
|
+
| Outside review (required before release) | `hyperdecks review <slug> --script decks/<slug>/script.md` | `review_deck` |
|
|
59
89
|
| Your voice (once) | `hyperdecks voice clone <file...> --name <name>` | `clone_voice` |
|
|
60
90
|
| Narrate | `hyperdecks narrate decks/<slug>` | `narrate_deck` |
|
|
61
91
|
| Check | `hyperdecks check decks/<slug>` | `check_deck` |
|
|
62
92
|
| Ship | `hyperdecks release decks/<slug> --to "<name>" --email <e>` | `release_deck` |
|
|
93
|
+
| Share-link poster | `hyperdecks poster <slug>` | `generate_deck_poster` |
|
|
63
94
|
| Import only | `hyperdecks import <file> --slug <slug>` | `import_deck_from_url` |
|
|
64
95
|
| One more link | `hyperdecks share new <slug> "<name>"` | `create_share` |
|
|
65
96
|
| Who watched | `hyperdecks deck stats <slug>` | `deck_stats` |
|
|
@@ -76,18 +107,31 @@ Write `decks/<slug>/evidence.md` as you go: one row per fact with the slide, the
|
|
|
76
107
|
claim, the source (file path, thread, doc title) and its date. Never put a
|
|
77
108
|
number on a slide that has no row.
|
|
78
109
|
|
|
110
|
+
<!-- topic: format -->
|
|
79
111
|
### 2. Scaffold
|
|
80
112
|
|
|
81
113
|
```bash
|
|
82
|
-
hyperdecks deck new <slug> "<title>" --narrated
|
|
114
|
+
hyperdecks deck new <slug> "<title>" --narrated --layouts hero,features,product,number,closer
|
|
115
|
+
# one slide per layout, from the layout library
|
|
116
|
+
hyperdecks deck new <slug> "<title>" --narrated [--presenter-style stage|bubble|glass|corner]
|
|
117
|
+
# the plain eight-slide outline
|
|
83
118
|
```
|
|
84
119
|
|
|
120
|
+
Both write `decks/<slug>/` and register a draft you own. Prefer `--layouts`:
|
|
121
|
+
pick the layouts from the story (see **Design** below), in order; repeat one
|
|
122
|
+
for more of the same (`number,number` gives slides `number` and `number-2`).
|
|
123
|
+
|
|
85
124
|
Files, all in `decks/<slug>/`:
|
|
86
125
|
|
|
87
|
-
- `index.html`:
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
126
|
+
- `index.html`: the `<section class="slide" id="…">` slides and the hosted
|
|
127
|
+
player script. With `--layouts` each slide is a layout's section (ids like
|
|
128
|
+
`features`, inner ids like `features-f1`) and its CSS sits once in `<head>`;
|
|
129
|
+
without, eight outline slides (hello, problem, why-now, idea, how, proof, ask,
|
|
130
|
+
bye). Keep, cut or add slides; keep the contract below.
|
|
131
|
+
- `script.md`: the narration, one `## <slide-id>` block per slide. With
|
|
132
|
+
`--layouts` each block starts as the layout's starter line with its `[go]` /
|
|
133
|
+
`[look]` cues already pointing at the slide's elements: rewrite the words,
|
|
134
|
+
keep the cues at the words they belong to.
|
|
91
135
|
- `evidence.md`: the sources table. Private: release never uploads it.
|
|
92
136
|
|
|
93
137
|
The deck contract (`check` enforces each line):
|
|
@@ -100,13 +144,186 @@ The deck contract (`check` enforces each line):
|
|
|
100
144
|
- A title (first `<h1>`/`<h2>`) over 28 characters carries
|
|
101
145
|
`data-title-mobile="<shorter>"`. The scaffold puts one on every title.
|
|
102
146
|
- Each slide keeps its `<div class="narration-slot"></div>` (where the
|
|
103
|
-
presenter's face and
|
|
147
|
+
presenter's face and captions sit; the player glides the presenter there,
|
|
148
|
+
so put slots on different sides across slides, as the scaffold's
|
|
149
|
+
`.slot-left` does); the first slide has `data-intro`.
|
|
104
150
|
- The player script stays
|
|
105
151
|
`<script type="module" src="https://decks.hypersocial.ai/player/v1/player.js" data-manifest="…">`.
|
|
106
152
|
`narrate` fills `data-manifest`; do not edit it by hand.
|
|
107
153
|
- Local images and files sit inside the deck folder and are referenced
|
|
108
154
|
relatively (`img/chart.png`). Hosted images (`gen-image` URLs) are fine too.
|
|
109
155
|
|
|
156
|
+
<!-- topic: presenter -->
|
|
157
|
+
#### Which presenter style
|
|
158
|
+
|
|
159
|
+
Set the deck's on the player tag (`data-presenter-style="stage"`) or in
|
|
160
|
+
script.md's front matter (`presenterStyle: stage`); override one slide with
|
|
161
|
+
`data-presenter-style` on its `<section>` or `presenter-style: corner` under
|
|
162
|
+
its `##` heading.
|
|
163
|
+
|
|
164
|
+
| Style | Pick it when |
|
|
165
|
+
|---|---|
|
|
166
|
+
| `stage` (default with the live head) | the presenter carries the deck: a founder pitch, a walkthrough. Large unframed head, lower-third captions; leave ~500 px beside the text for it |
|
|
167
|
+
| `bubble` (default otherwise) | a light aside; the face in a circle with a speech bubble |
|
|
168
|
+
| `glass` | dark or busy slides: head and captions on one frosted panel |
|
|
169
|
+
| `corner` | the slide is the point (a product shot, a chart, a demo): small head bottom-right, subtitles along the bottom |
|
|
170
|
+
|
|
171
|
+
Below 650 px stage and glass become corner on their own. Run
|
|
172
|
+
`hyperdecks check <deck> --layout` to be warned about any slide whose presenter
|
|
173
|
+
would cover its title.
|
|
174
|
+
|
|
175
|
+
<!-- topic: transitions -->
|
|
176
|
+
#### Transitions
|
|
177
|
+
|
|
178
|
+
Every slide enters with `drift` unless it says otherwise. Use another only
|
|
179
|
+
where the slide's job matches its "use for"; never hand-write slide-change
|
|
180
|
+
animation in the deck's own JS (it fights the player's timing).
|
|
181
|
+
|
|
182
|
+
| Transition | Use for | What it does |
|
|
183
|
+
|---|---|---|
|
|
184
|
+
| `drift` (default) | most slides | the old slide drifts out, the new one in, its parts arriving title first |
|
|
185
|
+
| `cut` | a punchline, a fast beat | instant |
|
|
186
|
+
| `push` | the next step in a sequence | the new slide slides over; the old one sinks back and darkens |
|
|
187
|
+
| `wipe` | a new section | a band in the deck's second colour, then one in ink, sweeps across and leaves the new slide |
|
|
188
|
+
| `zoom <selector>` | going into the detail of one row, bar or card | the new slide opens out of that element on the slide before |
|
|
189
|
+
| `morph` (carry over) | a number or title on both slides | the element travels into its new place and size |
|
|
190
|
+
| `fly` | the deck's one big reveal | the presenter flies across and the new slide appears behind it |
|
|
191
|
+
|
|
192
|
+
Set the deck's in script.md's front matter (`transition: drift`) or on the
|
|
193
|
+
player tag (`data-transition`); a slide's under its `##` heading
|
|
194
|
+
(`transition: push`) or as `data-transition` on its `<section>`, which wins.
|
|
195
|
+
A slide's transition is how it enters; going back plays it in reverse.
|
|
196
|
+
A `transition:` in script.md reaches the player through the manifest, so it
|
|
197
|
+
takes effect after `narrate` (release runs it; nothing re-renders);
|
|
198
|
+
`data-transition` in index.html takes effect at once. Zoom
|
|
199
|
+
names its target on the slide before: `transition: zoom #dash-row`. Morph
|
|
200
|
+
pairs elements by name: put `data-morph="saved"` on the element on both
|
|
201
|
+
slides. Reduced motion turns every one into a short crossfade, and the
|
|
202
|
+
narration never waits for a transition.
|
|
203
|
+
|
|
204
|
+
`check` fails an unknown name, a `zoom` with no selector or one that matches
|
|
205
|
+
nothing on the slide before, a `morph` with no `data-morph` name on both
|
|
206
|
+
slides, and a second `fly`. It warns when a deck uses more than two kinds
|
|
207
|
+
besides its default: pick one or two and keep them for the same job.
|
|
208
|
+
|
|
209
|
+
Viewers can poke the live head: a click or tap makes it react (an "oof", a
|
|
210
|
+
flinch) and a drag pulls it a little before it springs back, without pausing
|
|
211
|
+
the narration.
|
|
212
|
+
|
|
213
|
+
<!-- topic: design -->
|
|
214
|
+
### Design: make it look good
|
|
215
|
+
|
|
216
|
+
A narrated deck is only as convincing as it looks. Design before you write the
|
|
217
|
+
narration, and check the result at both widths (step 6).
|
|
218
|
+
|
|
219
|
+
**One idea per slide.** The title states the idea as a sentence a listener
|
|
220
|
+
could repeat ("Narration renders in two minutes", not "Speed"). Everything
|
|
221
|
+
else on the slide supports that sentence; if it needs a second idea, it is a
|
|
222
|
+
second slide. Five to nine slides carry a three-minute deck.
|
|
223
|
+
|
|
224
|
+
**Type scale.** The layout shell defines it in `:root`; use the tokens, not
|
|
225
|
+
new sizes:
|
|
226
|
+
|
|
227
|
+
| Token | Stage (1600×900) | Phone | For |
|
|
228
|
+
|---|---|---|---|
|
|
229
|
+
| `--t-display` | 128px | 54px | one hero line or a closing word, at most once per slide |
|
|
230
|
+
| `--t-title` | 84px | 38px | the slide's title |
|
|
231
|
+
| `--t-sub` | 56px | 28px | a title beside a visual, a number's label |
|
|
232
|
+
| `--t-lead` | 30px | 17px | one supporting sentence |
|
|
233
|
+
| `--t-body` | 24px | 15px | list items, card text |
|
|
234
|
+
| `--t-label` | 17px | 12px | kickers, sources, captions (mono, uppercase) |
|
|
235
|
+
|
|
236
|
+
Nothing on a slide below 17px at stage size (a screenshot's frame chrome aside). A title over 28 characters needs
|
|
237
|
+
`data-title-mobile`; write the short version as a real sentence.
|
|
238
|
+
|
|
239
|
+
**Colour and contrast.** Three colours do the work: `--ink`, `--paper` and one
|
|
240
|
+
`--accent` (a second, `--accent-2`, only for a chart's other series, an
|
|
241
|
+
illustration or a placeholder face). Text is ink on paper or accent, or paper on ink: never accent
|
|
242
|
+
on paper, never grey on a colour. Alternate slide grounds (`on-accent`,
|
|
243
|
+
plain, `on-ink`) so the slide changes read, and keep every number, source and
|
|
244
|
+
label at full contrast. Change the palette and fonts once, in `:root`; every
|
|
245
|
+
layout reads them.
|
|
246
|
+
|
|
247
|
+
**Pick the layout from what the slide says.** Each layout's file in
|
|
248
|
+
`templates/layouts/` opens with its slot side, presenter and the cues that
|
|
249
|
+
suit it.
|
|
250
|
+
|
|
251
|
+
| Layout | Use it for | Presenter, moves |
|
|
252
|
+
|---|---|---|
|
|
253
|
+
| `hero` | the opening, a section opener; the presenter is the visual, no `.art` unless it shows the real subject | stage, bottom-right; `[wave]`, `[look: h1]` |
|
|
254
|
+
| `number` | one number with its source: proof, traction, a delta | stage; `[look: #<id>-figure]` as it is said |
|
|
255
|
+
| `product` | a screenshot in a browser frame (`.frame.phone` for a phone shot) with the point beside it | stage; `[look: #<id>-frame]`, `[reveal: #<id>-callout]` |
|
|
256
|
+
| `quote` | a customer or user in their own words, quoted exactly | stage, bottom-left; `[look: #<id>-quote]` |
|
|
257
|
+
| `compare` | before/after, them/us, three parallel lines each | stage; `[look: #<id>-before]`, `[go: #<id>-after]` |
|
|
258
|
+
| `timeline` | four milestones: history, a roadmap, a process | stage; `[go: #<id>-m1]` … `m4`, `[go: slot]` |
|
|
259
|
+
| `features` | three things it does, an icon each | stage; `[go: #<id>-f1]` … `f3`, `[go: slot]` |
|
|
260
|
+
| `chart` | real numbers drawn with `chart`, the takeaway beside | stage; `[look: #<id>-chart]`, `[reveal: #<id>-takeaway]` |
|
|
261
|
+
| `team` | up to four people, faces only with permission | stage; `[go: #<id>-p1]` … `p4`, `[go: slot]` |
|
|
262
|
+
| `closer` | the end: one line and one action (a command, a link) | stage, bottom-left; `[go: #<id>-cta]`, `[go: slot]`, `[wave]` |
|
|
263
|
+
|
|
264
|
+
Presenter style follows the deck (step 2, *Which presenter style*): `stage`
|
|
265
|
+
when the presenter carries the story, which is what the layouts are drawn for
|
|
266
|
+
(they keep the slot's corner clear); `corner` on a slide where a big
|
|
267
|
+
visual is the point and moves are not needed; `glass` on a dark or busy
|
|
268
|
+
picture. Two layouts (`quote`, `closer`) sit left; put a `slot-left` on others
|
|
269
|
+
where there is room so slide changes move the presenter.
|
|
270
|
+
|
|
271
|
+
**Visuals: real first, generated second.**
|
|
272
|
+
|
|
273
|
+
- Product: `hyperdecks screenshot <url>` (`capture_url`) into `product`'s
|
|
274
|
+
`.shot`; crop to what the narration talks about. Never mock a UI that
|
|
275
|
+
exists.
|
|
276
|
+
- Numbers: `hyperdecks chart <spec.json>` (`render_chart`) in the deck's
|
|
277
|
+
palette into `chart`'s `.chart`, the source in `data-note` and evidence.md.
|
|
278
|
+
Never a generated picture of a chart.
|
|
279
|
+
- **No decorative imagery.** Generic illustration (stages, speech bubbles,
|
|
280
|
+
floating shapes, abstract "tech" art, clip-art metaphors) makes a deck look
|
|
281
|
+
cheap. A visual earns its place only if it shows something real from the
|
|
282
|
+
story: the product, the data, a concrete situation or object. When in doubt,
|
|
283
|
+
leave it out: one big statement in type beats a picture of nothing. The
|
|
284
|
+
presenter is the hero of the opening slide; don't put art behind it.
|
|
285
|
+
- Icons: only when they label something the viewer must tell apart at a
|
|
286
|
+
glance. Three short statements set large usually beat three icon cards.
|
|
287
|
+
- Images: `gen-image` (`generate_image`) only for a concrete subject the
|
|
288
|
+
deck is about (a product in use, a place, a real object), never a metaphor.
|
|
289
|
+
One style per deck, described the same way every time (subject, medium,
|
|
290
|
+
palette hexes, "no text"). `--model nano-banana-2.1` when the image must
|
|
291
|
+
carry legible type.
|
|
292
|
+
- Video: `gen-video` for a short loop behind a hero or a product moment, with
|
|
293
|
+
`[play: video]` at its word; never needed for a deck to work.
|
|
294
|
+
- People: real photos only with permission; initials otherwise.
|
|
295
|
+
|
|
296
|
+
**Motion.** The presenter's moves are the deck's motion; keep everything else
|
|
297
|
+
still.
|
|
298
|
+
|
|
299
|
+
- `[go]` when the narration walks through items (cards, milestones, people,
|
|
300
|
+
the action on the closer): one `go` per item at the word that starts it,
|
|
301
|
+
then `[go: slot]` before the slide ends. Never more than one `go` per
|
|
302
|
+
sentence; never a `go` on a slide in `corner` style.
|
|
303
|
+
- `[look]` for a glance: the title as it is read, a number as it is said, a
|
|
304
|
+
screenshot as the narration turns to it.
|
|
305
|
+
- `[reveal]` for the one detail that should not be read before it is said (a
|
|
306
|
+
takeaway, a callout); not for every line.
|
|
307
|
+
- `[wave]` once at the start and once at the end.
|
|
308
|
+
- No CSS animation on slides beyond `.reveal`; the player animates the slide
|
|
309
|
+
change.
|
|
310
|
+
|
|
311
|
+
**Review before release (required).** After `check` passes and the deck is
|
|
312
|
+
imported, run `hyperdecks review <slug> --script decks/<slug>/script.md`
|
|
313
|
+
(`review_deck`, then poll `check_review_job`). Act on every finding:
|
|
314
|
+
|
|
315
|
+
- `fix`: change the slide or the script, re-import (or `release --qa`), and
|
|
316
|
+
review again until no `fix` is left. Do not release with a `fix` open.
|
|
317
|
+
- `consider`: apply it when it serves the slide's one idea; otherwise note in
|
|
318
|
+
your reply to the user why you left it.
|
|
319
|
+
- A finding you disagree with (a deliberate choice, a misread screenshot):
|
|
320
|
+
say so to the user with the reason instead of silently ignoring it.
|
|
321
|
+
|
|
322
|
+
If review cannot run (no credits, the service is down), say so to the user and
|
|
323
|
+
do the step 6 screenshot pass yourself as the reviewer: the same desktop and
|
|
324
|
+
phone screenshots, the same `fix` bar.
|
|
325
|
+
|
|
326
|
+
<!-- topic: script -->
|
|
110
327
|
### 3. Write slides and script
|
|
111
328
|
|
|
112
329
|
- One idea per slide; the title states it.
|
|
@@ -115,9 +332,32 @@ The deck contract (`check` enforces each line):
|
|
|
115
332
|
- Narration: short phrases, each sentence one caption of 4 to 85 characters
|
|
116
333
|
(two lines in the bubble). Aim for 2.5 to 3 minutes in all; `maxTotalSeconds`
|
|
117
334
|
in the front matter is the cap check uses (180 in the scaffold).
|
|
118
|
-
- Holds:
|
|
335
|
+
- Holds: 0.4 s by default. Give a slide `hold: 1.5` when the viewer needs time to read a number, a chart or a reveal, and `hold: 2` on interactive slides.
|
|
119
336
|
- Cues: `[reveal: #id]` reveals `.reveal#id` at the word before it; also
|
|
120
337
|
`[wave]`, `[mood: excited]`, `[pause: 0.5]`, `[custom: name]`.
|
|
338
|
+
- Moves, to point at part of a slide: `[go: <selector>]` flies the presenter
|
|
339
|
+
beside that element (the side with room) until the next `go`, the slide's
|
|
340
|
+
end, or `[go: slot]`; `[look: <selector>]` turns the head toward it without
|
|
341
|
+
moving. One selector each, matched inside that slide; check fails one that
|
|
342
|
+
matches nothing. Use `go` when the narration walks through a list or chart,
|
|
343
|
+
`look` for a glance at a title or number. Not in `corner` style. The best
|
|
344
|
+
showcase is a slide of stacked cards, one point each, with a `go` to each
|
|
345
|
+
card at the word that starts it: `Write [go: #step-1] the slides, write
|
|
346
|
+
[go: #step-2] what you'd say`. Give each card an id.
|
|
347
|
+
|
|
348
|
+
| Cue | Effect |
|
|
349
|
+
|---|---|
|
|
350
|
+
| `[wave]` | the presenter greets (the live head's joy emote) |
|
|
351
|
+
| `[mood: excited]` / `[emote: name]` | the head's mood or emote |
|
|
352
|
+
| `[reveal: #id]` | adds `is-revealed` to `#id` |
|
|
353
|
+
| `[pause: 0.5]` | a beat of silence (≤ 5 s) |
|
|
354
|
+
| `[play: video]` / `[pause: video]` | play or pause the slide's video |
|
|
355
|
+
| `[go: .list]` / `[go: slot]` | fly beside `.list` / back to the slot |
|
|
356
|
+
| `[look: h2]` | look at the title |
|
|
357
|
+
| `[custom: name]` | only the slide's controller sees it |
|
|
358
|
+
- `voice: dash` narrates with D.A.S.H.'s own robot voice, a synthetic
|
|
359
|
+
character voice (not a clone of anyone) any account may use, for decks that
|
|
360
|
+
D.A.S.H. presents. It works once the deployment sets `CHARACTER_VOICE_DASH`.
|
|
121
361
|
- No `voice:` in the front matter means the user's first ready voice. If
|
|
122
362
|
`hyperdecks voice list` shows none, ask the user to record one and run
|
|
123
363
|
`voice clone` (it asks them for consent; never clone anyone else's voice).
|
|
@@ -133,12 +373,18 @@ A slide fails when the transcript does not match the script: read the error,
|
|
|
133
373
|
reword the sentence (spell numbers and names the way they are said, or add a
|
|
134
374
|
`normalize:` entry), and narrate again; only that slide re-renders.
|
|
135
375
|
|
|
376
|
+
<!-- topic: check -->
|
|
136
377
|
### 5. Check
|
|
137
378
|
|
|
138
379
|
```bash
|
|
139
|
-
hyperdecks check decks/<slug> [--forbid "Other Co,codename"]
|
|
380
|
+
hyperdecks check decks/<slug> [--forbid "Other Co,codename"] [--layout]
|
|
140
381
|
```
|
|
141
382
|
|
|
383
|
+
`--layout` lays each slide out in Chromium (needs `hyperdecks preview setup`).
|
|
384
|
+
At the stage size it warns, without failing, when a slide's presenter would
|
|
385
|
+
overlap its title. On a 390×844 phone (the share player's 374×736 slide card)
|
|
386
|
+
it fails any slide whose content overflows: the player never scrolls a slide.
|
|
387
|
+
|
|
142
388
|
`--forbid` lists phrases that must not reach this audience (another customer,
|
|
143
389
|
an internal codename). Messages and what to do:
|
|
144
390
|
|
|
@@ -152,25 +398,48 @@ an internal codename). Messages and what to do:
|
|
|
152
398
|
| `narration runs …s, over the …s cap` | shorten the script |
|
|
153
399
|
| `clip <id>: audio …` / `clip <id>: timeline …` | narrate again; the asset is missing or wrong |
|
|
154
400
|
| `clip <id>: caption N runs` | narrate that slide again (`--slide <id>`) |
|
|
155
|
-
| `clip <id>:
|
|
401
|
+
| `clip <id>: captions do not cover the clip text` | narrate that slide again |
|
|
156
402
|
| `clip <id>: caption N is … characters` | split or join sentences in that block |
|
|
157
403
|
| `local reference does not resolve` / `leaves the deck folder` | move the file into the deck folder or fix the path |
|
|
158
404
|
| `player script must be` / `no player script` | restore the player/v1 script tag |
|
|
159
405
|
| `the player script has no data-manifest` | run `narrate` |
|
|
406
|
+
| `no loading state` | copy the template's `<style data-hd-loading>` block (and the preload lines above it) into `<head>`; set `--hd-ground` / `--hd-ground-ink` to the first slide's colours |
|
|
160
407
|
| `forbidden phrase` | remove it from the page, script or narration |
|
|
161
408
|
| `slide <id>: needs a data-note` | add the source |
|
|
162
409
|
| `slide <id>: title … needs a data-title-mobile` | add a shorter title |
|
|
410
|
+
| `… presenter style "…" is not one of` | use stage, bubble, glass or corner |
|
|
411
|
+
| `script.md line N: [go: …] matches nothing in slide <id>` | fix the selector, or add the element to that slide |
|
|
412
|
+
| `… transition "…" is not one of` | use drift, cut, push, wipe, zoom `<selector>`, morph or fly |
|
|
413
|
+
| `slide <id>: zoom target "…" matches nothing on the slide before it` | point the zoom at an element of the previous slide, or give that element the id |
|
|
414
|
+
| `slide <id>: morph needs an element with the same data-morph` | put `data-morph="<name>"` on the carried element on both slides, or use drift |
|
|
415
|
+
| `script.md says transition "…" but the manifest has "…"` | run `narrate` (no audio re-renders), or release, which runs it |
|
|
416
|
+
| `fly is for the deck's one big moment` | keep `fly` on one slide; use drift or push on the others |
|
|
417
|
+
| ⚠ `N kinds of transition besides the default` | use one or two kinds, each for its own job |
|
|
418
|
+
| `slide <id>: its content runs …px past the slide on a 390×844 phone` | trim that slide on phones: smaller type, fewer items, or hide decoration in its `@media (max-width: 650px)` rules (an `#id` rule outranks them; restate it there) |
|
|
419
|
+
| ⚠ `slide <id>: the … presenter would overlap the title` | move that slide's `.narration-slot`, pad the text away from it, or use `corner` |
|
|
163
420
|
|
|
164
421
|
### 6. Look at it, at both widths
|
|
165
422
|
|
|
166
423
|
Serve the folder (`npx serve decks/<slug>` or `python3 -m http.server -d decks/<slug>`)
|
|
167
424
|
and screenshot it with Playwright at 1440×900 and 390×844, every slide
|
|
168
|
-
(`#scene=<id>`). Look at both: nothing clipped, the
|
|
169
|
-
mobile titles in use. Fix and repeat until both read well.
|
|
425
|
+
(`#scene=<id>`). Look at both: nothing clipped, the presenter and its captions
|
|
426
|
+
clear of the text, the mobile titles in use. Fix and repeat until both read well.
|
|
427
|
+
|
|
428
|
+
Then the required review (see **Design**, *Review before release*): once the
|
|
429
|
+
deck is imported, `hyperdecks review <slug> --script decks/<slug>/script.md`
|
|
430
|
+
(`review_deck`, then `check_review_job`) has GPT-6 Luna look at every slide of
|
|
431
|
+
the deck's QA link on desktop and phone and list each problem as `fix` or
|
|
432
|
+
`consider` with a concrete suggestion. Release only when no `fix` is left.
|
|
433
|
+
|
|
434
|
+
Pick image models by job: `gen-image` defaults to GPT Image 2.5; `--model
|
|
435
|
+
nano-banana-2.1` is stronger on typography and photoreal scenes. `gen-video`
|
|
436
|
+
defaults to MiniMax H3 Max (`--model kling-v3` is the fallback). Use `chart` for
|
|
437
|
+
real numbers instead of a generated picture of a chart, and `icons` with the
|
|
438
|
+
deck's palette for a set that matches.
|
|
170
439
|
|
|
171
440
|
### 7. Release
|
|
172
441
|
|
|
173
|
-
Commit the deck folder first: release refuses uncommitted changes so every
|
|
442
|
+
Only after `check` passes and the last review has no `fix` finding. Commit the deck folder first: release refuses uncommitted changes so every
|
|
174
443
|
release matches a commit.
|
|
175
444
|
|
|
176
445
|
```bash
|
|
@@ -187,6 +456,11 @@ references must be tracked by git (an ignored `*.mp4` is refused). Then it impor
|
|
|
187
456
|
(each `--email` pairs with the `--to` before it). Confirm recipients with the
|
|
188
457
|
user before sending real links; send the links yourself only if asked.
|
|
189
458
|
|
|
459
|
+
Release also makes the deck's share-link poster (its first slide with a Play
|
|
460
|
+
badge, shown when a link is pasted into Slack, iMessage or email, and on the
|
|
461
|
+
dashboard card) within a minute. When the first slide changed look, check it
|
|
462
|
+
with `hyperdecks poster <slug>` (`generate_deck_poster`), which prints its URL.
|
|
463
|
+
|
|
190
464
|
### 8. Report who watched
|
|
191
465
|
|
|
192
466
|
```bash
|
|
@@ -197,6 +471,16 @@ hyperdecks activity --deck <slug> --limit 10
|
|
|
197
471
|
Tell the user who opened it, how far they got and whether the narration
|
|
198
472
|
finished. QA links never count.
|
|
199
473
|
|
|
474
|
+
### Hosted source (chat agents and the connector)
|
|
475
|
+
|
|
476
|
+
A deck can also live on Hyperdecks with no folder: chat agents build it through
|
|
477
|
+
the hosted MCP (`deck_guide`, `new_deck`, `get_deck_source`, `write_deck_source`,
|
|
478
|
+
`upload_deck_asset`, `check_deck`, `release_deck`; see `chat.md`). Move between
|
|
479
|
+
the two with `hyperdecks source pull <slug> [dir]` (the hosted draft into a
|
|
480
|
+
folder) and `hyperdecks source push <slug> [dir]` (a folder's files back to the
|
|
481
|
+
draft), `hyperdecks asset add <slug> <file|url>` for an image, `hyperdecks guide
|
|
482
|
+
[topic]` for these sections, and `--hosted` on `deck new`, `check` and `release`.
|
|
483
|
+
|
|
200
484
|
## Safety
|
|
201
485
|
|
|
202
486
|
- For read-only inspection, run commands directly and summarize the important
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Hyperdecks from a chat app (hosted MCP)
|
|
2
|
+
|
|
3
|
+
You are building a narrated deck through the Hyperdecks connector: no terminal,
|
|
4
|
+
no git, no folder. The deck's files (`index.html`, `script.md`, `evidence.md`)
|
|
5
|
+
live on Hyperdecks as a draft; you read and edit them with tools, and nothing
|
|
6
|
+
reaches a recipient until `release_deck`. Topics: call `deck_guide` with
|
|
7
|
+
`format`, `script`, `design`, `layouts`, `presenter`, `transitions` or `check`
|
|
8
|
+
before the step that needs it.
|
|
9
|
+
|
|
10
|
+
## The loop
|
|
11
|
+
|
|
12
|
+
1. `deck_guide` (this page), then `deck_guide { topic: "layouts" }` to pick slides.
|
|
13
|
+
2. `new_deck { slug, title, layouts }`: registers your draft and returns the
|
|
14
|
+
full text of every file plus a `previewUrl` (the draft, untracked).
|
|
15
|
+
3. Images: `generate_image`, `render_chart`, `capture_url`, or
|
|
16
|
+
`upload_deck_asset` for a picture the user gave you (a URL, or a file they
|
|
17
|
+
uploaded). Each returns a hosted URL: put that URL in the HTML. A hosted deck
|
|
18
|
+
has no folder, so a relative path like `img/a.png` is an error.
|
|
19
|
+
4. `write_deck_source` to change a file: `edits: [{ find, replace }]` with
|
|
20
|
+
exact text that occurs once (copy it from `get_deck_source`), or `content`
|
|
21
|
+
to replace the file. Pass `baseRev` (the `rev` you last read) so a
|
|
22
|
+
concurrent edit fails instead of being overwritten.
|
|
23
|
+
5. `check_deck { slug }` until it passes (the narration errors clear in step 6).
|
|
24
|
+
6. `narrate_deck { slug }` with no `script` narrates the stored `script.md`;
|
|
25
|
+
poll `check_narration_job` until `done`. The draft's player tag then has its
|
|
26
|
+
`data-manifest`. No voice of their own yet? Pass `voice: "dash"`.
|
|
27
|
+
7. `check_deck { slug }` again, then `review_deck { slug, draft: true }` and
|
|
28
|
+
`check_review_job`: it shoots desktop and 390×844 phone frames, which is how
|
|
29
|
+
you catch a slide that overflows a phone (the hosted check cannot measure
|
|
30
|
+
layout).
|
|
31
|
+
8. `release_deck { slug, qa: true }` gives the user a QA link to watch first.
|
|
32
|
+
`release_deck { slug, recipients: [{ recipient, email }] }` makes one
|
|
33
|
+
tracked link each. Release creates live links: confirm the recipients with
|
|
34
|
+
the user before you call it.
|
|
35
|
+
9. Later: `list_shares`, `deck_stats`, `activity_overview`.
|
|
36
|
+
|
|
37
|
+
## Rules that matter
|
|
38
|
+
|
|
39
|
+
- Every slide is `<section class="slide" id="…" data-note="<source of its facts>">`,
|
|
40
|
+
in the same order as the `## <id>` blocks in `script.md`.
|
|
41
|
+
- Keep the player script tag and the `<style data-hd-loading>` block the
|
|
42
|
+
scaffold wrote; never write `data-manifest` yourself.
|
|
43
|
+
- Edit the draft freely: recipients keep seeing the last release until you call
|
|
44
|
+
`release_deck` again. A release is refused when the check fails, when
|
|
45
|
+
narration is stale (narrate again first), or when the draft changed after
|
|
46
|
+
the check.
|
|
47
|
+
- Files are capped at 800 KB each: use hosted image URLs, never inline base64.
|
|
48
|
+
- Facts come from the user's material; put the source of each in `evidence.md`
|
|
49
|
+
and the slide's `data-note`.
|