@a1knowhow/demo-maker 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +104 -0
  3. package/SECURITY.md +33 -0
  4. package/bin/demo-maker.mjs +14 -0
  5. package/docs/README.md +35 -0
  6. package/docs/actions.md +160 -0
  7. package/docs/cli.md +73 -0
  8. package/docs/getting-started.md +220 -0
  9. package/docs/imports-and-fragments.md +78 -0
  10. package/docs/library-api.md +64 -0
  11. package/docs/locators.md +119 -0
  12. package/docs/recording.md +59 -0
  13. package/docs/repairing-scenarios.md +73 -0
  14. package/docs/scenario-schema.md +80 -0
  15. package/docs/url-capture.md +75 -0
  16. package/docs/variables.md +48 -0
  17. package/docs/video-and-pacing.md +109 -0
  18. package/examples/demo1-introduction.yaml +166 -0
  19. package/examples/demo2-github-actions.yaml +109 -0
  20. package/examples/files/demo1-introduction-run.log +50 -0
  21. package/examples/fragments/open-repository.yaml +15 -0
  22. package/examples/smoke.yaml +18 -0
  23. package/llms.txt +32 -0
  24. package/package.json +66 -0
  25. package/src/cli.ts +226 -0
  26. package/src/env.ts +112 -0
  27. package/src/export-chapters.ts +99 -0
  28. package/src/ffmpeg.ts +168 -0
  29. package/src/index.ts +54 -0
  30. package/src/load.ts +143 -0
  31. package/src/logger.ts +126 -0
  32. package/src/main.ts +68 -0
  33. package/src/parse-errors.ts +99 -0
  34. package/src/parse.ts +622 -0
  35. package/src/playwright-selector-to-locator.ts +328 -0
  36. package/src/record-cli.ts +179 -0
  37. package/src/recorder.ts +442 -0
  38. package/src/recording-to-yaml.ts +435 -0
  39. package/src/runner.ts +1582 -0
  40. package/src/selector-to-locator.ts +69 -0
  41. package/src/templates.ts +48 -0
  42. package/src/types.ts +319 -0
  43. package/src/url-capture.ts +105 -0
  44. package/src/variables.ts +64 -0
