@qwertybit/pr-preview 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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,33 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project
5
+ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [0.1.0] — 2026-06-08
8
+
9
+ Initial release.
10
+
11
+ ### Added
12
+
13
+ - **Record by demonstration**: a headed-Chrome harness loads your app in an
14
+ iframe; every click, keystroke, scroll and navigation becomes an editable
15
+ step with a thumbnail.
16
+ - **Per-pass before/after flow**: record the journey on the PR base branch
17
+ (run in an isolated git worktree) and again on your branch — the two UIs can
18
+ differ completely. A 5-step wizard, tab strip with branch names, and a
19
+ pinned action bar guide each stage.
20
+ - **High-quality output**: produces small, sharp `before.mp4` / `after.mp4`
21
+ via ffmpeg (H.264, near-Full-HD), with an automatic GIF fallback when ffmpeg
22
+ is absent. `format: "mp4" | "gif" | "both"`.
23
+ - **Burned-in captions**: each clip shows its branch, the base it's compared
24
+ against, and a timestamp.
25
+ - **Resilient replay**: a synthetic cursor, human pacing, a ready-page gate,
26
+ a manual-auth popup (passwords are never stored), and selector-drift
27
+ recovery (retry / skip / restart the capture).
28
+ - **Cross-origin without a proxy**: the recorder is injected via Playwright's
29
+ `exposeBinding`; only frame-busting headers (`X-Frame-Options`,
30
+ CSP `frame-ancestors`) are stripped.
31
+ - CLI: `pr-preview init`, `pr-preview record`, `pr-preview run`.
32
+
33
+ [0.1.0]: https://github.com/QwertyBit-Ventures/pr-preview/releases/tag/v0.1.0
package/LICENSE ADDED
@@ -0,0 +1,30 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 QwertyBit (vlad@flowpoint.ai)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ Trademarks. The MIT license above applies to the source code of this CLI only.
26
+ It does NOT grant any rights to the "pr-preview" / "PR Preview" names, the logo,
27
+ or other QwertyBit brand features, which remain trademarks of QwertyBit. The
28
+ hosted pr-preview service (pr-preview.com) and any commercial editions or
29
+ premium add-ons are separate, proprietary offerings and are not covered by this
30
+ license.
package/README.md ADDED
@@ -0,0 +1,242 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/QwertyBit-Ventures/pr-preview/main/npm_package/harness/public/logo-wordmark.svg" alt="PR Preview" width="280" />
3
+ </p>
4
+
5
+ <p align="center">
6
+ <strong>See what your PR changed — before &amp; after, in a clip.</strong><br/>
7
+ A free, open-source CLI that records a journey through your app and turns it into a polished
8
+ before/after video for your pull request.
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/@qwertybit/pr-preview"><img src="https://img.shields.io/npm/v/@qwertybit/pr-preview?color=635bff" alt="npm version" /></a>
13
+ <a href="./LICENSE"><img src="https://img.shields.io/npm/l/@qwertybit/pr-preview?color=2da44e" alt="MIT license" /></a>
14
+ <img src="https://img.shields.io/node/v/@qwertybit/pr-preview" alt="node >= 20" />
15
+ <a href="https://pr-preview.com"><img src="https://img.shields.io/badge/website-pr--preview.com-635bff" alt="pr-preview.com" /></a>
16
+ </p>
17
+
18
+ <p align="center">
19
+ <img src="https://raw.githubusercontent.com/QwertyBit-Ventures/pr-preview/main/npm_package/docs/media/demo.gif" alt="PR Preview demo — recording a UI journey and producing a before/after video" width="720" />
20
+ </p>
21
+
22
+ **PR Preview** opens your app in a controlled Chrome window and records the journey you perform —
23
+ clicking through a feature, logging in, submitting a form. The recording *is* the clip (no replay,
24
+ no flaky re-enactment), so what you did is exactly what reviewers see. Do it on your PR's base
25
+ branch and on your branch and you get two high-quality videos you can drag straight into a GitHub
26
+ pull request:
27
+
28
+ | `before.mp4` | `after.mp4` |
29
+ | --- | --- |
30
+ | your journey on the base branch | the same journey, with your changes |
31
+
32
+ No CI to set up, no scripts to write. It runs locally, against your real dev server, and ships in
33
+ about a minute.
34
+
35
+ > **Why it matters:** in the AI era, more of every diff is machine-generated, and reviewers
36
+ > can't infer how the UI behaves from reading generated code. A 15-second before/after clip makes
37
+ > the visual change obvious in seconds — and turns "LGTM" into an actual review.
38
+
39
+ ---
40
+
41
+ ## ✨ Features
42
+
43
+ - 🎬 **Record by demonstration** — just use your app. Clicks, typing, scrolling and navigation are
44
+ captured as an editable outline; no selectors or scripts to hand-write.
45
+ - 🎥 **Live capture, zero drift** — the clip is your real recording, not a replay, so it never
46
+ desyncs on stateful apps. A synthetic cursor makes every move easy to follow.
47
+ - 🌳 **True before/after** — the base branch runs in an isolated git **worktree**; your working
48
+ tree is never touched. Or point it at an app you already run with `--url`.
49
+ - 🎞️ **Tiny, sharp MP4s** — H.264, near-Full-HD, a few hundred KB. GitHub renders them inline in a
50
+ PR. High-quality GIF fallback when ffmpeg isn't installed.
51
+ - 🔒 **Runs entirely on your machine** — nothing is uploaded. Your source and app data never leave
52
+ your computer.
53
+ - 🏷️ **Self-describing clips** — each is captioned with its branch and a timestamp.
54
+ - 🤖 **Agent-friendly** — config-driven and flag-free, so you can kick it off from Claude Code or CI.
55
+
56
+ ## 🚀 Install
57
+
58
+ ```bash
59
+ npm i -D @qwertybit/pr-preview
60
+ npx playwright install chromium # one-time browser download
61
+ npx pr-preview init # scaffolds pr-preview.config.js
62
+ ```
63
+
64
+ > **ffmpeg** (optional, recommended) gives you MP4 output. macOS: `brew install ffmpeg` ·
65
+ > Debian/Ubuntu: `apt install ffmpeg`. Without it, PR Preview produces a high-quality GIF instead.
66
+
67
+ ## ⚡ Quick start
68
+
69
+ On your PR branch:
70
+
71
+ ```bash
72
+ npx pr-preview run
73
+ ```
74
+
75
+ That's it. PR Preview will:
76
+
77
+ 1. Detect your PR base, check it out into a worktree, and start its dev server.
78
+ 2. Open Chrome with the recording harness. **Record** your journey → **Confirm** → `before.mp4`.
79
+ 3. Switch to your branch's app, record the same journey (or reuse the BEFORE outline) → **Save** →
80
+ `after.mp4`.
81
+ 4. Open the output folder.
82
+
83
+ Both clips land in `.pr-preview/output/`. Drag them into your PR description — done.
84
+
85
+ Just need one clip (a demo, a bug repro)? `npx pr-preview run --single` records a single standalone
86
+ video, no comparison.
87
+
88
+ ## 🧠 How it works
89
+
90
+ A run is a short wizard shown in the harness sidebar:
91
+
92
+ ```
93
+ ①────────②────────③────────④────────⑤
94
+ Record Capture Record Capture Generate
95
+ (base) before (branch) after files
96
+ ```
97
+
98
+ - **The clip is the recording.** Frames are captured live as you perform the journey, then trimmed
99
+ at the ends and captioned — so it looks polished without the drift of re-enacting steps.
100
+ - **Before and after are recorded separately** (a PR can change the UI completely). If the flows
101
+ match, a **Load BEFORE steps** shortcut reuses the outline as a checklist.
102
+ - **Reset nudge** at the start of each pass lets you clear cookies/storage for a clean start, or
103
+ keep a session you set up by hand (e.g. a manual login) — only shown when there's state to reset.
104
+ - **Refresh button** in the frame corner reloads the app whenever you need a clean slate.
105
+
106
+ ## 📦 Output
107
+
108
+ | `format` | Result | Needs ffmpeg |
109
+ | --- | --- | --- |
110
+ | `"mp4"` *(default)* | `before.mp4`, `after.mp4` | yes (falls back to GIF) |
111
+ | `"gif"` | `before.gif`, `after.gif` | no |
112
+ | `"both"` | both pairs | yes |
113
+
114
+ MP4 is recommended: full color, far smaller than GIF, and GitHub embeds it inline.
115
+
116
+ ## ⚙️ Configuration
117
+
118
+ Everything lives in `pr-preview.config.js` (or `.ts` / `.json`), so a project is set up once and
119
+ runs with **no flags**:
120
+
121
+ ```js
122
+ /** @type {import('@qwertybit/pr-preview').Config} */
123
+ export default {
124
+ devCommand: "npm run dev", // required — $PORT is provided
125
+ url: "http://localhost:{port}", // required — {port} is templated in
126
+ cwd: ".", // frontend dir (for monorepos)
127
+ readyTimeout: 60000, // ms to wait for the dev server
128
+
129
+ // Run options (set once here instead of passing CLI flags each time):
130
+ externalUrl: undefined, // use an app you already run (skip the dev server)
131
+ baseBranch: undefined, // override base ("before") detection
132
+ keepWorktree: false, // reuse the base worktree across runs
133
+
134
+ output: ".pr-preview/output",
135
+ format: "mp4", // "mp4" | "gif" | "both"
136
+ passes: 2, // 2 = before/after · 1 = single clip
137
+ resetStorage: true, // default for the start-of-pass reset choice
138
+ viewport: { width: 1920, height: 1080 },
139
+ headerStrip: true, // strip X-Frame-Options / frame-ancestors so the app frames
140
+
141
+ // Browser permissions granted up front so a native prompt never blocks the run:
142
+ permissions: ["geolocation", "clipboard-read", "clipboard-write"], // allow-all by default
143
+ geolocation: undefined, // { latitude, longitude } — fixed & deterministic
144
+ };
145
+ ```
146
+
147
+ | Field | Default | Notes |
148
+ | --- | --- | --- |
149
+ | `devCommand` | — | Command that starts your dev server. `$PORT` is set for you. |
150
+ | `url` | — | Where the app answers once ready. `{port}` is replaced. |
151
+ | `cwd` | `"."` | Frontend directory relative to the repo root. |
152
+ | `readyTimeout` | `60000` | How long to wait for `url` to respond. |
153
+ | `externalUrl` | — | Use an app you already run instead of a managed dev server. Same as `run --url`. |
154
+ | `baseBranch` | auto | Override PR-base detection. Same as `run --base`. |
155
+ | `keepWorktree` | `false` | Reuse the base worktree across runs. Same as `run --keep-worktree`. |
156
+ | `format` | `"mp4"` | `mp4` \| `gif` \| `both`. |
157
+ | `passes` | `2` | `2` = before/after comparison; `1` = single standalone clip. `run --single` forces 1. |
158
+ | `resetStorage` | `true` | Default for the start-of-pass reset choice (clear cookies/storage vs. keep your session). |
159
+ | `viewport` | `1920×1080` | Logical app resolution; the window scales to fit. |
160
+ | `headerStrip` | `true` | Strip only frame-busting headers so the app loads in the iframe. |
161
+ | `permissions` | allow-all | Browser permissions to grant (Playwright names). Unlisted ones stay denied — no native prompt blocks the run. |
162
+ | `geolocation` | — | Fixed `{ latitude, longitude }` so location apps render identical results in both clips. |
163
+
164
+ ## 🖥️ CLI
165
+
166
+ | Command | What it does |
167
+ | --- | --- |
168
+ | `pr-preview init` | Scaffold `pr-preview.config.js` and a `.gitignore` entry. |
169
+ | `pr-preview record` | Record a journey on the current branch only (`-o <file>`). |
170
+ | `pr-preview run` | The full before/after flow. |
171
+
172
+ `run` flags: `-b, --base <ref>` (override base) · `--keep-worktree` (reuse the base worktree) ·
173
+ `-u, --url <url>` (use your own running app) · `-s, --single` (one standalone clip, no comparison).
174
+
175
+ ### Bring your own running app (`--url`)
176
+
177
+ For apps that can't boot in a throwaway checkout (need `.env`, a backend, a database), run the app
178
+ yourself and point PR Preview at it:
179
+
180
+ ```bash
181
+ npm run dev # → http://localhost:3000 (base branch)
182
+ npx pr-preview run --url http://localhost:3000
183
+ ```
184
+
185
+ It records BEFORE on your running app, then **pauses** — you switch branches, restart on the same
186
+ URL, and click **Continue** — then it records AFTER. No worktree, no managed dev server.
187
+
188
+ ## 🤖 Use it from Claude Code
189
+
190
+ Because every setting lives in the config, a run takes no flags — so an AI agent can kick it off.
191
+ Ask Claude Code for a preview and it runs `npx pr-preview run`; a Chrome window opens, **you click
192
+ through the ~30-second journey**, and the agent picks up the finished `before.mp4` / `after.mp4` to
193
+ drop into your PR. The agent triggers and finalizes; you demonstrate the journey.
194
+
195
+ ## 🔐 Privacy
196
+
197
+ PR Preview runs locally — it opens your app in a Chrome window, records, and writes video files to
198
+ your project. Nothing is uploaded. The clip is a real screen recording, so avoid typing real
199
+ production secrets on camera (use a test login, or your own redaction).
200
+
201
+ ## Requirements
202
+
203
+ - **Node.js ≥ 20**
204
+ - **Chromium** via Playwright (`npx playwright install chromium`)
205
+ - **ffmpeg** (optional) for MP4 output
206
+
207
+ ## Limitations
208
+
209
+ PR Preview drives a real app inside a controlled browser, so a few things are out of scope:
210
+
211
+ - **In-iframe SSO** (e.g. a redirect-style "Sign in with Google") — providers refuse to be framed.
212
+ Log in by hand before recording and keep the session; popup-based OAuth usually works.
213
+ - **CAPTCHA** — complete it by hand.
214
+ - **Canvas/WebGL, closed shadow roots, nested third-party iframes** (Stripe Elements, embedded
215
+ checkout) — limited support.
216
+
217
+ ## Contributing
218
+
219
+ See [CONTRIBUTING.md](./CONTRIBUTING.md). Issues and PRs welcome — and a ⭐ helps a lot.
220
+
221
+ ## License & what's free
222
+
223
+ The **CLI is open source under the [MIT license](./LICENSE)** — free to use, including commercially.
224
+ This is an open-core project:
225
+
226
+ - ✅ **This CLI** — recording and before/after clip generation. MIT, free forever. Clips carry a
227
+ small `pr-preview.com` watermark.
228
+ - 🔒 **PR Preview for Teams** ([pr-preview.com](https://pr-preview.com)) — the hosted service:
229
+ clip hosting, a synced review player, team reviewers & comments, sharing, and watermark-free
230
+ clips. A separate, proprietary commercial offering — *coming soon*.
231
+ - ™️ The **"PR Preview" name and logo** are trademarks of SC QWERTYBIT SRL; the MIT license covers
232
+ the code, not the brand.
233
+
234
+ ---
235
+
236
+ <p align="center">
237
+ <a href="https://pr-preview.com"><strong>🎬 pr-preview.com</strong></a><br/>
238
+ <sub>See it in action, and <a href="https://pr-preview.com/#teams">join the early-access list for PR&nbsp;Preview for Teams</a> —<br/>
239
+ hosted clips, team reviews &amp; sharing, coming soon.</sub>
240
+ </p>
241
+
242
+ <p align="center"><sub>Built by <a href="https://pr-preview.com">QwertyBit</a> · Free &amp; Open Source · MIT</sub></p>
Binary file