@navipartner/demo-video 0.7.0 → 0.7.2
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 +13 -9
- package/bin/demo-video.mjs +98 -17
- package/bin/init.d.mts +2 -0
- package/bin/init.mjs +17 -6
- package/dist/{adapter-CDOXdUZI.d.ts → adapter-DxZmb-QU.d.ts} +47 -8
- package/dist/{chunk-D7UYGNSF.js → chunk-XMOGUZJU.js} +211 -50
- package/dist/index.d.ts +119 -20
- package/dist/index.js +1 -1
- package/dist/runner/index.d.ts +1 -1
- package/dist/runner/index.js +753 -217
- package/package.json +1 -1
- package/skills/np-demo-video/SKILL.md +242 -230
- package/skills/np-demo-video/look.md +182 -82
- package/skills/np-demo-video/reference.md +89 -30
|
@@ -1,103 +1,166 @@
|
|
|
1
1
|
# The look
|
|
2
2
|
|
|
3
|
-
Every NaviPartner demo video should look and feel the same
|
|
3
|
+
Every NaviPartner demo video should look and feel the same. They are made
|
|
4
|
+
for serious buyers: operators and owners choosing a system for their shops,
|
|
5
|
+
restaurants and venues. They watch to understand, so a video is brisk where
|
|
6
|
+
nothing is happening and gives information the time it needs. In order of
|
|
7
|
+
importance:
|
|
4
8
|
|
|
5
|
-
1. **The product tells the story; text
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
3. **
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
1. **The product tells the story; text frames it.** Words live on their own
|
|
10
|
+
cards *between* the chapters, never over the live app. A card may hold a
|
|
11
|
+
snapshot of what its chapter achieves beside the words: the app, captured,
|
|
12
|
+
not a mock-up.
|
|
13
|
+
2. **No dead time.** Setup happens behind cards, only values that show
|
|
14
|
+
something are typed, and every beat is there so the viewer sees
|
|
15
|
+
something. Never rushed: results and cards stay up long enough to read.
|
|
16
|
+
3. **Purposeful camera.** Every page opens wide, on the whole window. The
|
|
17
|
+
camera pushes in only where the action would be too small to read, and
|
|
18
|
+
then only after the viewer has seen where they are. It moves between
|
|
19
|
+
shots, never during the action, never chases the cursor, and there are no
|
|
20
|
+
hard cuts inside a chapter.
|
|
21
|
+
4. **Soft, light, branded.** A pale brand-tinted background, a floating app
|
|
22
|
+
window, big serif statements, and the brand colour used boldly.
|
|
23
|
+
5. **Believable data.** The most real-looking records the e2e mocks have.
|
|
24
|
+
Never "Test item 1" on screen when the story can type a better value.
|
|
16
25
|
|
|
17
|
-
##
|
|
26
|
+
## Two kinds of video
|
|
18
27
|
|
|
19
|
-
A
|
|
20
|
-
|
|
28
|
+
A story says which it is (`"kind"`, default `showcase`). The beats are the
|
|
29
|
+
same in both; the shape differs.
|
|
30
|
+
|
|
31
|
+
| | Showcase | Feature clip |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| Shows | the app's main journey, from start to the moment of value (the primary story is always one) | one feature: "see the new split-bill button" |
|
|
34
|
+
| For | the website, a sales meeting, a buyer comparing systems | release news, a LinkedIn post, a customer update |
|
|
35
|
+
| Length | 45–90 s | 15–30 s |
|
|
36
|
+
| Shape | open card, 2–4 chapters of 10–20 s, a payoff, end card | open card naming the feature, one chapter, end card |
|
|
37
|
+
| Open and end cards | up to 3.5 s | up to 2.5 s |
|
|
38
|
+
|
|
39
|
+
`check` keeps a feature clip to one chapter and a showcase to four, and
|
|
40
|
+
prints how long the story will run.
|
|
41
|
+
|
|
42
|
+
### Showcase
|
|
21
43
|
|
|
22
44
|
```
|
|
23
|
-
open card
|
|
24
|
-
┌
|
|
25
|
-
│ demo 10–
|
|
26
|
-
└ payoff 3–
|
|
45
|
+
open card ≤ 3.5 s logo + what the product does for the buyer + a snapshot of the result
|
|
46
|
+
┌ chapter card ~2–4 s "Pay *by card*." + the benefit in one line, beside a snapshot of the result
|
|
47
|
+
│ demo 10–20 s the app doing exactly that, ending on the result
|
|
48
|
+
└ payoff ~3–4 s optional: the result just shown, as a fact
|
|
27
49
|
… 2–4 chapters …
|
|
28
|
-
|
|
29
|
-
|
|
50
|
+
end card ≤ 3.5 s logo + the promise, or the next step
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Feature clip
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
open card ≤ 2.5 s logo + "New: …" + a snapshot of the feature
|
|
57
|
+
┌ chapter card ~2–3 s the feature's statement + what it does for the customer
|
|
58
|
+
│ demo 8–15 s straight to the feature; all setup behind the card
|
|
59
|
+
end card ≤ 2.5 s logo + where it is available
|
|
30
60
|
```
|
|
31
61
|
|
|
32
|
-
-
|
|
33
|
-
the
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
62
|
+
- **The first seconds carry brand and product.** The open card shows the
|
|
63
|
+
logo and a snapshot of the result (a showcase) or of the feature (a clip),
|
|
64
|
+
so a viewer who stops after two seconds has seen both.
|
|
65
|
+
- Setup the viewer needn't watch (a language dialog, a cookie banner,
|
|
66
|
+
opening a tab) happens behind the card before it, never on screen.
|
|
67
|
+
- Length follows the chapters: don't pad, don't cram.
|
|
38
68
|
|
|
39
|
-
##
|
|
69
|
+
## Cards
|
|
40
70
|
|
|
41
71
|
| Card | Text | Look |
|
|
42
72
|
|---|---|---|
|
|
43
|
-
| Open | eyebrow `Introducing`
|
|
44
|
-
|
|
|
45
|
-
| Payoff | the result just shown
|
|
46
|
-
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
73
|
+
| Open | eyebrow (`Introducing`, or `New` for a clip) · brand logo · one line on what it does for the buyer · a snapshot of the result | pale |
|
|
74
|
+
| Chapter | the statement and the benefit (below), beside a snapshot of the result when there is one | pale and brand colour alternate, chapter by chapter |
|
|
75
|
+
| Payoff | the result just shown; the sub-line states the fact the app showed: "64,50 kr. by card." | full-bleed brand colour |
|
|
76
|
+
| End | logo + the product's promise, or the next step: "Book a demo at navipartner.com." | pale, held still |
|
|
77
|
+
|
|
78
|
+
A **chapter card** has two lines of words, and no eyebrow: chapter numbers
|
|
79
|
+
and topic labels don't help in a film this short.
|
|
80
|
+
|
|
81
|
+
1. **Statement:** ≤ 7 words naming what the chapter shows, in its own verb,
|
|
82
|
+
sentence case, ending with a full stop, **one word or phrase in italic**
|
|
83
|
+
(the action or its result): "Pay *by card*."
|
|
84
|
+
2. **Benefit:** one sub-line, ideally ≤ 12 words, saying what it does for
|
|
85
|
+
the customer as something the chapter then shows. An outcome, not a
|
|
86
|
+
feature name, and a specific value when the app shows one: "Tap, insert
|
|
87
|
+
or phone: the terminal takes it all."
|
|
88
|
+
|
|
89
|
+
**Text and UI on one card.** A card shows a snapshot of the result beside
|
|
90
|
+
the words when there is something visual to show: the finished pass, the
|
|
91
|
+
receipt, the "Paid" screen. The words go left, the snapshot right, in the
|
|
92
|
+
same rounded window and soft shadow as the app. It is the app, captured by
|
|
93
|
+
`check`, never a mock-up. A chapter that ends on a toast or a number stays
|
|
94
|
+
text only, centred.
|
|
95
|
+
|
|
96
|
+
- **Typeface:** the brand's fonts. For NaviPartner: **Merriweather** for
|
|
97
|
+
statements (its italic is the emphasis word), **Work Sans** for eyebrows
|
|
98
|
+
and sub-lines. At 1080p: statements 116 px (92 px beside a snapshot),
|
|
99
|
+
sub-lines 40 px (36 px), the open card's eyebrow 28 px spaced capitals,
|
|
100
|
+
logo 720 px wide.
|
|
101
|
+
- **Tone:** plain, confident, present tense, for a professional audience.
|
|
102
|
+
No exclamation marks except inside a quoted customer line. No "seamless",
|
|
103
|
+
"revolutionary" or "effortless".
|
|
104
|
+
- **Truth:** every fact on a card is visible in the video (the price shown,
|
|
105
|
+
the receipt that appears), checked by an `expectText`. No invented
|
|
106
|
+
durations or customer statistics.
|
|
62
107
|
- **Never on a card:** testids, barcodes, internal names or any other code.
|
|
63
|
-
- **Reading time:** a card stays up
|
|
108
|
+
- **Reading time:** a card stays up 0.5 s plus ~0.25 s a word of its
|
|
109
|
+
statement and ~0.2 s a word of its sub-line (an eyebrow's words 0.12 s),
|
|
110
|
+
at least 1.6 s. The open and end cards stay at most 3.5 s in a showcase
|
|
111
|
+
and 2.5 s in a clip, unless the story asks for more. Setup behind a card
|
|
112
|
+
that takes longer holds it up: `check` says so.
|
|
64
113
|
|
|
65
114
|
## Transitions
|
|
66
115
|
|
|
67
|
-
- **Blur dissolve** everywhere.
|
|
68
|
-
~500 ms
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
blur in, so two headings never show at once.
|
|
116
|
+
- **Blur dissolve** everywhere. A card's words blur in from ~12 px to sharp
|
|
117
|
+
over ~500 ms, one after the other: statement, snapshot, sub-line. A
|
|
118
|
+
card hands over to the app by fading out (~600 ms) while the app sharpens
|
|
119
|
+
behind it.
|
|
120
|
+
- Card to card: the old words blur out first (~240 ms), then the new ones
|
|
121
|
+
blur in, so two statements never show at once.
|
|
74
122
|
- No slides, wipes, spins, or zoom-punch transitions.
|
|
75
123
|
|
|
76
124
|
## Camera
|
|
77
125
|
|
|
78
|
-
- **Wide
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
126
|
+
- **Wide is the default.** The app floats in the middle of the frame at
|
|
127
|
+
~90 % width, with a small corner radius, a soft long shadow and no browser
|
|
128
|
+
chrome. A wide shot whose text reads (16 px or more on the 1080p frame)
|
|
129
|
+
needs no push-in.
|
|
130
|
+
- **A page never opens zoomed.** Every chapter opens wide when its card
|
|
131
|
+
dissolves, and so does every new screen. When a push-in is needed, the
|
|
132
|
+
whole window is seen first (the engine holds it ~0.8 s), then the camera
|
|
133
|
+
moves in.
|
|
134
|
+
- **Push in only where it's needed:** where the text is too small to read
|
|
135
|
+
wide (`check` asks for it), or to read a result. Frame the control *and*
|
|
136
|
+
what it changes, and no tighter than it takes to read (scale 1.3–1.8,
|
|
137
|
+
never past 2: tighter loses the context and softens the picture). A live
|
|
138
|
+
preview that the action changes belongs in the shot.
|
|
83
139
|
- **Hold steady through the action.** The clicks happen inside the shot; the
|
|
84
140
|
camera doesn't move with them. At most two push-ins a chapter.
|
|
85
141
|
- **Show the result.** When an action changes something outside the shot (a
|
|
86
142
|
row added at the top, a new screen), pull out right after it. A push-in
|
|
87
143
|
that shows a button pressed and nothing happening is the worst shot.
|
|
88
|
-
- **
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
-
|
|
144
|
+
- **End on the result.** The last shot of a chapter frames what it achieved
|
|
145
|
+
(the pass with its wallet badge, the receipt), held long enough to read,
|
|
146
|
+
then the card covers it.
|
|
147
|
+
- **Each move eases in and out** (engine: 900 ms,
|
|
148
|
+
`cubic-bezier(0.65, 0, 0.35, 1)`), then settles 150 ms before anything
|
|
149
|
+
happens.
|
|
92
150
|
|
|
93
151
|
## Cursor
|
|
94
152
|
|
|
95
|
-
- A small standard arrow, used
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
- **A beat around every click:** it rests on the control (
|
|
153
|
+
- A small standard arrow, used for the clicks and drags a person would make.
|
|
154
|
+
It glides on a gentle curve, easing in and out (400–800 ms by distance),
|
|
155
|
+
and doesn't pulse, ripple or jerk.
|
|
156
|
+
- **A beat around every click:** it rests on the control (160 ms, its hover
|
|
99
157
|
state shows), presses (110 ms, the pressed state shows), and the app's
|
|
100
|
-
reaction plays
|
|
158
|
+
reaction plays: 450 ms, then until the app has settled (a toast after a
|
|
159
|
+
save, a preview redrawn), up to a second more.
|
|
160
|
+
- **Every control the viewer sees used gets the cursor**, a colour picker or
|
|
161
|
+
an upload as much as a button: an adapter action names its control, and
|
|
162
|
+
the cursor goes there and rests before it acts.
|
|
163
|
+
- Typing runs at ~45 ms a character.
|
|
101
164
|
- Between actions it rests where it doesn't cover what the viewer should
|
|
102
165
|
read.
|
|
103
166
|
- If the UI animates by itself (an order total updating, a status changing),
|
|
@@ -108,10 +171,10 @@ end card 3–5 s logo + tagline, still
|
|
|
108
171
|
- **Background:** white tinted ~5–8 % with the brand's primary colour, with
|
|
109
172
|
one or two very soft radial blooms. Never a busy wallpaper, and never
|
|
110
173
|
dark mode.
|
|
111
|
-
- **Brand colour:**
|
|
112
|
-
colour. The brand's logo
|
|
113
|
-
|
|
114
|
-
|
|
174
|
+
- **Brand colour:** payoffs and every other chapter card are full-bleed
|
|
175
|
+
brand colour. The brand's logo is on the open and end cards. The app
|
|
176
|
+
itself is shown in its tenant's branding (their kiosk looks like their
|
|
177
|
+
kiosk).
|
|
115
178
|
- **Brand:** NaviPartner's (below). A pitch draft (linear.md) swaps in a
|
|
116
179
|
customer's researched logo, colours and fonts, following the same roles.
|
|
117
180
|
|
|
@@ -122,23 +185,23 @@ These values are taken from navipartner.com and the official logo
|
|
|
122
185
|
|
|
123
186
|
| Role | Value |
|
|
124
187
|
|---|---|
|
|
125
|
-
| Primary:
|
|
126
|
-
| Navy: logo wordmark,
|
|
188
|
+
| Primary: brand cards, italic emphasis word, the open card's eyebrow, background tint | `#1F5494` |
|
|
189
|
+
| Navy: logo wordmark, statements on pale cards | `#123A7E` |
|
|
127
190
|
| Light blue: the logo's "NAVI" mark, soft background bloom, sparingly | `#729FD3` |
|
|
128
|
-
| Text: sub-lines
|
|
191
|
+
| Text: sub-lines | `#232323`; muted `#707070` |
|
|
129
192
|
| Pale background base | `#F8F8F8` / `#FFFFFF` |
|
|
130
193
|
| Heading font | Merriweather 400/700, italic for the emphasis word |
|
|
131
194
|
| Body font | Work Sans 400/600/700 |
|
|
132
195
|
| Logo | official two-colour SVG: `#729FD3` mark + `#123A7E` wordmark, on pale backgrounds only. On `#1F5494`, use it all white. |
|
|
133
196
|
|
|
134
197
|
A NaviPartner pale card is `#F8F8F8` with a `#1F5494` tint at ~5 % and one
|
|
135
|
-
`#729FD3` bloom, with the
|
|
136
|
-
brand card is full-bleed `#1F5494` with the
|
|
137
|
-
the sub-line in white Work Sans at
|
|
198
|
+
`#729FD3` bloom, with the statement in navy and the italic word in primary.
|
|
199
|
+
A brand card is full-bleed `#1F5494` with the statement in white
|
|
200
|
+
Merriweather and the sub-line in white Work Sans at ~85 % opacity.
|
|
138
201
|
|
|
139
202
|
Keep the two brand layers apart. The cards and background use the video's
|
|
140
203
|
brand (NaviPartner, or the customer's). What's inside the app window is the
|
|
141
|
-
|
|
204
|
+
app's tenant branding from the adapter.
|
|
142
205
|
|
|
143
206
|
## Sound
|
|
144
207
|
|
|
@@ -152,5 +215,42 @@ the whole story.
|
|
|
152
215
|
This is used for the website and the LinkedIn feed.
|
|
153
216
|
- **Portrait kiosk apps** (food order 1080×1920) float centred in the 16:9
|
|
154
217
|
frame, and the camera pushes in the same way.
|
|
155
|
-
- 1:1 / 9:16 cuts for SoMe come later.
|
|
156
|
-
1080×1080 area
|
|
218
|
+
- 1:1 / 9:16 cuts for SoMe come later. Text-only cards keep their words
|
|
219
|
+
inside the central 1080×1080 area; a card with a snapshot will stack it
|
|
220
|
+
under the words there.
|
|
221
|
+
|
|
222
|
+
## Where these rules come from
|
|
223
|
+
|
|
224
|
+
Researched October 2026. Apple-style ads composite their UI in afterwards;
|
|
225
|
+
we film the real app, so we borrow their discipline (one message per shot,
|
|
226
|
+
the product as the hero), not their technique.
|
|
227
|
+
|
|
228
|
+
- **Showcase length and pace.** Wistia's data on 1.1 million videos: product
|
|
229
|
+
and explainer videos keep over half their viewers up to a few minutes,
|
|
230
|
+
with the steepest drop after two; put what matters early. B2B launch
|
|
231
|
+
videos run 30–60 s, explainers 60–90 s. A buyer can follow a slower video
|
|
232
|
+
that carries real information, so cut dead time, not information.
|
|
233
|
+
([Wistia](https://wistia.com/blog/optimal-video-length),
|
|
234
|
+
[Flowjam](https://www.flowjam.com/blog/b2b-saas-launch-video))
|
|
235
|
+
- **Feature clips and the first seconds.** In feeds, attention is decided in
|
|
236
|
+
the first 2–3 seconds; brand in the first 5 (Google's ABCD) or 2
|
|
237
|
+
(LinkedIn: a visible logo lifts click-through 17%), and lead with the
|
|
238
|
+
product in use, not only a logo (Meta). Short ads do best around 15–30 s.
|
|
239
|
+
([Think with Google](https://thinkwithgoogle.com/_qs/documents/8472/ABCD_Complete_V7b_HR_1.pdf),
|
|
240
|
+
[LinkedIn via Storykit](https://storykit.io/blog/linkedin-video-ads-best-practices),
|
|
241
|
+
[Meta via Cinerads](https://www.cinerads.com/blog/meta-ads-video-creative-best-practices))
|
|
242
|
+
- **Silent by design.** About 80 % of LinkedIn video and 85 % of Facebook
|
|
243
|
+
video is watched without sound, so the cards carry every claim.
|
|
244
|
+
- **What goes on a card.** One idea per scene with one supporting line; the
|
|
245
|
+
benefit a viewer grasps fastest beats the feature's name; specific numbers
|
|
246
|
+
beat vague claims; short labels hold viewers.
|
|
247
|
+
([Nemo](https://www.nemovideo.com/blog/kinetic-typography-product-ads),
|
|
248
|
+
[Arcade, 14 million demo sessions](https://www.arcade.software/post/2026-arcade-benchmarks))
|
|
249
|
+
- **Reading time.** Netflix allows at most 20 characters a second, text up
|
|
250
|
+
0.83–7 s; the BBC works to about 0.3 s a word. Our cards are read faster
|
|
251
|
+
than subtitles (0.25 s a statement word, 0.2 s a sub-line word): the viewer
|
|
252
|
+
isn't also following speech.
|
|
253
|
+
([Netflix](https://backlothelp.netflix.com/hc/en-us/articles/219375728))
|
|
254
|
+
- **Camera.** Screen Studio's "Focused" motion settles quickly so UI can be
|
|
255
|
+
read; that is the model: quick moves, then stillness.
|
|
256
|
+
([Screen Studio](https://screen.studio/guide/animations))
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Reference: adapter, story and
|
|
1
|
+
# Reference: adapter, story, brand and check
|
|
2
2
|
|
|
3
3
|
## Adapter (`<app>/demo/demo.config.ts`)
|
|
4
4
|
|
|
@@ -7,9 +7,10 @@ the mocks booted the app), `viewport` (default 1728×972; a portrait kiosk is
|
|
|
7
7
|
scaled to fit) and `setup(page, { brand })`, which runs the app's e2e mocks
|
|
8
8
|
**unchanged** and lays the brand over the response that carries it.
|
|
9
9
|
Optional: `actions` (app steps such as a barcode scan), `idleTimeoutSeconds`,
|
|
10
|
-
`locale`, `timezone`, and `brandNeeds`: the `config` keys and asset slots
|
|
11
|
-
description (where it shows, what shape) or
|
|
12
|
-
brand without a need that isn't optional fails
|
|
10
|
+
`locale`, `timezone`, and `brandNeeds`: the `config` keys and asset slots
|
|
11
|
+
`setup` uses, each a description (where it shows, what shape) or
|
|
12
|
+
`{ what, optional: true }`. A brand without a need that isn't optional fails
|
|
13
|
+
`check`.
|
|
13
14
|
|
|
14
15
|
```ts
|
|
15
16
|
import { defineDemo, overlayResponse } from "@navipartner/demo-video";
|
|
@@ -42,30 +43,88 @@ export default defineDemo({
|
|
|
42
43
|
|
|
43
44
|
## Story (`<app>/demo/stories/<name>.json`)
|
|
44
45
|
|
|
45
|
-
`app`, `description`, optional `
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
46
|
+
`app`, `description`, optional `kind` (`showcase`, the default, or
|
|
47
|
+
`feature`), `primary` (a showcase), `title`, `closing`, `steps`.
|
|
48
|
+
|
|
49
|
+
| Step | Fields |
|
|
50
|
+
|---|---|
|
|
51
|
+
| `click` | `target`, `nth`, `zoom` (push in on it first, 1.3–2), `behindCard` |
|
|
52
|
+
| `type` | `target`, `nth`, `text`, `perCharMs` (≥ 40, default 45), `replace` (clear the field first; without it the text goes at its end), `behindCard` |
|
|
53
|
+
| `press` | `key`, `behindCard` |
|
|
54
|
+
| `zoom` | `target`, `nth`, `scale` (1.3–2) |
|
|
55
|
+
| `frame` | `targets` (2–4 testids or `{ target, nth }`), `maxScale` (1.3–2, default 1.8) |
|
|
56
|
+
| `zoomOut` | `park` (rest the cursor too) |
|
|
57
|
+
| `park` | rests the cursor in empty space |
|
|
58
|
+
| `waitFor` | `target`, `nth`, `hidden`, `timeout` (s), `behindCard` |
|
|
59
|
+
| `expectText` | `target`, `nth`, `text`, `contains`, `timeout` (s) |
|
|
60
|
+
| `hold` | `seconds` (≤ 6) |
|
|
61
|
+
| `card` | see Cards |
|
|
62
|
+
|
|
63
|
+
Plus the adapter's actions as `{ "do": "<action>", …params }`. `target` is a
|
|
64
|
+
testid or any Playwright selector (`role=button[name=/pay/i]`); `nth` picks
|
|
65
|
+
among matches (-1 = last). Clicks wait until their target stops moving.
|
|
66
|
+
|
|
67
|
+
**Cards** (`card`, `title`, `closing`): `heading` (≤ 7 words, `*word*` in
|
|
68
|
+
italic, once), `sub` (≤ 16 words; a chapter card's benefit ≤ 10), `logo`,
|
|
69
|
+
`style` (`pale` | `brand`; chapter cards without one alternate, pale first),
|
|
70
|
+
`seconds` (a minimum: a card stays up long enough to read), and on `title`
|
|
71
|
+
and `closing` only, `eyebrow` (≤ 4 words). `title` may `show` an element
|
|
72
|
+
too: a snapshot of it as it last looks in the story, beside the logo. A `card` step may `show` an element
|
|
73
|
+
(a testid or `{ target, nth }`): a snapshot of it beside the words, as it
|
|
74
|
+
last looks in the chapter after the card (on a payoff, as the card comes up).
|
|
75
|
+
Cards that follow each other hand over directly. A number on a card must be
|
|
76
|
+
checked by an `expectText` in the story.
|
|
77
|
+
|
|
78
|
+
**Behind a card:** `behindCard` steps right after a card (or at the very
|
|
79
|
+
start, behind the title card) run while the card covers the app, with no
|
|
80
|
+
cursor and no camera. `click`, `type`, `press`, `waitFor` and adapter
|
|
81
|
+
actions take it; never a push-in, since every chapter opens wide. A card stays up until what's behind
|
|
82
|
+
it is done: `check` names a card whose setup outlasts its reading time.
|
|
83
|
+
|
|
84
|
+
**Camera rules** (`check` enforces them): every page opens wide, and a
|
|
85
|
+
push-in from the wide shot comes after the whole window has been seen. At
|
|
86
|
+
most two push-ins a chapter, and a push-in needs something done or read in
|
|
87
|
+
its shot. A control a step uses must be inside the current shot. What it
|
|
88
|
+
changes (watched from the press to the app settling: typing's preview, a
|
|
89
|
+
toast, a restyle) must be in the shot or shown by the next step (a
|
|
90
|
+
`zoomOut`, or a zoom that frames it). A wide shot whose text is under 16 px
|
|
91
|
+
on the frame, where the controls and what they change would fit a push-in
|
|
92
|
+
of 1.4 or more, needs one.
|
|
93
|
+
|
|
94
|
+
**Adapter actions** may name the control they use (`target(params)`); the
|
|
95
|
+
cursor then goes there and rests, and the camera rules apply as for a
|
|
96
|
+
click. Without one, an action has no cursor and only a short beat after
|
|
97
|
+
it.
|
|
98
|
+
|
|
99
|
+
**Timing:** the engine adds the beats around clicks, the camera's settle and
|
|
100
|
+
a linger before each card (look.md has the numbers). Holds may not add up
|
|
101
|
+
past the app's idle timeout. A passing `check` prints the story's estimated
|
|
102
|
+
length against its kind's range (`seconds` and `kind` in `--json`).
|
|
103
|
+
|
|
104
|
+
## What `check` says, and the fix
|
|
105
|
+
|
|
106
|
+
| It says | Fix |
|
|
107
|
+
|---|---|
|
|
108
|
+
| `"x" is outside the shot …` | `zoomOut` first, or frame an area that holds everything the shot uses |
|
|
109
|
+
| `clicking / typing in / using "x" changes y, which is outside the shot …` | `zoomOut` right after, or frame the control with what it changes |
|
|
110
|
+
| `"x" is used in the wide shot, where its text is N px, too small to read …` | `frame` the controls and what they change (the engine pushes in after a wide beat); or, if it's setup, `behindCard` |
|
|
111
|
+
| `N camera push-ins in one chapter` | Push in once on the chapter's area and hold steady |
|
|
112
|
+
| `… only fit in the wide shot` | Stay wide, or frame things that sit together |
|
|
113
|
+
| `a zoom with nothing in its shot` | Remove it, or act or read something in it |
|
|
114
|
+
| `zoom 2.4; use 1.3–2` | Zoom less: context reads better and stays sharp |
|
|
115
|
+
| `behindCard only right after a card` | Move the step to just after a card, or drop `behindCard` |
|
|
116
|
+
| `"x" (show) never appears in the chapter …` | Show an element the chapter ends on |
|
|
117
|
+
| `cards between chapters have no eyebrow` | Remove it: the statement and sub-line carry the chapter |
|
|
118
|
+
| `… shows the same snapshot` | Show each result once: on the open card or on a chapter card |
|
|
119
|
+
| `title.show: "x" never appears in the story` | Show an element the story reaches: its result, or the feature |
|
|
120
|
+
| `kind: a feature clip shows one feature, in one chapter` | Cut it to the feature's one chapter, or make it a showcase |
|
|
121
|
+
| `N chapters; a showcase has at most 4` | Make a second story |
|
|
122
|
+
| `kind: the primary story … is a showcase` | Drop `"kind": "feature"` from the primary story |
|
|
123
|
+
| `"…" looks like a testid-like name / barcode / code` | Cards are for people: say it in words |
|
|
124
|
+
| `"38" isn't shown by an expectText` | Quote only values an `expectText` checks |
|
|
125
|
+
| `the card announces a chapter in which nothing is done` | Follow it with the steps it describes (setup behind the card doesn't count) |
|
|
126
|
+
| `… names a brand or extends a story` | Remove it: a customer's branding is @Linear's, a translation is a story of its own |
|
|
127
|
+
| `…/demo/brands isn't used` | Delete the folder: repos keep no brands |
|
|
69
128
|
|
|
70
129
|
## Brand (the engine's `navipartner`, or one a pitch draft builds)
|
|
71
130
|
|
|
@@ -73,8 +132,8 @@ export default defineDemo({
|
|
|
73
132
|
- `config`: opaque to the engine, the keys the app's branding API reads
|
|
74
133
|
(`primaryColor`, …). An adapter may also read `config.demoData`: names
|
|
75
134
|
for the mock's products, keyed by the mock's barcodes (prices and flows
|
|
76
|
-
stay the mock's). It takes `demoData` out before it
|
|
77
|
-
|
|
135
|
+
stay the mock's). It takes `demoData` out before it overlays the
|
|
136
|
+
branding.
|
|
78
137
|
- `assets`: slot → file, e.g. `{ "logo": "navipartner/logo.svg" }`
|
|
79
138
|
- `video`: `primary`, `ink`, `accent`, `text`, `headingFont`, `bodyFont`,
|
|
80
139
|
optional `fontsUrl`, `logo` (asset slot)
|