@@ -0,0 +1,75 @@
1
+ # URL capture
2
+
3
+ Purpose: Store path segments from the browser URL as `{{ variables }}` during a run.
4
+
5
+ ## What it does
6
+
7
+ When the runner navigates (and after some steps), it can match the current page URL against regex rules. Each rule’s **first capturing group** is written to a named variable for later steps.
8
+
9
+ Example: after opening `/projects/abc123/settings`, capture `project_id=abc123` and use `{{ project_id }}` in the next URL or fill.
10
+
11
+ No rules by default — nothing is captured until you configure them.
12
+
13
+ ## Scenario YAML
14
+
15
+ ```yaml
16
+ name: my-demo
17
+ base_url: https://app.example/
18
+ url_capture:
19
+ - variable: workspace_id
20
+ pattern: "/workspace/([^/]+)(?:/|$)"
21
+ - variable: document_id
22
+ pattern: "/workspace/[^/]+/doc/([^/]+)"
23
+ steps:
24
+ - action: navigate
25
+ url: /workspace/… # after load, workspace_id is set if the URL matches
26
+ - action: navigate
27
+ url: "/workspace/{{ workspace_id }}/doc/{{ document_id }}/edit"
28
+ ```
29
+
30
+ `pattern` is a **RegExp source string** (not slash-wrapped YAML regex). Entry-file only (imports do not contribute `url_capture`).
31
+
32
+ ## CLI
33
+
34
+ Repeatable flag:
35
+
36
+ ```bash
37
+ npx demo-maker run demo.yaml \
38
+ --capture-from-url 'workspace_id=/workspace/([^/]+)(?:/|$)' \
39
+ --capture-from-url 'document_id=/workspace/[^/]+/doc/([^/]+)'
40
+ ```
41
+
42
+ Or a JSON file:
43
+
44
+ ```json
45
+ [
46
+ { "variable": "workspace_id", "pattern": "/workspace/([^/]+)(?:/|$)" },
47
+ { "variable": "document_id", "pattern": "/workspace/[^/]+/doc/([^/]+)" }
48
+ ]
49
+ ```
50
+
51
+ ```bash
52
+ npx demo-maker run demo.yaml --url-capture-file=./url-capture.json
53
+ ```
54
+
55
+ CLI rules are applied **after** scenario `url_capture` (same variable name overwrites when both match later).
56
+
57
+ ## Library
58
+
59
+ ```ts
60
+ import { runScenario, createRegexUrlCapture } from "@a1knowhow/demo-maker";
61
+
62
+ await runScenario(scenario, context, {
63
+ urlCaptureHooks: [
64
+ createRegexUrlCapture([
65
+ { variable: "org_id", pattern: String.raw`/orgs/([^/]+)` },
66
+ ]),
67
+ ],
68
+ });
69
+ ```
70
+
71
+ ## Related
72
+
73
+ - [Variables](./variables.md)
74
+ - [CLI](./cli.md)
75
+ - [Library API](./library-api.md)
@@ -0,0 +1,48 @@
1
+ # Variables and templates
2
+
3
+ Purpose: Runtime substitution in scenario strings.
4
+
5
+ ## `{{ placeholders }}`
6
+
7
+ In `value:`, `url:`, string locator fields, and captions, use:
8
+
9
+ ```yaml
10
+ value: "{{ auth.email }}"
11
+ url: "{{ BASE_URL }}/settings"
12
+ locator: { text: "{{ DEMO_WORKSPACE1 }}" }
13
+ ```
14
+
15
+ Sources (later overrides earlier where applicable):
16
+
17
+ - `--env-file` / `.env`-style file (all keys)
18
+ - Shell `process.env` only for: auth env names, `BASE_URL`, and flat `{{ NAME }}` keys referenced in the scenario
19
+ - Captured variables during the run (see [URL capture](./url-capture.md))
20
+ - Built-in `auth.email` / `auth.password` from env names in `auth:` (or defaults `E2E_TEST_USER_EMAIL` / `E2E_TEST_USER_PASSWORD`)
21
+ - Nested keys: `{{ auth.email }}`
22
+
23
+ Prefer putting secrets and demo-specific values in `--env-file` rather than relying on the ambient shell environment.
24
+
25
+ `BASE_URL` from the env file overrides scenario `base_url` unless `--base-url` is passed (CLI wins).
26
+
27
+ **Regex locators are not interpolated** — see [Locators](./locators.md).
28
+
29
+ ## Template functions
30
+
31
+ `[fnName:"arg"]` in supported string fields. Currently used in `video.filename`:
32
+
33
+ | Syntax | Description |
34
+ |--------|-------------|
35
+ | `[date:"FORMAT"]` | Current local date/time |
36
+
37
+ Tokens: `YYYY`, `MM`, `DD`, `HH`, `mm`.
38
+
39
+ ```yaml
40
+ video:
41
+ enabled: true
42
+ dir: output/videos
43
+ filename: demo-[date:"YYYY-MM-DD-HHmm"].mp4
44
+ ```
45
+
46
+ Produces e.g. `demo-2026-04-01-1432.mp4`.
47
+
48
+ Implemented in `src/templates.ts`.
@@ -0,0 +1,109 @@
1
+ # Video and pacing
2
+
3
+ Purpose: Recording quality, overlays, ffmpeg post-processing, and timing.
4
+
5
+ Requires **ffmpeg** on `PATH` for `.mp4`, trim/splice (`start_step`/`end_step`, `cut_video`), and background audio.
6
+
7
+ ## Video config
8
+
9
+ ```yaml
10
+ video:
11
+ enabled: true
12
+ dir: "output/videos" # relative to process cwd
13
+ filename: "demo-[date:\"YYYY-MM-DD-HHmm\"].mp4"
14
+ size: { width: 1920, height: 1080 } # final output
15
+ viewport: { width: 1440, height: 810 } # browser render (optional)
16
+ start_step: 11 # optional trim (1-based); needs ffmpeg
17
+ end_step: 40
18
+ caption_parallel: true # optional
19
+ playback_speed: 1.25 # optional; .mp4 only
20
+ ```
21
+
22
+ | Field | Notes |
23
+ |-------|--------|
24
+ | `enabled` | Must be `true` to record |
25
+ | `dir` | Created if missing; relative to **cwd**, not the YAML path |
26
+ | `filename` | Optional; `.mp4` triggers H.264 re-encode (CRF 18). Supports `[date:"…"]` |
27
+ | `size` | Final resolution (YouTube-oriented default 1920×1080) |
28
+ | `viewport` | Browser size; if smaller than `size`, ffmpeg upscales (lanczos). Use on laptops so headed Chrome fits the screen |
29
+ | `start_step` / `end_step` | Trim saved video after full run |
30
+ | `caption_parallel` | If true, caption overlay does not block the next step |
31
+ | `playback_speed` | Speed final MP4 (`setpts`); chapters remapped; BGM stays normal tempo |
32
+
33
+ Playwright records VP8 WebM internally; `.mp4` re-encodes to H.264 (`libx264`, `yuv420p`, `faststart`).
34
+
35
+ ## Captions
36
+
37
+ Any step may set `caption:`. With video enabled, a bottom overlay is shown after the step. Default: wait ~2.5s before the next step. With `caption_parallel: true`, the caption fades on a timer while the next steps run.
38
+
39
+ Optional `caption_style: chapter` — full-width bottom bar, larger type.
40
+
41
+ Prefer few captions (scene intent), not every click. Supports `{{ ENV }}`.
42
+
43
+ ## Scene polish actions
44
+
45
+ | Action | Role |
46
+ |--------|------|
47
+ | `title_card` | Full-screen chapter title (`text`, `hold_ms`, `fade_ms`) |
48
+ | `transition` | Fade to black (`fade_ms`; optional `hold_ms` for outro) |
49
+ | `cut_video` | Exclude nested duration from MP4; optional `title_card` placeholder |
50
+ | `video_exclude: true` | Exclude a single step |
51
+
52
+ ## Background audio
53
+
54
+ ```yaml
55
+ audio:
56
+ background: path/to/music.mp3
57
+ ```
58
+
59
+ Mixed into the final MP4 via ffmpeg (when producing `.mp4`).
60
+
61
+ ## Timing and chapters
62
+
63
+ On success with video, the runner writes `<basename>.timing.json` beside the video. Chapter timestamps remap after splice/speed.
64
+
65
+ ```bash
66
+ demo-maker export-chapters output/videos/demo.timing.json
67
+ demo-maker export-chapters output/videos
68
+ ```
69
+
70
+ Use `action: log` with `── Scene N: Title` and/or `caption:` for chapter labels. Excluded (`cut_video`) steps are omitted from chapter export.
71
+
72
+ ## Pacing fields
73
+
74
+ | Field | Role |
75
+ |-------|------|
76
+ | `step_delay_ms` | After each step |
77
+ | `slow_mo_ms` | Playwright slowMo |
78
+ | `typing_delay_ms` | Between keystrokes (`type`); per-step override OK |
79
+ | `post_click_delay_ms` | After click settle |
80
+ | `navigate_hold_ms` | After navigate settle |
81
+ | `pre_action_delay_ms` | Before navigate/click |
82
+
83
+ `--fast` disables pacing for smoke checks.
84
+
85
+ Hold on a frame for video:
86
+
87
+ ```yaml
88
+ - action: wait
89
+ timeout_ms: 4000
90
+ ```
91
+
92
+ ## Recommended YouTube settings (laptop)
93
+
94
+ ```yaml
95
+ video:
96
+ enabled: true
97
+ dir: output/videos
98
+ filename: demo-[date:"YYYY-MM-DD-HHmm"].mp4
99
+ size: { width: 1920, height: 1080 }
100
+ viewport: { width: 1440, height: 810 }
101
+ ```
102
+
103
+ On a large external display, omit `viewport` for native 1080p rendering.
104
+
105
+ ## Related
106
+
107
+ - [Actions](./actions.md) (`title_card`, `cut_video`, `wait`)
108
+ - [Variables](./variables.md) (filename templates)
109
+ - [Getting started](./getting-started.md)
@@ -0,0 +1,166 @@
1
+ name: demo1-introduction
2
+ title: "demo-maker — Getting started walkthrough"
3
+ description: |
4
+ Public intro demo: open this repo on GitHub, walk getting-started.md
5
+ (install → YAML → env → video → record), then actions.md and locators.md
6
+ (including the accessibility tip). No auth required.
7
+ base_url: https://github.com
8
+ video:
9
+ enabled: true
10
+ dir: output/videos
11
+ filename: demo1-introduction-[date:"YYYY-MM-DD-HHmm"].mp4
12
+ size: { width: 1920, height: 1080 }
13
+ viewport: { width: 1440, height: 810 }
14
+ caption_parallel: true
15
+ playback_speed: 1.1
16
+ # Optional BGM (bring your own royalty-free track; path relative to cwd):
17
+ # audio:
18
+ # background: path/to/your-track.mp3
19
+ step_delay_ms: 250
20
+ slow_mo_ms: 50
21
+ typing_delay_ms: 40
22
+ post_click_delay_ms: 250
23
+ navigate_hold_ms: 1000
24
+ pre_action_delay_ms: 200
25
+ action_timeout_ms: 30000
26
+
27
+ steps:
28
+ - action: title_card
29
+ text: "From install to your first MP4"
30
+ hold_ms: 1400
31
+
32
+ - action: log
33
+ message: "── Scene 1: Repository home → Getting started"
34
+
35
+ - import: fragments/open-repository.yaml
36
+
37
+ - action: navigate
38
+ url: /a1knowhow/demo-maker/blob/main/docs/getting-started.md
39
+ caption: "Getting started"
40
+
41
+ - action: expect_visible
42
+ locator:
43
+ role: heading
44
+ name: Getting started
45
+
46
+ - action: log
47
+ message: "── Scene 2: Install"
48
+
49
+ - action: click
50
+ locator:
51
+ role: link
52
+ name: "Permalink: Step 1 — Install prerequisites"
53
+ caption: "Install"
54
+
55
+ - action: wait
56
+ timeout_ms: 900
57
+
58
+ - action: log
59
+ message: "── Scene 3: Create your YAML"
60
+
61
+ - action: click
62
+ locator:
63
+ role: link
64
+ name: "Permalink: Step 3 — Point at your app"
65
+
66
+ - action: click
67
+ locator:
68
+ text: "name: my-app-smoke"
69
+ caption: "Create your YAML file"
70
+
71
+ - action: wait
72
+ timeout_ms: 1000
73
+
74
+ - action: log
75
+ message: "── Scene 4: Env vars when needed"
76
+
77
+ - action: click
78
+ locator:
79
+ role: link
80
+ name: "Permalink: Step 4 — Env file and auth (when needed)"
81
+ caption: "Env vars when you need auth"
82
+
83
+ - action: wait
84
+ timeout_ms: 900
85
+
86
+ - action: log
87
+ message: "── Scene 5: Record video"
88
+
89
+ - action: click
90
+ locator:
91
+ role: link
92
+ name: "Permalink: Step 5 — Record a video (MP4)"
93
+ caption: "Enable video for MP4 output"
94
+
95
+ - action: wait
96
+ timeout_ms: 500
97
+
98
+ - action: log
99
+ message: "── Scene 6: Generate draft YAML"
100
+
101
+ - action: click
102
+ locator:
103
+ role: link
104
+ name: "Permalink: Step 6 — Record interactions instead of writing YAML by hand"
105
+ caption: "Generate draft YAML with demo-maker record"
106
+
107
+ - action: wait
108
+ timeout_ms: 1000
109
+
110
+ - action: log
111
+ message: "── Scene 7: Actions reference"
112
+
113
+ - action: click
114
+ locator:
115
+ role: link
116
+ name: "Permalink: Next reading"
117
+
118
+ - action: click
119
+ locator:
120
+ selector: '.markdown-body a[href$="actions.md"]'
121
+ settle_until:
122
+ locator:
123
+ role: heading
124
+ name: Actions
125
+ caption: "Browse every action"
126
+
127
+ - action: wait
128
+ timeout_ms: 800
129
+ caption: "navigate, click, type, expect_visible, …"
130
+
131
+ - action: log
132
+ message: "── Scene 8: Locators"
133
+
134
+ - action: click
135
+ locator:
136
+ role: link
137
+ name: "Permalink: Related"
138
+
139
+ - action: click
140
+ locator:
141
+ selector: '.markdown-body a[href$="locators.md"]'
142
+ settle_until:
143
+ locator:
144
+ role: heading
145
+ name: Locators
146
+ caption: "How to target UI elements"
147
+
148
+ - action: wait
149
+ timeout_ms: 800
150
+
151
+ - action: click
152
+ locator:
153
+ role: link
154
+ name: "Permalink: Accessibility tip (for app authors)"
155
+ caption: "Unique aria-labels keep demos stable"
156
+
157
+ - action: wait
158
+ timeout_ms: 1400
159
+
160
+ - action: transition
161
+ fade_ms: 400
162
+ hold_ms: 300
163
+
164
+ - action: title_card
165
+ text: "Try https://github.com/a1knowhow/demo-maker"
166
+ hold_ms: 1800
@@ -0,0 +1,109 @@
1
+ name: demo2-github-actions
2
+ title: "demo-maker — GitHub Actions walkthrough"
3
+ description: |
4
+ Richer public example: open this repo on GitHub, open Actions, open the latest
5
+ successful run, and open the test job (green check-marks on each step).
6
+ No auth required for this walkthrough. Expanding step logs needs a signed-in
7
+ GitHub session (optional --storage-state); anonymously GitHub disables clicks
8
+ on log steps (pointer-events:none).
9
+ base_url: https://github.com
10
+ video:
11
+ enabled: true
12
+ dir: output/videos
13
+ filename: demo2-github-actions-[date:"YYYY-MM-DD-HHmm"].mp4
14
+ size: { width: 1920, height: 1080 }
15
+ viewport: { width: 1440, height: 810 }
16
+ caption_parallel: true
17
+ playback_speed: 1.25
18
+ # Optional BGM (bring your own royalty-free track; path relative to cwd):
19
+ # audio:
20
+ # background: path/to/your-track.mp3
21
+ step_delay_ms: 400
22
+ slow_mo_ms: 80
23
+ typing_delay_ms: 40
24
+ post_click_delay_ms: 350
25
+ navigate_hold_ms: 1800
26
+ pre_action_delay_ms: 350
27
+ action_timeout_ms: 30000
28
+
29
+ steps:
30
+ - action: title_card
31
+ text: "Demo videos as code"
32
+ hold_ms: 1600
33
+
34
+ - action: log
35
+ message: "── Scene 1: Repository home → Actions"
36
+
37
+ - import: fragments/open-repository.yaml
38
+
39
+ - action: click
40
+ locator:
41
+ role: link
42
+ name: Actions
43
+ settle_until:
44
+ locator:
45
+ role: combobox
46
+ name: Filter workflow runs
47
+ caption: "Open GitHub Actions"
48
+
49
+ - action: wait
50
+ timeout_ms: 1200
51
+ caption: "CI runs for this repo"
52
+
53
+ - action: log
54
+ message: "── Scene 2: Open the latest successful run"
55
+
56
+ - action: title_card
57
+ text: "Inspect a green CI run"
58
+ hold_ms: 1400
59
+
60
+ - action: click
61
+ locator:
62
+ role: link
63
+ name: /completed successfully:/i
64
+ settle_until:
65
+ locator:
66
+ role: link
67
+ name: test
68
+ caption: "Open the first successful workflow run"
69
+
70
+ - action: wait
71
+ timeout_ms: 1000
72
+
73
+ - action: log
74
+ message: "── Scene 3: Open the test job"
75
+
76
+ - action: click
77
+ locator:
78
+ role: link
79
+ name: test
80
+ settle_until:
81
+ text: Run npm test
82
+ caption: "Open the test job"
83
+
84
+ - action: expect_visible
85
+ locator:
86
+ text: Run npm test
87
+
88
+ - action: expect_visible
89
+ locator:
90
+ text: Run npm run typecheck
91
+
92
+ - action: wait
93
+ timeout_ms: 2800
94
+ caption: "Green checks on every step — re-run forever"
95
+
96
+ # Expanding a step log requires a signed-in GitHub session (anonymous UI uses
97
+ # pointer-events:none on <details>). With storage_state, you can add:
98
+ # - action: click
99
+ # locator:
100
+ # selector: 'summary.CheckStep-header:has-text("Run npm test")'
101
+ # caption: "Expand the npm test step"
102
+
103
+ - action: transition
104
+ fade_ms: 500
105
+ hold_ms: 400
106
+
107
+ - action: title_card
108
+ text: "Try https://github.com/a1knowhow/demo-maker"
109
+ hold_ms: 2200
@@ -0,0 +1,50 @@
1
+ Base URL: https://github.com
2
+ Running scenario: demo1-introduction (35/35 steps)
3
+ 10:35:58 - Step 1/35: title_card - From install to your first MP4
4
+ 10:36:00 - Step 2/35: log - ── Scene 1: Repository home → Getting started
5
+ [log] ── Scene 1: Repository home → Getting started
6
+ 10:36:01 - Step 3/35: navigate - Open the demo-maker repository
7
+ 10:36:04 - Step 4/35: expect_visible - link "demo-maker"
8
+ 10:36:04 - Step 5/35: wait - 800ms
9
+ 10:36:05 - Step 6/35: navigate - Getting started
10
+ 10:36:08 - Step 7/35: expect_visible - heading "Getting started"
11
+ 10:36:08 - Step 8/35: log - ── Scene 2: Install
12
+ [log] ── Scene 2: Install
13
+ 10:36:08 - Step 9/35: click - Install
14
+ 10:36:10 - Step 10/35: wait - 900ms
15
+ 10:36:11 - Step 11/35: log - ── Scene 3: Create your YAML
16
+ [log] ── Scene 3: Create your YAML
17
+ 10:36:12 - Step 12/35: click - link "Permalink: Step 3 — Point at your app"
18
+ 10:36:13 - Step 13/35: click - Create your YAML file
19
+ 10:36:14 - Step 14/35: wait - 1000ms
20
+ 10:36:16 - Step 15/35: log - ── Scene 4: Env vars when needed
21
+ [log] ── Scene 4: Env vars when needed
22
+ 10:36:16 - Step 16/35: click - Env vars when you need auth
23
+ 10:36:18 - Step 17/35: wait - 900ms
24
+ 10:36:19 - Step 18/35: log - ── Scene 5: Record video
25
+ [log] ── Scene 5: Record video
26
+ 10:36:19 - Step 19/35: click - Enable video for MP4 output
27
+ 10:36:21 - Step 20/35: wait - 500ms
28
+ 10:36:21 - Step 21/35: log - ── Scene 6: Generate draft YAML
29
+ [log] ── Scene 6: Generate draft YAML
30
+ 10:36:22 - Step 22/35: click - Generate draft YAML with demo-maker record
31
+ 10:36:23 - Step 23/35: wait - 1000ms
32
+ 10:36:24 - Step 24/35: log - ── Scene 7: Actions reference
33
+ [log] ── Scene 7: Actions reference
34
+ 10:36:25 - Step 25/35: click - link "Permalink: Next reading"
35
+ 10:36:26 - Step 26/35: click - Browse every action
36
+ 10:36:28 - Step 27/35: wait - navigate, click, type, expect_visible, …
37
+ 10:36:29 - Step 28/35: log - ── Scene 8: Locators
38
+ [log] ── Scene 8: Locators
39
+ 10:36:30 - Step 29/35: click - link "Permalink: Related"
40
+ 10:36:31 - Step 30/35: click - How to target UI elements
41
+ 10:36:33 - Step 31/35: wait - 800ms
42
+ 10:36:34 - Step 32/35: click - Unique aria-labels keep demos stable
43
+ 10:36:35 - Step 33/35: wait - 1400ms
44
+ 10:36:37 - Step 34/35: transition - fade 400ms
45
+ 10:36:38 - Step 35/35: title_card - Try https://github.com/a1knowhow/demo-maker
46
+ Re-encoded to H.264 MP4 (CRF 18). Playback speed 1.1×. Upscaled 1440x810 → 1920x1080.
47
+ Timing saved: demo-maker/output/videos/demo1-introduction-2026-09-12-0735.timing.json
48
+ Scenario completed successfully.
49
+ Video saved: demo-maker/output/videos/demo1-introduction-2026-09-12-0735.mp4
50
+ Timing saved: demo-maker/output/videos/demo1-introduction-2026-09-12-0735.timing.json
@@ -0,0 +1,15 @@
1
+ name: open-repository
2
+ description: Fragment — open the demo-maker repository home page
3
+ base_url: https://github.com
4
+ steps:
5
+ - action: navigate
6
+ url: /a1knowhow/demo-maker
7
+ caption: "Open the demo-maker repository"
8
+
9
+ - action: expect_visible
10
+ locator:
11
+ role: link
12
+ name: demo-maker
13
+
14
+ - action: wait
15
+ timeout_ms: 800
@@ -0,0 +1,18 @@
1
+ name: smoke
2
+ description: Minimal public example — opens example.com (no auth)
3
+ base_url: https://example.com
4
+ video:
5
+ enabled: true
6
+ dir: output/videos
7
+ filename: smoke-[date:"YYYY-MM-DD-HHmm"].mp4
8
+ size: { width: 1920, height: 1080 }
9
+ viewport: { width: 1440, height: 810 } # optional; fit laptop screen when headed
10
+ steps:
11
+ - action: navigate
12
+ url: "/"
13
+ caption: "Example domain"
14
+ - action: expect_visible
15
+ locator:
16
+ text: Example Domain
17
+ - action: wait
18
+ timeout_ms: 800
package/llms.txt ADDED
@@ -0,0 +1,32 @@
1
+ # demo-maker
2
+
3
+ > Demo videos as code — YAML + Playwright → polished, consistent product feature videos. Configure once, re-run forever.
4
+
5
+ Open-source CLI (`@a1knowhow/demo-maker`). Requires Node.js 20+, Playwright Chromium, and ffmpeg. Apache-2.0.
6
+
7
+ Prefer markdown docs linked below over scraping HTML. Schema lives in source TypeScript.
8
+
9
+ ## Docs
10
+
11
+ - [README](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/README.md): Overview, install, quick start
12
+ - [Getting started](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/docs/getting-started.md): First scenario and MP4
13
+ - [CLI](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/docs/cli.md): Commands and flags
14
+ - [Scenario schema](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/docs/scenario-schema.md): YAML structure
15
+ - [Actions](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/docs/actions.md): Step actions
16
+ - [Locators](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/docs/locators.md): Targeting UI
17
+ - [Video & pacing](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/docs/video-and-pacing.md): Recording quality
18
+ - [Recording](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/docs/recording.md): Live record to YAML
19
+ - [Repair](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/docs/repairing-scenarios.md): Fix after UI changes
20
+
21
+ ## Optional
22
+
23
+ - [Docs index](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/docs/README.md)
24
+ - [Imports & fragments](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/docs/imports-and-fragments.md)
25
+ - [Variables](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/docs/variables.md)
26
+ - [URL capture](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/docs/url-capture.md)
27
+ - [Library API](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/docs/library-api.md)
28
+ - [Types](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/src/types.ts): Typed scenario schema
29
+ - [Example scenario](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/examples/smoke.yaml)
30
+ - [Getting started walkthrough](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/examples/demo1-introduction.yaml)
31
+ - [GitHub Actions walkthrough](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/examples/demo2-github-actions.yaml)
32
+ - [Security policy](https://raw.githubusercontent.com/a1knowhow/demo-maker/main/SECURITY.md)
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@a1knowhow/demo-maker",
3
+ "version": "0.1.0",
4
+ "description": "Demo videos as code — configure once, re-run forever. YAML + Playwright → polished, consistent product feature videos.",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "bin": {
8
+ "demo-maker": "./bin/demo-maker.mjs"
9
+ },
10
+ "exports": {
11
+ ".": "./src/index.ts"
12
+ },
13
+ "files": [
14
+ "bin",
15
+ "src",
16
+ "examples",
17
+ "docs",
18
+ "LICENSE",
19
+ "README.md",
20
+ "SECURITY.md",
21
+ "llms.txt"
22
+ ],
23
+ "keywords": [
24
+ "automation",
25
+ "cli",
26
+ "demo",
27
+ "ffmpeg",
28
+ "playwright",
29
+ "product-demo",
30
+ "screen-recording",
31
+ "video",
32
+ "yaml"
33
+ ],
34
+ "engines": {
35
+ "node": ">=20"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/a1knowhow/demo-maker.git"
40
+ },
41
+ "homepage": "https://github.com/a1knowhow/demo-maker#readme",
42
+ "bugs": {
43
+ "url": "https://github.com/a1knowhow/demo-maker/issues"
44
+ },
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "scripts": {
49
+ "demo-maker": "tsx src/main.ts",
50
+ "test": "vitest run",
51
+ "test:watch": "vitest",
52
+ "typecheck": "tsc -p tsconfig.json --noEmit",
53
+ "pack:check": "npm pack --dry-run",
54
+ "prepublishOnly": "npm test && npm run typecheck"
55
+ },
56
+ "dependencies": {
57
+ "playwright": "^1.62.1",
58
+ "tsx": "^4.23.13",
59
+ "yaml": "^2.9.0"
60
+ },
61
+ "devDependencies": {
62
+ "@types/node": "^22.13.10",
63
+ "typescript": "^5.9.3",
64
+ "vitest": "^3.0.9"
65
+ }
66
+ }