Vibecode Arcade
track this build4 phases, 12 steps, beginner friendly0%The core loop is buildable, but a dependable replacement becomes a real weekend or multi-day project. For Arcade, build an interactive product story from captured screens and hotspots. The hard boundary is capture polish, hosted playback, analytics, personalization, and collaboration, plus capture polish, hosting, and collaboration.
You are building a lean indie version of Arcade. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # Arcade · indie build A demo builder that captures real screens and turns them into a clickable walkthrough, where the interesting work is stitching steps into something coherent and the critical work is making sure nothing in the captures should not be public. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Capture | A browser extension recording steps as images with element positions | hotspots need to know where the user clicked, not just what the screen looked like | | Redaction | Applied to the stored image, irreversibly | an overlay leaves the original pixels in the file | | Detection | Automatic identification of likely personal data in captures | the failure is not noticing rather than deciding | | Playback | A small player with hotspots derived from the recorded steps | a demo embedded on a marketing page must not slow it down | | Runtime | TypeScript with object storage for images | the work is capture, image processing and a small player | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the server, the image pipeline and the player build. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **An image processing library** · free - Why: Redaction modifies pixels and must be irreversible, which is image work rather than a display concern. - Get it: Any library that can modify and re-encode images reliably at capture resolution. - Verify: A redacted region is unrecoverable from the re-encoded file - [ ] **Text and face detection you can run locally** · free, needs machine time - Why: Captures contain real customer data and sending them to a service for scanning is the disclosure you are trying to prevent. - Get it: A local text recognition model and a face detector, evaluated on real screenshots rather than photographs. - Verify: Text in a browser tab title and a name in a table are both detected - [ ] **A real application with realistic data** · free - Why: Detection quality and the places sensitive data actually appears can only be assessed against a real interface with real-looking records. - Get it: A staging environment with realistic rather than obviously fake data, since fake data hides the problem. - Verify: A recorded session contains at least five genuine detections - [ ] **What must never appear in a published demo** · free - Why: The publish gate blocks on unresolved detections, and what counts as needing resolution is a decision that belongs before the first demo rather than during a review. - Get it: List the categories that must always be redacted and who may resolve a detection as acceptable. - Verify: A written list exists and the detector covers every category on it ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Video recording rather than steps. - Native desktop application capture. - Automatic narration. - Any guarantee that detection is complete. - capture polish, hosted playback, analytics, personalization, and collaboration - instant hosted sharing - viewer analytics - team libraries - cross-device capture If one of those is essential to you, that is the reason to keep paying for Arcade, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Arcade The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me an interactive product demo built from captured screens, with the customer data taken out to replace Arcade. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Rule zero You are recording a working application, which means you are recording whatever was on the screen: real customer names in a list, an email address in the corner, a support ticket, a revenue figure. Demos get published on marketing sites and sent to prospects, so a missed redaction is a disclosure to everyone. So redaction happens on the captured image before it is stored, not as an overlay drawn on top at display time. An overlay is a rectangle over pixels that are still in the file, and anyone who downloads the image or reads the page source has the original. The build also detects likely personal data automatically and requires each detection to be resolved before a demo can be published, because the failure mode is not deciding to publish something sensitive, it is not noticing it was there. ### Stack (fixed, do not substitute) - Capture: A browser extension recording steps as images with element positions · hotspots need to know where the user clicked, not just what the screen looked like - Redaction: Applied to the stored image, irreversibly · an overlay leaves the original pixels in the file - Detection: Automatic identification of likely personal data in captures · the failure is not noticing rather than deciding - Playback: A small player with hotspots derived from the recorded steps · a demo embedded on a marketing page must not slow it down - Runtime: TypeScript with object storage for images · the work is capture, image processing and a small player ### Data model (create this before Phase 1) - demos(id, title, state, created_at, published_at, redaction_cleared_at) - steps(id, demo_id, ordinal, image_key, viewport_json, click_point, annotation, transition) - hotspots(step_id, x, y, width, height, target_step_id, label) - detections(step_id, kind, bbox_json, confidence, resolved_as, resolved_by, at) · kind is email, name, number or face - redactions(step_id, bbox_json, method, applied_at) · applied to the stored image, recorded for audit - originals(step_id, key, deleted_at) · the unredacted capture, deleted rather than retained - A demo cannot reach a published state while any detection is unresolved, which is enforced in the publish path rather than by a reminder. ### Phase 1 · Capturing steps, not just screenshots Build: A browser extension capturing a screenshot and the click position on each interaction, with the viewport recorded. Handle scrolling, navigation and a page that changes under the pointer. Store steps in order. Trap: Capturing after the click means the screenshot shows the result rather than the state the user was looking at when they decided to click, so the hotspot lands on something that is no longer there. Capture before the interaction and record the position separately. Done when: Steps capture the screen state before each interaction with the click position recorded separately. Scrolling and navigation produce coherent ordered steps. A page that changes under the pointer does not produce a hotspot pointing at nothing. Captures are taken at a consistent resolution regardless of the recorder's screen. Do not build yet: No detection, redaction, editing or playback. ### Phase 2 · Finding what should not be published Build: Detect email addresses, names, long numbers and faces in captures, with bounding boxes. Present every detection for resolution. Detect across the whole image rather than only in expected regions. Trap: Detecting only in the areas you expect data to appear misses the browser tab title, the notification that popped up, the autocomplete dropdown and the name in the corner of the page, which are exactly where the accidents happen. Scan the whole image, and accept false positives as the cost of not missing one. Done when: Emails, names, long numbers and faces are detected across the whole capture including browser interface areas. Every detection is presented with its position for resolution. False positives can be dismissed and stay dismissed. A capture with no detections is distinguishable from one that was never scanned. Do not build yet: No redaction, editing or publishing yet. ### Phase 3 · Redaction that removes pixels Build: Apply redaction to the stored image irreversibly and delete the original. Verify the redacted region cannot be recovered from the stored file. Record what was redacted without recording its content. Trap: Drawing a black rectangle in the player leaves the original pixels in the stored file, so anyone who opens the image directly sees exactly what you thought you had removed, and images on a marketing site are trivially downloadable. Modify the image and delete the original. Done when: A redacted region cannot be recovered from the stored image, verified by examining the file directly. The unredacted original is deleted rather than retained. The redaction record notes the region and method without storing what was there. Blur is offered but pixel removal is the default, since blur is sometimes reversible. Do not build yet: No editing, publishing or playback yet. ### Phase 4 · A demo that tells a story Build: Edit the step sequence: reorder, remove, annotate and set hotspots. Add branching where a demo has more than one path. Detect a hotspot pointing at a step that no longer exists. Trap: A demo that is simply every captured click is too long and includes the three attempts it took to find the right menu, which is exactly what a prospect does not need to see. Make removing and reordering steps the primary editing action rather than an afterthought. Done when: Steps can be reordered, removed and annotated, and removal does not break hotspots pointing at them. Branching paths work and unreachable steps are reported. A demo of thirty captured clicks edits down to eight steps in a few minutes. Annotations do not obscure the content they describe. Do not build yet: No publishing or playback yet. ### Phase 5 · Publishing, blocked until it is clean Build: Block publication while any detection is unresolved, enforced in the publish path. Serve an embeddable player that is small and does not block the host page. Report step completion where the author enables it. Trap: Warning about unresolved detections and publishing anyway means the warning is dismissed by whoever is in a hurry, which is always. Block the publish, name the steps with unresolved detections, and make resolving them the only route forward. Done when: Publishing is refused while any detection is unresolved, with the affected steps named, tested directly. The embedded player is small, loads asynchronously and survives a host page with conflicting styles. Completion reporting is off by default and states what it records. A published demo's images carry no recoverable redacted content, checked again at publish. Do not build yet: Nothing after this. ### Out of scope (and why) - Recording video rather than steps, which has entirely different redaction problems and no reliable way to catch a frame you missed. - Capturing native desktop applications, which is a different platform integration per operating system. - Automatic narration or voiceover, which is a separate quality problem and often worse than silence. - Any guarantee that detection catches everything, which it will not, which is why publication is blocked on human resolution rather than on a clean scan. ### README must contain - That redaction modifies the stored image and deletes the original, because an overlay leaves the pixels in the file - That detection scans the whole capture including browser interface, where the accidents actually happen - That publication is blocked while any detection is unresolved rather than warning about it - That captures are taken before each interaction, so a hotspot lands on what was actually clicked - That detection will miss things, which is why a human resolves every one rather than trusting a clean scan ===== AGENTS.md ===== # Agent instructions · Arcade indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A browser extension recording steps as images with element positions, Applied to the stored image, irreversibly, Automatic identification of likely personal data in captures, A small player with hotspots derived from the recorded steps, TypeScript with object storage for images. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Capturing after the click means the screenshot shows the result rather than the state the user was looking at when they decided to click, so the hotspot lands on something that is no longer there. Capture before the interaction and record the position separately. - Detecting only in the areas you expect data to appear misses the browser tab title, the notification that popped up, the autocomplete dropdown and the name in the corner of the page, which are exactly where the accidents happen. Scan the whole image, and accept false positives as the cost of not missing one. - Drawing a black rectangle in the player leaves the original pixels in the stored file, so anyone who opens the image directly sees exactly what you thought you had removed, and images on a marketing site are trivially downloadable. Modify the image and delete the original. - A demo that is simply every captured click is too long and includes the three attempts it took to find the right menu, which is exactly what a prospect does not need to see. Make removing and reordering steps the primary editing action rather than an afterthought. ===== BUILD_PLAN.md ===== # Build plan · Arcade A demo builder that captures real screens and turns them into a clickable walkthrough, where the interesting work is stitching steps into something coherent and the critical work is making sure nothing in the captures should not be public. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Capturing steps, not just screenshots A recorded session becomes ordered steps with the click positions kept. ### Steps 1. Capture before the interaction Capturing after shows the result, not what was clicked. Files: `extension/capture.ts` 2. Record click position separately The hotspot needs it and the image cannot carry it. Files: `extension/capture.ts` 3. Normalise capture resolution A demo recorded on one screen must look right on every other. Files: `src/normalise.ts` ### Done when - [ ] Steps capture state before each interaction - [ ] Click positions are recorded separately - [ ] Scrolling and navigation stay coherent - [ ] Capture resolution is consistent ### Watch out - Capturing after the click means the screenshot shows the result rather than the state the user was looking at when they decided to click, so the hotspot lands on something that is no longer there. Capture before the interaction and record the position separately. ## Phase 2 · Finding what should not be published Likely personal data in every capture is detected and shown. ### Steps 1. Scan the whole image Tab titles, notifications and dropdowns are where the accidents are. Files: `src/detect.ts` 2. Report position per detection So resolution is a look rather than a search. Files: `src/detect.ts` 3. Distinguish clean from unscanned A capture nobody scanned should not look like a clean one. Files: `src/steps.ts` ### Done when - [ ] Detection covers the whole image including browser interface - [ ] Every detection carries a position - [ ] Dismissed false positives stay dismissed - [ ] Clean and unscanned are distinguishable ### Watch out - Detecting only in the areas you expect data to appear misses the browser tab title, the notification that popped up, the autocomplete dropdown and the name in the corner of the page, which are exactly where the accidents happen. Scan the whole image, and accept false positives as the cost of not missing one. ## Phase 3 · Redaction that removes pixels Redacted content is gone from the stored image, not covered. ### Steps 1. Modify the stored image An overlay leaves the pixels in the file. Files: `src/redact.ts`, `tests/redaction.test.ts` 2. Delete the original Retaining it means the disclosure risk is still on your disk. Files: `src/originals.ts` 3. Default to removal, not blur Some blurs are reversible. Removal is not. Files: `src/redact.ts` ### Done when - [ ] Redacted regions are unrecoverable from the file - [ ] Originals are deleted - [ ] Redaction records region and method, not content - [ ] Removal is the default over blur ### Watch out - Drawing a black rectangle in the player leaves the original pixels in the stored file, so anyone who opens the image directly sees exactly what you thought you had removed, and images on a marketing site are trivially downloadable. Modify the image and delete the original. ## Phase 4 · A demo that tells a story Captured steps become a walkthrough someone can follow. ### Steps 1. Make editing down the primary action Every captured click includes the three failed attempts. Files: `src/edit.ts` 2. Detect broken and unreachable steps Removing a step should not leave a hotspot pointing nowhere. Files: `src/validate.ts` 3. Keep annotations out of the way An annotation covering the thing it describes is worse than none. Files: `src/annotate.ts` ### Done when - [ ] Reordering and removal keep hotspots valid - [ ] Branching works and unreachable steps are reported - [ ] Thirty clicks edit to eight steps quickly - [ ] Annotations do not obscure their subject ### Watch out - A demo that is simply every captured click is too long and includes the three attempts it took to find the right menu, which is exactly what a prospect does not need to see. Make removing and reordering steps the primary editing action rather than an afterthought. ## Not in this build - Video recording rather than steps. - Native desktop application capture. - Automatic narration. - Any guarantee that detection is complete. ## After v1, if you want it - Variable substitution so one demo can show a prospect's own name, which needs its own care - Localised demos from one recording, since the redaction work should not be repeated per language - Analytics on where viewers stop, which is genuinely useful and needs an honest consent position ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required · secret. Demo structure and detection records. DATABASE_URL=postgres://localhost:5432/demos # Required. Redacted images. Originals are deleted rather than stored here. IMAGE_BUCKET=s3://demo-captures # Required. Removal rather than blur, since some blurs are reversible. REDACTION_METHOD=remove # Required. Present as a constant. A retained original is the disclosure still on your disk. KEEP_ORIGINALS=never # Required. Present as a constant. A warning is dismissed by whoever is in a hurry. PUBLISH_BLOCKS_ON_DETECTIONS=always # Required. Captures contain real customer data and should not be sent anywhere to be scanned. DETECTION_MODEL=local
You are building a lean indie version of Arcade. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # Arcade · indie build A demo builder that captures real screens and turns them into a clickable walkthrough, where the interesting work is stitching steps into something coherent and the critical work is making sure nothing in the captures should not be public. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Capture | A browser extension recording steps as images with element positions | hotspots need to know where the user clicked, not just what the screen looked like | | Redaction | Applied to the stored image, irreversibly | an overlay leaves the original pixels in the file | | Detection | Automatic identification of likely personal data in captures | the failure is not noticing rather than deciding | | Playback | A small player with hotspots derived from the recorded steps | a demo embedded on a marketing page must not slow it down | | Runtime | TypeScript with object storage for images | the work is capture, image processing and a small player | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the server, the image pipeline and the player build. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **An image processing library** · free - Why: Redaction modifies pixels and must be irreversible, which is image work rather than a display concern. - Get it: Any library that can modify and re-encode images reliably at capture resolution. - Verify: A redacted region is unrecoverable from the re-encoded file - [ ] **Text and face detection you can run locally** · free, needs machine time - Why: Captures contain real customer data and sending them to a service for scanning is the disclosure you are trying to prevent. - Get it: A local text recognition model and a face detector, evaluated on real screenshots rather than photographs. - Verify: Text in a browser tab title and a name in a table are both detected - [ ] **A real application with realistic data** · free - Why: Detection quality and the places sensitive data actually appears can only be assessed against a real interface with real-looking records. - Get it: A staging environment with realistic rather than obviously fake data, since fake data hides the problem. - Verify: A recorded session contains at least five genuine detections - [ ] **What must never appear in a published demo** · free - Why: The publish gate blocks on unresolved detections, and what counts as needing resolution is a decision that belongs before the first demo rather than during a review. - Get it: List the categories that must always be redacted and who may resolve a detection as acceptable. - Verify: A written list exists and the detector covers every category on it ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Video recording rather than steps. - Native desktop application capture. - Automatic narration. - Any guarantee that detection is complete. - capture polish, hosted playback, analytics, personalization, and collaboration - instant hosted sharing - viewer analytics - team libraries - cross-device capture If one of those is essential to you, that is the reason to keep paying for Arcade, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · Arcade The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me an interactive product demo built from captured screens, with the customer data taken out to replace Arcade. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Rule zero You are recording a working application, which means you are recording whatever was on the screen: real customer names in a list, an email address in the corner, a support ticket, a revenue figure. Demos get published on marketing sites and sent to prospects, so a missed redaction is a disclosure to everyone. So redaction happens on the captured image before it is stored, not as an overlay drawn on top at display time. An overlay is a rectangle over pixels that are still in the file, and anyone who downloads the image or reads the page source has the original. The build also detects likely personal data automatically and requires each detection to be resolved before a demo can be published, because the failure mode is not deciding to publish something sensitive, it is not noticing it was there. ### Stack (fixed, do not substitute) - Capture: A browser extension recording steps as images with element positions · hotspots need to know where the user clicked, not just what the screen looked like - Redaction: Applied to the stored image, irreversibly · an overlay leaves the original pixels in the file - Detection: Automatic identification of likely personal data in captures · the failure is not noticing rather than deciding - Playback: A small player with hotspots derived from the recorded steps · a demo embedded on a marketing page must not slow it down - Runtime: TypeScript with object storage for images · the work is capture, image processing and a small player ### Data model (create this before Phase 1) - demos(id, title, state, created_at, published_at, redaction_cleared_at) - steps(id, demo_id, ordinal, image_key, viewport_json, click_point, annotation, transition) - hotspots(step_id, x, y, width, height, target_step_id, label) - detections(step_id, kind, bbox_json, confidence, resolved_as, resolved_by, at) · kind is email, name, number or face - redactions(step_id, bbox_json, method, applied_at) · applied to the stored image, recorded for audit - originals(step_id, key, deleted_at) · the unredacted capture, deleted rather than retained - A demo cannot reach a published state while any detection is unresolved, which is enforced in the publish path rather than by a reminder. ### Phase 1 · Capturing steps, not just screenshots Build: A browser extension capturing a screenshot and the click position on each interaction, with the viewport recorded. Handle scrolling, navigation and a page that changes under the pointer. Store steps in order. Trap: Capturing after the click means the screenshot shows the result rather than the state the user was looking at when they decided to click, so the hotspot lands on something that is no longer there. Capture before the interaction and record the position separately. Done when: Steps capture the screen state before each interaction with the click position recorded separately. Scrolling and navigation produce coherent ordered steps. A page that changes under the pointer does not produce a hotspot pointing at nothing. Captures are taken at a consistent resolution regardless of the recorder's screen. Do not build yet: No detection, redaction, editing or playback. ### Phase 2 · Finding what should not be published Build: Detect email addresses, names, long numbers and faces in captures, with bounding boxes. Present every detection for resolution. Detect across the whole image rather than only in expected regions. Trap: Detecting only in the areas you expect data to appear misses the browser tab title, the notification that popped up, the autocomplete dropdown and the name in the corner of the page, which are exactly where the accidents happen. Scan the whole image, and accept false positives as the cost of not missing one. Done when: Emails, names, long numbers and faces are detected across the whole capture including browser interface areas. Every detection is presented with its position for resolution. False positives can be dismissed and stay dismissed. A capture with no detections is distinguishable from one that was never scanned. Do not build yet: No redaction, editing or publishing yet. ### Phase 3 · Redaction that removes pixels Build: Apply redaction to the stored image irreversibly and delete the original. Verify the redacted region cannot be recovered from the stored file. Record what was redacted without recording its content. Trap: Drawing a black rectangle in the player leaves the original pixels in the stored file, so anyone who opens the image directly sees exactly what you thought you had removed, and images on a marketing site are trivially downloadable. Modify the image and delete the original. Done when: A redacted region cannot be recovered from the stored image, verified by examining the file directly. The unredacted original is deleted rather than retained. The redaction record notes the region and method without storing what was there. Blur is offered but pixel removal is the default, since blur is sometimes reversible. Do not build yet: No editing, publishing or playback yet. ### Phase 4 · A demo that tells a story Build: Edit the step sequence: reorder, remove, annotate and set hotspots. Add branching where a demo has more than one path. Detect a hotspot pointing at a step that no longer exists. Trap: A demo that is simply every captured click is too long and includes the three attempts it took to find the right menu, which is exactly what a prospect does not need to see. Make removing and reordering steps the primary editing action rather than an afterthought. Done when: Steps can be reordered, removed and annotated, and removal does not break hotspots pointing at them. Branching paths work and unreachable steps are reported. A demo of thirty captured clicks edits down to eight steps in a few minutes. Annotations do not obscure the content they describe. Do not build yet: No publishing or playback yet. ### Phase 5 · Publishing, blocked until it is clean Build: Block publication while any detection is unresolved, enforced in the publish path. Serve an embeddable player that is small and does not block the host page. Report step completion where the author enables it. Trap: Warning about unresolved detections and publishing anyway means the warning is dismissed by whoever is in a hurry, which is always. Block the publish, name the steps with unresolved detections, and make resolving them the only route forward. Done when: Publishing is refused while any detection is unresolved, with the affected steps named, tested directly. The embedded player is small, loads asynchronously and survives a host page with conflicting styles. Completion reporting is off by default and states what it records. A published demo's images carry no recoverable redacted content, checked again at publish. Do not build yet: Nothing after this. ### Out of scope (and why) - Recording video rather than steps, which has entirely different redaction problems and no reliable way to catch a frame you missed. - Capturing native desktop applications, which is a different platform integration per operating system. - Automatic narration or voiceover, which is a separate quality problem and often worse than silence. - Any guarantee that detection catches everything, which it will not, which is why publication is blocked on human resolution rather than on a clean scan. ### README must contain - That redaction modifies the stored image and deletes the original, because an overlay leaves the pixels in the file - That detection scans the whole capture including browser interface, where the accidents actually happen - That publication is blocked while any detection is unresolved rather than warning about it - That captures are taken before each interaction, so a hotspot lands on what was actually clicked - That detection will miss things, which is why a human resolves every one rather than trusting a clean scan ===== AGENTS.md ===== # Agent instructions · Arcade indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A browser extension recording steps as images with element positions, Applied to the stored image, irreversibly, Automatic identification of likely personal data in captures, A small player with hotspots derived from the recorded steps, TypeScript with object storage for images. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Capturing after the click means the screenshot shows the result rather than the state the user was looking at when they decided to click, so the hotspot lands on something that is no longer there. Capture before the interaction and record the position separately. - Detecting only in the areas you expect data to appear misses the browser tab title, the notification that popped up, the autocomplete dropdown and the name in the corner of the page, which are exactly where the accidents happen. Scan the whole image, and accept false positives as the cost of not missing one. - Drawing a black rectangle in the player leaves the original pixels in the stored file, so anyone who opens the image directly sees exactly what you thought you had removed, and images on a marketing site are trivially downloadable. Modify the image and delete the original. - A demo that is simply every captured click is too long and includes the three attempts it took to find the right menu, which is exactly what a prospect does not need to see. Make removing and reordering steps the primary editing action rather than an afterthought. ===== BUILD_PLAN.md ===== # Build plan · Arcade A demo builder that captures real screens and turns them into a clickable walkthrough, where the interesting work is stitching steps into something coherent and the critical work is making sure nothing in the captures should not be public. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Capturing steps, not just screenshots A recorded session becomes ordered steps with the click positions kept. ### Steps 1. Capture before the interaction Capturing after shows the result, not what was clicked. Files: `extension/capture.ts` 2. Record click position separately The hotspot needs it and the image cannot carry it. Files: `extension/capture.ts` 3. Normalise capture resolution A demo recorded on one screen must look right on every other. Files: `src/normalise.ts` ### Done when - [ ] Steps capture state before each interaction - [ ] Click positions are recorded separately - [ ] Scrolling and navigation stay coherent - [ ] Capture resolution is consistent ### Watch out - Capturing after the click means the screenshot shows the result rather than the state the user was looking at when they decided to click, so the hotspot lands on something that is no longer there. Capture before the interaction and record the position separately. ## Phase 2 · Finding what should not be published Likely personal data in every capture is detected and shown. ### Steps 1. Scan the whole image Tab titles, notifications and dropdowns are where the accidents are. Files: `src/detect.ts` 2. Report position per detection So resolution is a look rather than a search. Files: `src/detect.ts` 3. Distinguish clean from unscanned A capture nobody scanned should not look like a clean one. Files: `src/steps.ts` ### Done when - [ ] Detection covers the whole image including browser interface - [ ] Every detection carries a position - [ ] Dismissed false positives stay dismissed - [ ] Clean and unscanned are distinguishable ### Watch out - Detecting only in the areas you expect data to appear misses the browser tab title, the notification that popped up, the autocomplete dropdown and the name in the corner of the page, which are exactly where the accidents happen. Scan the whole image, and accept false positives as the cost of not missing one. ## Phase 3 · Redaction that removes pixels Redacted content is gone from the stored image, not covered. ### Steps 1. Modify the stored image An overlay leaves the pixels in the file. Files: `src/redact.ts`, `tests/redaction.test.ts` 2. Delete the original Retaining it means the disclosure risk is still on your disk. Files: `src/originals.ts` 3. Default to removal, not blur Some blurs are reversible. Removal is not. Files: `src/redact.ts` ### Done when - [ ] Redacted regions are unrecoverable from the file - [ ] Originals are deleted - [ ] Redaction records region and method, not content - [ ] Removal is the default over blur ### Watch out - Drawing a black rectangle in the player leaves the original pixels in the stored file, so anyone who opens the image directly sees exactly what you thought you had removed, and images on a marketing site are trivially downloadable. Modify the image and delete the original. ## Phase 4 · A demo that tells a story Captured steps become a walkthrough someone can follow. ### Steps 1. Make editing down the primary action Every captured click includes the three failed attempts. Files: `src/edit.ts` 2. Detect broken and unreachable steps Removing a step should not leave a hotspot pointing nowhere. Files: `src/validate.ts` 3. Keep annotations out of the way An annotation covering the thing it describes is worse than none. Files: `src/annotate.ts` ### Done when - [ ] Reordering and removal keep hotspots valid - [ ] Branching works and unreachable steps are reported - [ ] Thirty clicks edit to eight steps quickly - [ ] Annotations do not obscure their subject ### Watch out - A demo that is simply every captured click is too long and includes the three attempts it took to find the right menu, which is exactly what a prospect does not need to see. Make removing and reordering steps the primary editing action rather than an afterthought. ## Not in this build - Video recording rather than steps. - Native desktop application capture. - Automatic narration. - Any guarantee that detection is complete. ## After v1, if you want it - Variable substitution so one demo can show a prospect's own name, which needs its own care - Localised demos from one recording, since the redaction work should not be repeated per language - Analytics on where viewers stop, which is genuinely useful and needs an honest consent position ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required · secret. Demo structure and detection records. DATABASE_URL=postgres://localhost:5432/demos # Required. Redacted images. Originals are deleted rather than stored here. IMAGE_BUCKET=s3://demo-captures # Required. Removal rather than blur, since some blurs are reversible. REDACTION_METHOD=remove # Required. Present as a constant. A retained original is the disclosure still on your disk. KEEP_ORIGINALS=never # Required. Present as a constant. A warning is dismissed by whoever is in a hurry. PUBLISH_BLOCKS_ON_DETECTIONS=always # Required. Captures contain real customer data and should not be sent anywhere to be scanned. DETECTION_MODEL=local
You are building a production product version of Arcade. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== PRODUCT.md ===== # Arcade · product brief ## Problem The core loop is buildable, but a dependable replacement becomes a real weekend or multi-day project. For Arcade, build an interactive product story from captured screens and hotspots. The hard boundary is capture polish, hosted playback, analytics, personalization, and collaboration, plus capture polish, hosting, and collaboration. ## Product outcome Interactive demos built from real screens where redacted content is genuinely gone from the files, and a demo cannot be published while anything unresolved remains. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - macOS or Windows screen-recording permission - microphone permission - ffmpeg - local disk space ## Explicit non-goals for v1 - Video recording rather than steps. - Native desktop application capture. - Automatic narration. - Any guarantee that detection is complete. - capture polish, hosted playback, analytics, personalization, and collaboration - instant hosted sharing - viewer analytics - team libraries - cross-device capture ## Success criteria - Redacted regions are confirmed unrecoverable from the stored file - Originals are confirmed deleted - Detection is confirmed to cover browser interface areas - Publishing is confirmed refused with unresolved detections - The player is confirmed small and style isolated ===== BRIEF.md ===== # Build brief · Arcade The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me an interactive product demo built from captured screens, with the customer data taken out to replace Arcade. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Rule zero You are recording a working application, which means you are recording whatever was on the screen: real customer names in a list, an email address in the corner, a support ticket, a revenue figure. Demos get published on marketing sites and sent to prospects, so a missed redaction is a disclosure to everyone. So redaction happens on the captured image before it is stored, not as an overlay drawn on top at display time. An overlay is a rectangle over pixels that are still in the file, and anyone who downloads the image or reads the page source has the original. The build also detects likely personal data automatically and requires each detection to be resolved before a demo can be published, because the failure mode is not deciding to publish something sensitive, it is not noticing it was there. ### Stack (fixed, do not substitute) - Capture: A browser extension recording steps as images with element positions · hotspots need to know where the user clicked, not just what the screen looked like - Redaction: Applied to the stored image, irreversibly · an overlay leaves the original pixels in the file - Detection: Automatic identification of likely personal data in captures · the failure is not noticing rather than deciding - Playback: A small player with hotspots derived from the recorded steps · a demo embedded on a marketing page must not slow it down - Runtime: TypeScript with object storage for images · the work is capture, image processing and a small player ### Data model (create this before Phase 1) - demos(id, title, state, created_at, published_at, redaction_cleared_at) - steps(id, demo_id, ordinal, image_key, viewport_json, click_point, annotation, transition) - hotspots(step_id, x, y, width, height, target_step_id, label) - detections(step_id, kind, bbox_json, confidence, resolved_as, resolved_by, at) · kind is email, name, number or face - redactions(step_id, bbox_json, method, applied_at) · applied to the stored image, recorded for audit - originals(step_id, key, deleted_at) · the unredacted capture, deleted rather than retained - A demo cannot reach a published state while any detection is unresolved, which is enforced in the publish path rather than by a reminder. ### Phase 1 · Capturing steps, not just screenshots Build: A browser extension capturing a screenshot and the click position on each interaction, with the viewport recorded. Handle scrolling, navigation and a page that changes under the pointer. Store steps in order. Trap: Capturing after the click means the screenshot shows the result rather than the state the user was looking at when they decided to click, so the hotspot lands on something that is no longer there. Capture before the interaction and record the position separately. Done when: Steps capture the screen state before each interaction with the click position recorded separately. Scrolling and navigation produce coherent ordered steps. A page that changes under the pointer does not produce a hotspot pointing at nothing. Captures are taken at a consistent resolution regardless of the recorder's screen. Do not build yet: No detection, redaction, editing or playback. ### Phase 2 · Finding what should not be published Build: Detect email addresses, names, long numbers and faces in captures, with bounding boxes. Present every detection for resolution. Detect across the whole image rather than only in expected regions. Trap: Detecting only in the areas you expect data to appear misses the browser tab title, the notification that popped up, the autocomplete dropdown and the name in the corner of the page, which are exactly where the accidents happen. Scan the whole image, and accept false positives as the cost of not missing one. Done when: Emails, names, long numbers and faces are detected across the whole capture including browser interface areas. Every detection is presented with its position for resolution. False positives can be dismissed and stay dismissed. A capture with no detections is distinguishable from one that was never scanned. Do not build yet: No redaction, editing or publishing yet. ### Phase 3 · Redaction that removes pixels Build: Apply redaction to the stored image irreversibly and delete the original. Verify the redacted region cannot be recovered from the stored file. Record what was redacted without recording its content. Trap: Drawing a black rectangle in the player leaves the original pixels in the stored file, so anyone who opens the image directly sees exactly what you thought you had removed, and images on a marketing site are trivially downloadable. Modify the image and delete the original. Done when: A redacted region cannot be recovered from the stored image, verified by examining the file directly. The unredacted original is deleted rather than retained. The redaction record notes the region and method without storing what was there. Blur is offered but pixel removal is the default, since blur is sometimes reversible. Do not build yet: No editing, publishing or playback yet. ### Phase 4 · A demo that tells a story Build: Edit the step sequence: reorder, remove, annotate and set hotspots. Add branching where a demo has more than one path. Detect a hotspot pointing at a step that no longer exists. Trap: A demo that is simply every captured click is too long and includes the three attempts it took to find the right menu, which is exactly what a prospect does not need to see. Make removing and reordering steps the primary editing action rather than an afterthought. Done when: Steps can be reordered, removed and annotated, and removal does not break hotspots pointing at them. Branching paths work and unreachable steps are reported. A demo of thirty captured clicks edits down to eight steps in a few minutes. Annotations do not obscure the content they describe. Do not build yet: No publishing or playback yet. ### Phase 5 · Publishing, blocked until it is clean Build: Block publication while any detection is unresolved, enforced in the publish path. Serve an embeddable player that is small and does not block the host page. Report step completion where the author enables it. Trap: Warning about unresolved detections and publishing anyway means the warning is dismissed by whoever is in a hurry, which is always. Block the publish, name the steps with unresolved detections, and make resolving them the only route forward. Done when: Publishing is refused while any detection is unresolved, with the affected steps named, tested directly. The embedded player is small, loads asynchronously and survives a host page with conflicting styles. Completion reporting is off by default and states what it records. A published demo's images carry no recoverable redacted content, checked again at publish. Do not build yet: Nothing after this. ### Out of scope (and why) - Recording video rather than steps, which has entirely different redaction problems and no reliable way to catch a frame you missed. - Capturing native desktop applications, which is a different platform integration per operating system. - Automatic narration or voiceover, which is a separate quality problem and often worse than silence. - Any guarantee that detection catches everything, which it will not, which is why publication is blocked on human resolution rather than on a clean scan. ### README must contain - That redaction modifies the stored image and deletes the original, because an overlay leaves the pixels in the file - That detection scans the whole capture including browser interface, where the accidents actually happen - That publication is blocked while any detection is unresolved rather than warning about it - That captures are taken before each interaction, so a hotspot lands on what was actually clicked - That detection will miss things, which is why a human resolves every one rather than trusting a clean scan ===== ARCHITECTURE.md ===== # Architecture · Arcade ## Stack | Part | Choice | Why | | --- | --- | --- | | Capture | A browser extension recording steps as images with element positions | hotspots need to know where the user clicked, not just what the screen looked like | | Redaction | Applied to the stored image, irreversibly | an overlay leaves the original pixels in the file | | Detection | Automatic identification of likely personal data in captures | the failure is not noticing rather than deciding | | Playback | A small player with hotspots derived from the recorded steps | a demo embedded on a marketing page must not slow it down | | Runtime | TypeScript with object storage for images | the work is capture, image processing and a small player | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Capture | Pre-interaction screens with click positions. | Any recorder, provided the capture precedes the interaction. | | Detection | Whole-image scanning for personal data. | Any detector, provided it covers browser interface areas and runs locally. | | Redaction | Irreversible modification of stored images. | Not swappable for a display overlay, which leaves the pixels present. | | Editing | Reordering, removal and hotspot integrity. | Any interface, provided removal cannot orphan a hotspot. | | Publishing | The gate on unresolved detections. | Not swappable for a warning, which is dismissed under time pressure. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `DATABASE_URL` · required, secret · Demo structure and detection records. - `IMAGE_BUCKET` · required · Redacted images. Originals are deleted rather than stored here. - `REDACTION_METHOD` · required · Removal rather than blur, since some blurs are reversible. - `KEEP_ORIGINALS` · required · Present as a constant. A retained original is the disclosure still on your disk. - `PUBLISH_BLOCKS_ON_DETECTIONS` · required · Present as a constant. A warning is dismissed by whoever is in a hurry. - `DETECTION_MODEL` · required · Captures contain real customer data and should not be sent anywhere to be scanned. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it. ===== AGENTS.md ===== # Agent instructions · Arcade product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: A browser extension recording steps as images with element positions, Applied to the stored image, irreversibly, Automatic identification of likely personal data in captures, A small player with hotspots derived from the recorded steps, TypeScript with object storage for images. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - Capturing after the click means the screenshot shows the result rather than the state the user was looking at when they decided to click, so the hotspot lands on something that is no longer there. Capture before the interaction and record the position separately. - Detecting only in the areas you expect data to appear misses the browser tab title, the notification that popped up, the autocomplete dropdown and the name in the corner of the page, which are exactly where the accidents happen. Scan the whole image, and accept false positives as the cost of not missing one. - Drawing a black rectangle in the player leaves the original pixels in the stored file, so anyone who opens the image directly sees exactly what you thought you had removed, and images on a marketing site are trivially downloadable. Modify the image and delete the original. - A demo that is simply every captured click is too long and includes the three attempts it took to find the right menu, which is exactly what a prospect does not need to see. Make removing and reordering steps the primary editing action rather than an afterthought. - Warning about unresolved detections and publishing anyway means the warning is dismissed by whoever is in a hurry, which is always. Block the publish, name the steps with unresolved detections, and make resolving them the only route forward. ===== MILESTONES.md ===== # Delivery milestones · Arcade Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · Capturing steps, not just screenshots A recorded session becomes ordered steps with the click positions kept. ### Steps 1. Capture before the interaction Capturing after shows the result, not what was clicked. Files: `extension/capture.ts` 2. Record click position separately The hotspot needs it and the image cannot carry it. Files: `extension/capture.ts` 3. Normalise capture resolution A demo recorded on one screen must look right on every other. Files: `src/normalise.ts` ### Done when - [ ] Steps capture state before each interaction - [ ] Click positions are recorded separately - [ ] Scrolling and navigation stay coherent - [ ] Capture resolution is consistent ### Watch out - Capturing after the click means the screenshot shows the result rather than the state the user was looking at when they decided to click, so the hotspot lands on something that is no longer there. Capture before the interaction and record the position separately. ## M2 · Finding what should not be published Likely personal data in every capture is detected and shown. ### Steps 1. Scan the whole image Tab titles, notifications and dropdowns are where the accidents are. Files: `src/detect.ts` 2. Report position per detection So resolution is a look rather than a search. Files: `src/detect.ts` 3. Distinguish clean from unscanned A capture nobody scanned should not look like a clean one. Files: `src/steps.ts` ### Done when - [ ] Detection covers the whole image including browser interface - [ ] Every detection carries a position - [ ] Dismissed false positives stay dismissed - [ ] Clean and unscanned are distinguishable ### Watch out - Detecting only in the areas you expect data to appear misses the browser tab title, the notification that popped up, the autocomplete dropdown and the name in the corner of the page, which are exactly where the accidents happen. Scan the whole image, and accept false positives as the cost of not missing one. ## M3 · Redaction that removes pixels Redacted content is gone from the stored image, not covered. ### Steps 1. Modify the stored image An overlay leaves the pixels in the file. Files: `src/redact.ts`, `tests/redaction.test.ts` 2. Delete the original Retaining it means the disclosure risk is still on your disk. Files: `src/originals.ts` 3. Default to removal, not blur Some blurs are reversible. Removal is not. Files: `src/redact.ts` ### Done when - [ ] Redacted regions are unrecoverable from the file - [ ] Originals are deleted - [ ] Redaction records region and method, not content - [ ] Removal is the default over blur ### Watch out - Drawing a black rectangle in the player leaves the original pixels in the stored file, so anyone who opens the image directly sees exactly what you thought you had removed, and images on a marketing site are trivially downloadable. Modify the image and delete the original. ## M4 · A demo that tells a story Captured steps become a walkthrough someone can follow. ### Steps 1. Make editing down the primary action Every captured click includes the three failed attempts. Files: `src/edit.ts` 2. Detect broken and unreachable steps Removing a step should not leave a hotspot pointing nowhere. Files: `src/validate.ts` 3. Keep annotations out of the way An annotation covering the thing it describes is worse than none. Files: `src/annotate.ts` ### Done when - [ ] Reordering and removal keep hotspots valid - [ ] Branching works and unreachable steps are reported - [ ] Thirty clicks edit to eight steps quickly - [ ] Annotations do not obscure their subject ### Watch out - A demo that is simply every captured click is too long and includes the three attempts it took to find the right menu, which is exactly what a prospect does not need to see. Make removing and reordering steps the primary editing action rather than an afterthought. ## M5 · Publishing, blocked until it is clean (production only) A demo cannot be published with an unresolved detection. ### Steps 1. Block publish on unresolved detections A warning is dismissed by whoever is in a hurry, which is everyone. Files: `src/publish.ts`, `tests/publish-block.test.ts` 2. Recheck redaction at publish The last moment before it becomes public is worth one more check. Files: `src/publish.ts` 3. Keep the player small and isolated It sits on a marketing page belonging to someone else. Files: `player/` ### Done when - [ ] Publishing is refused with unresolved detections - [ ] The player is small, asynchronous and style isolated - [ ] Completion reporting is off by default - [ ] Redaction is rechecked at publish ### Watch out - Warning about unresolved detections and publishing anyway means the warning is dismissed by whoever is in a hurry, which is always. Block the publish, name the steps with unresolved detections, and make resolving them the only route forward. ===== OPERATIONS.md ===== # Operations · Arcade ## Backup Redacted images and demo structure are the artefacts. Originals should not exist to back up, and if your backup contains them the deletion policy is not working. ## Restore Restore and confirm no unredacted originals returned, since a backup taken before deletion would reintroduce exactly the images the redaction removed. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring Detections resolved as acceptable is the number worth watching. A rising rate usually means someone is clearing detections to publish rather than redacting them. ## Incident checklist Customer data visible in a published demo is the failure, and the cause is nearly always an overlay rather than a redaction, or a detection dismissed in a hurry. The redaction audit records which. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Redacted regions are confirmed unrecoverable from the stored file - [ ] Originals are confirmed deleted - [ ] Detection is confirmed to cover browser interface areas - [ ] Publishing is confirmed refused with unresolved detections - [ ] The player is confirmed small and style isolated ## Launch constraint Do not market omitted Arcade capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered. ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required · secret. Demo structure and detection records. DATABASE_URL=postgres://localhost:5432/demos # Required. Redacted images. Originals are deleted rather than stored here. IMAGE_BUCKET=s3://demo-captures # Required. Removal rather than blur, since some blurs are reversible. REDACTION_METHOD=remove # Required. Present as a constant. A retained original is the disclosure still on your disk. KEEP_ORIGINALS=never # Required. Present as a constant. A warning is dismissed by whoever is in a hurry. PUBLISH_BLOCKS_ON_DETECTIONS=always # Required. Captures contain real customer data and should not be sent anywhere to be scanned. DETECTION_MODEL=local
# Arcade · indie build A demo builder that captures real screens and turns them into a clickable walkthrough, where the interesting work is stitching steps into something coherent and the critical work is making sure nothing in the captures should not be public. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Capture | A browser extension recording steps as images with element positions | hotspots need to know where the user clicked, not just what the screen looked like | | Redaction | Applied to the stored image, irreversibly | an overlay leaves the original pixels in the file | | Detection | Automatic identification of likely personal data in captures | the failure is not noticing rather than deciding | | Playback | A small player with hotspots derived from the recorded steps | a demo embedded on a marketing page must not slow it down | | Runtime | TypeScript with object storage for images | the work is capture, image processing and a small player | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the server, the image pipeline and the player build. - Get it: nodejs.org, or nvm install 22. - Verify: node --version prints v22 or higher - [ ] **An image processing library** · free - Why: Redaction modifies pixels and must be irreversible, which is image work rather than a display concern. - Get it: Any library that can modify and re-encode images reliably at capture resolution. - Verify: A redacted region is unrecoverable from the re-encoded file - [ ] **Text and face detection you can run locally** · free, needs machine time - Why: Captures contain real customer data and sending them to a service for scanning is the disclosure you are trying to prevent. - Get it: A local text recognition model and a face detector, evaluated on real screenshots rather than photographs. - Verify: Text in a browser tab title and a name in a table are both detected - [ ] **A real application with realistic data** · free - Why: Detection quality and the places sensitive data actually appears can only be assessed against a real interface with real-looking records. - Get it: A staging environment with realistic rather than obviously fake data, since fake data hides the problem. - Verify: A recorded session contains at least five genuine detections - [ ] **What must never appear in a published demo** · free - Why: The publish gate blocks on unresolved detections, and what counts as needing resolution is a decision that belongs before the first demo rather than during a review. - Get it: List the categories that must always be redacted and who may resolve a detection as acceptable. - Verify: A written list exists and the detector covers every category on it ## Quick start Follow Phase 1 in `BUILD_PLAN.md`; it creates the project. Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Video recording rather than steps. - Native desktop application capture. - Automatic narration. - Any guarantee that detection is complete. - capture polish, hosted playback, analytics, personalization, and collaboration - instant hosted sharing - viewer analytics - team libraries - cross-device capture If one of those is essential to you, that is the reason to keep paying for Arcade, and the README should say so rather than pretend.
# Build brief · Arcade The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me an interactive product demo built from captured screens, with the customer data taken out to replace Arcade. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Rule zero You are recording a working application, which means you are recording whatever was on the screen: real customer names in a list, an email address in the corner, a support ticket, a revenue figure. Demos get published on marketing sites and sent to prospects, so a missed redaction is a disclosure to everyone. So redaction happens on the captured image before it is stored, not as an overlay drawn on top at display time. An overlay is a rectangle over pixels that are still in the file, and anyone who downloads the image or reads the page source has the original. The build also detects likely personal data automatically and requires each detection to be resolved before a demo can be published, because the failure mode is not deciding to publish something sensitive, it is not noticing it was there. ### Stack (fixed, do not substitute) - Capture: A browser extension recording steps as images with element positions · hotspots need to know where the user clicked, not just what the screen looked like - Redaction: Applied to the stored image, irreversibly · an overlay leaves the original pixels in the file - Detection: Automatic identification of likely personal data in captures · the failure is not noticing rather than deciding - Playback: A small player with hotspots derived from the recorded steps · a demo embedded on a marketing page must not slow it down - Runtime: TypeScript with object storage for images · the work is capture, image processing and a small player ### Data model (create this before Phase 1) - demos(id, title, state, created_at, published_at, redaction_cleared_at) - steps(id, demo_id, ordinal, image_key, viewport_json, click_point, annotation, transition) - hotspots(step_id, x, y, width, height, target_step_id, label) - detections(step_id, kind, bbox_json, confidence, resolved_as, resolved_by, at) · kind is email, name, number or face - redactions(step_id, bbox_json, method, applied_at) · applied to the stored image, recorded for audit - originals(step_id, key, deleted_at) · the unredacted capture, deleted rather than retained - A demo cannot reach a published state while any detection is unresolved, which is enforced in the publish path rather than by a reminder. ### Phase 1 · Capturing steps, not just screenshots Build: A browser extension capturing a screenshot and the click position on each interaction, with the viewport recorded. Handle scrolling, navigation and a page that changes under the pointer. Store steps in order. Trap: Capturing after the click means the screenshot shows the result rather than the state the user was looking at when they decided to click, so the hotspot lands on something that is no longer there. Capture before the interaction and record the position separately. Done when: Steps capture the screen state before each interaction with the click position recorded separately. Scrolling and navigation produce coherent ordered steps. A page that changes under the pointer does not produce a hotspot pointing at nothing. Captures are taken at a consistent resolution regardless of the recorder's screen. Do not build yet: No detection, redaction, editing or playback. ### Phase 2 · Finding what should not be published Build: Detect email addresses, names, long numbers and faces in captures, with bounding boxes. Present every detection for resolution. Detect across the whole image rather than only in expected regions. Trap: Detecting only in the areas you expect data to appear misses the browser tab title, the notification that popped up, the autocomplete dropdown and the name in the corner of the page, which are exactly where the accidents happen. Scan the whole image, and accept false positives as the cost of not missing one. Done when: Emails, names, long numbers and faces are detected across the whole capture including browser interface areas. Every detection is presented with its position for resolution. False positives can be dismissed and stay dismissed. A capture with no detections is distinguishable from one that was never scanned. Do not build yet: No redaction, editing or publishing yet. ### Phase 3 · Redaction that removes pixels Build: Apply redaction to the stored image irreversibly and delete the original. Verify the redacted region cannot be recovered from the stored file. Record what was redacted without recording its content. Trap: Drawing a black rectangle in the player leaves the original pixels in the stored file, so anyone who opens the image directly sees exactly what you thought you had removed, and images on a marketing site are trivially downloadable. Modify the image and delete the original. Done when: A redacted region cannot be recovered from the stored image, verified by examining the file directly. The unredacted original is deleted rather than retained. The redaction record notes the region and method without storing what was there. Blur is offered but pixel removal is the default, since blur is sometimes reversible. Do not build yet: No editing, publishing or playback yet. ### Phase 4 · A demo that tells a story Build: Edit the step sequence: reorder, remove, annotate and set hotspots. Add branching where a demo has more than one path. Detect a hotspot pointing at a step that no longer exists. Trap: A demo that is simply every captured click is too long and includes the three attempts it took to find the right menu, which is exactly what a prospect does not need to see. Make removing and reordering steps the primary editing action rather than an afterthought. Done when: Steps can be reordered, removed and annotated, and removal does not break hotspots pointing at them. Branching paths work and unreachable steps are reported. A demo of thirty captured clicks edits down to eight steps in a few minutes. Annotations do not obscure the content they describe. Do not build yet: No publishing or playback yet. ### Phase 5 · Publishing, blocked until it is clean Build: Block publication while any detection is unresolved, enforced in the publish path. Serve an embeddable player that is small and does not block the host page. Report step completion where the author enables it. Trap: Warning about unresolved detections and publishing anyway means the warning is dismissed by whoever is in a hurry, which is always. Block the publish, name the steps with unresolved detections, and make resolving them the only route forward. Done when: Publishing is refused while any detection is unresolved, with the affected steps named, tested directly. The embedded player is small, loads asynchronously and survives a host page with conflicting styles. Completion reporting is off by default and states what it records. A published demo's images carry no recoverable redacted content, checked again at publish. Do not build yet: Nothing after this. ### Out of scope (and why) - Recording video rather than steps, which has entirely different redaction problems and no reliable way to catch a frame you missed. - Capturing native desktop applications, which is a different platform integration per operating system. - Automatic narration or voiceover, which is a separate quality problem and often worse than silence. - Any guarantee that detection catches everything, which it will not, which is why publication is blocked on human resolution rather than on a clean scan. ### README must contain - That redaction modifies the stored image and deletes the original, because an overlay leaves the pixels in the file - That detection scans the whole capture including browser interface, where the accidents actually happen - That publication is blocked while any detection is unresolved rather than warning about it - That captures are taken before each interaction, so a hotspot lands on what was actually clicked - That detection will miss things, which is why a human resolves every one rather than trusting a clean scan
# Agent instructions · Arcade indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A browser extension recording steps as images with element positions, Applied to the stored image, irreversibly, Automatic identification of likely personal data in captures, A small player with hotspots derived from the recorded steps, TypeScript with object storage for images. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Capturing after the click means the screenshot shows the result rather than the state the user was looking at when they decided to click, so the hotspot lands on something that is no longer there. Capture before the interaction and record the position separately. - Detecting only in the areas you expect data to appear misses the browser tab title, the notification that popped up, the autocomplete dropdown and the name in the corner of the page, which are exactly where the accidents happen. Scan the whole image, and accept false positives as the cost of not missing one. - Drawing a black rectangle in the player leaves the original pixels in the stored file, so anyone who opens the image directly sees exactly what you thought you had removed, and images on a marketing site are trivially downloadable. Modify the image and delete the original. - A demo that is simply every captured click is too long and includes the three attempts it took to find the right menu, which is exactly what a prospect does not need to see. Make removing and reordering steps the primary editing action rather than an afterthought.
# Build plan · Arcade A demo builder that captures real screens and turns them into a clickable walkthrough, where the interesting work is stitching steps into something coherent and the critical work is making sure nothing in the captures should not be public. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · Capturing steps, not just screenshots A recorded session becomes ordered steps with the click positions kept. ### Steps 1. Capture before the interaction Capturing after shows the result, not what was clicked. Files: `extension/capture.ts` 2. Record click position separately The hotspot needs it and the image cannot carry it. Files: `extension/capture.ts` 3. Normalise capture resolution A demo recorded on one screen must look right on every other. Files: `src/normalise.ts` ### Done when - [ ] Steps capture state before each interaction - [ ] Click positions are recorded separately - [ ] Scrolling and navigation stay coherent - [ ] Capture resolution is consistent ### Watch out - Capturing after the click means the screenshot shows the result rather than the state the user was looking at when they decided to click, so the hotspot lands on something that is no longer there. Capture before the interaction and record the position separately. ## Phase 2 · Finding what should not be published Likely personal data in every capture is detected and shown. ### Steps 1. Scan the whole image Tab titles, notifications and dropdowns are where the accidents are. Files: `src/detect.ts` 2. Report position per detection So resolution is a look rather than a search. Files: `src/detect.ts` 3. Distinguish clean from unscanned A capture nobody scanned should not look like a clean one. Files: `src/steps.ts` ### Done when - [ ] Detection covers the whole image including browser interface - [ ] Every detection carries a position - [ ] Dismissed false positives stay dismissed - [ ] Clean and unscanned are distinguishable ### Watch out - Detecting only in the areas you expect data to appear misses the browser tab title, the notification that popped up, the autocomplete dropdown and the name in the corner of the page, which are exactly where the accidents happen. Scan the whole image, and accept false positives as the cost of not missing one. ## Phase 3 · Redaction that removes pixels Redacted content is gone from the stored image, not covered. ### Steps 1. Modify the stored image An overlay leaves the pixels in the file. Files: `src/redact.ts`, `tests/redaction.test.ts` 2. Delete the original Retaining it means the disclosure risk is still on your disk. Files: `src/originals.ts` 3. Default to removal, not blur Some blurs are reversible. Removal is not. Files: `src/redact.ts` ### Done when - [ ] Redacted regions are unrecoverable from the file - [ ] Originals are deleted - [ ] Redaction records region and method, not content - [ ] Removal is the default over blur ### Watch out - Drawing a black rectangle in the player leaves the original pixels in the stored file, so anyone who opens the image directly sees exactly what you thought you had removed, and images on a marketing site are trivially downloadable. Modify the image and delete the original. ## Phase 4 · A demo that tells a story Captured steps become a walkthrough someone can follow. ### Steps 1. Make editing down the primary action Every captured click includes the three failed attempts. Files: `src/edit.ts` 2. Detect broken and unreachable steps Removing a step should not leave a hotspot pointing nowhere. Files: `src/validate.ts` 3. Keep annotations out of the way An annotation covering the thing it describes is worse than none. Files: `src/annotate.ts` ### Done when - [ ] Reordering and removal keep hotspots valid - [ ] Branching works and unreachable steps are reported - [ ] Thirty clicks edit to eight steps quickly - [ ] Annotations do not obscure their subject ### Watch out - A demo that is simply every captured click is too long and includes the three attempts it took to find the right menu, which is exactly what a prospect does not need to see. Make removing and reordering steps the primary editing action rather than an afterthought. ## Not in this build - Video recording rather than steps. - Native desktop application capture. - Automatic narration. - Any guarantee that detection is complete. ## After v1, if you want it - Variable substitution so one demo can show a prospect's own name, which needs its own care - Localised demos from one recording, since the redaction work should not be repeated per language - Analytics on where viewers stop, which is genuinely useful and needs an honest consent position
# Copy to .env and fill in. Never commit .env; this file documents it. # Required · secret. Demo structure and detection records. DATABASE_URL=postgres://localhost:5432/demos # Required. Redacted images. Originals are deleted rather than stored here. IMAGE_BUCKET=s3://demo-captures # Required. Removal rather than blur, since some blurs are reversible. REDACTION_METHOD=remove # Required. Present as a constant. A retained original is the disclosure still on your disk. KEEP_ORIGINALS=never # Required. Present as a constant. A warning is dismissed by whoever is in a hurry. PUBLISH_BLOCKS_ON_DETECTIONS=always # Required. Captures contain real customer data and should not be sent anywhere to be scanned. DETECTION_MODEL=local
# Arcade · product brief ## Problem The core loop is buildable, but a dependable replacement becomes a real weekend or multi-day project. For Arcade, build an interactive product story from captured screens and hotspots. The hard boundary is capture polish, hosted playback, analytics, personalization, and collaboration, plus capture polish, hosting, and collaboration. ## Product outcome Interactive demos built from real screens where redacted content is genuinely gone from the files, and a demo cannot be published while anything unresolved remains. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - macOS or Windows screen-recording permission - microphone permission - ffmpeg - local disk space ## Explicit non-goals for v1 - Video recording rather than steps. - Native desktop application capture. - Automatic narration. - Any guarantee that detection is complete. - capture polish, hosted playback, analytics, personalization, and collaboration - instant hosted sharing - viewer analytics - team libraries - cross-device capture ## Success criteria - Redacted regions are confirmed unrecoverable from the stored file - Originals are confirmed deleted - Detection is confirmed to cover browser interface areas - Publishing is confirmed refused with unresolved detections - The player is confirmed small and style isolated
# Build brief · Arcade The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me an interactive product demo built from captured screens, with the customer data taken out to replace Arcade. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Rule zero You are recording a working application, which means you are recording whatever was on the screen: real customer names in a list, an email address in the corner, a support ticket, a revenue figure. Demos get published on marketing sites and sent to prospects, so a missed redaction is a disclosure to everyone. So redaction happens on the captured image before it is stored, not as an overlay drawn on top at display time. An overlay is a rectangle over pixels that are still in the file, and anyone who downloads the image or reads the page source has the original. The build also detects likely personal data automatically and requires each detection to be resolved before a demo can be published, because the failure mode is not deciding to publish something sensitive, it is not noticing it was there. ### Stack (fixed, do not substitute) - Capture: A browser extension recording steps as images with element positions · hotspots need to know where the user clicked, not just what the screen looked like - Redaction: Applied to the stored image, irreversibly · an overlay leaves the original pixels in the file - Detection: Automatic identification of likely personal data in captures · the failure is not noticing rather than deciding - Playback: A small player with hotspots derived from the recorded steps · a demo embedded on a marketing page must not slow it down - Runtime: TypeScript with object storage for images · the work is capture, image processing and a small player ### Data model (create this before Phase 1) - demos(id, title, state, created_at, published_at, redaction_cleared_at) - steps(id, demo_id, ordinal, image_key, viewport_json, click_point, annotation, transition) - hotspots(step_id, x, y, width, height, target_step_id, label) - detections(step_id, kind, bbox_json, confidence, resolved_as, resolved_by, at) · kind is email, name, number or face - redactions(step_id, bbox_json, method, applied_at) · applied to the stored image, recorded for audit - originals(step_id, key, deleted_at) · the unredacted capture, deleted rather than retained - A demo cannot reach a published state while any detection is unresolved, which is enforced in the publish path rather than by a reminder. ### Phase 1 · Capturing steps, not just screenshots Build: A browser extension capturing a screenshot and the click position on each interaction, with the viewport recorded. Handle scrolling, navigation and a page that changes under the pointer. Store steps in order. Trap: Capturing after the click means the screenshot shows the result rather than the state the user was looking at when they decided to click, so the hotspot lands on something that is no longer there. Capture before the interaction and record the position separately. Done when: Steps capture the screen state before each interaction with the click position recorded separately. Scrolling and navigation produce coherent ordered steps. A page that changes under the pointer does not produce a hotspot pointing at nothing. Captures are taken at a consistent resolution regardless of the recorder's screen. Do not build yet: No detection, redaction, editing or playback. ### Phase 2 · Finding what should not be published Build: Detect email addresses, names, long numbers and faces in captures, with bounding boxes. Present every detection for resolution. Detect across the whole image rather than only in expected regions. Trap: Detecting only in the areas you expect data to appear misses the browser tab title, the notification that popped up, the autocomplete dropdown and the name in the corner of the page, which are exactly where the accidents happen. Scan the whole image, and accept false positives as the cost of not missing one. Done when: Emails, names, long numbers and faces are detected across the whole capture including browser interface areas. Every detection is presented with its position for resolution. False positives can be dismissed and stay dismissed. A capture with no detections is distinguishable from one that was never scanned. Do not build yet: No redaction, editing or publishing yet. ### Phase 3 · Redaction that removes pixels Build: Apply redaction to the stored image irreversibly and delete the original. Verify the redacted region cannot be recovered from the stored file. Record what was redacted without recording its content. Trap: Drawing a black rectangle in the player leaves the original pixels in the stored file, so anyone who opens the image directly sees exactly what you thought you had removed, and images on a marketing site are trivially downloadable. Modify the image and delete the original. Done when: A redacted region cannot be recovered from the stored image, verified by examining the file directly. The unredacted original is deleted rather than retained. The redaction record notes the region and method without storing what was there. Blur is offered but pixel removal is the default, since blur is sometimes reversible. Do not build yet: No editing, publishing or playback yet. ### Phase 4 · A demo that tells a story Build: Edit the step sequence: reorder, remove, annotate and set hotspots. Add branching where a demo has more than one path. Detect a hotspot pointing at a step that no longer exists. Trap: A demo that is simply every captured click is too long and includes the three attempts it took to find the right menu, which is exactly what a prospect does not need to see. Make removing and reordering steps the primary editing action rather than an afterthought. Done when: Steps can be reordered, removed and annotated, and removal does not break hotspots pointing at them. Branching paths work and unreachable steps are reported. A demo of thirty captured clicks edits down to eight steps in a few minutes. Annotations do not obscure the content they describe. Do not build yet: No publishing or playback yet. ### Phase 5 · Publishing, blocked until it is clean Build: Block publication while any detection is unresolved, enforced in the publish path. Serve an embeddable player that is small and does not block the host page. Report step completion where the author enables it. Trap: Warning about unresolved detections and publishing anyway means the warning is dismissed by whoever is in a hurry, which is always. Block the publish, name the steps with unresolved detections, and make resolving them the only route forward. Done when: Publishing is refused while any detection is unresolved, with the affected steps named, tested directly. The embedded player is small, loads asynchronously and survives a host page with conflicting styles. Completion reporting is off by default and states what it records. A published demo's images carry no recoverable redacted content, checked again at publish. Do not build yet: Nothing after this. ### Out of scope (and why) - Recording video rather than steps, which has entirely different redaction problems and no reliable way to catch a frame you missed. - Capturing native desktop applications, which is a different platform integration per operating system. - Automatic narration or voiceover, which is a separate quality problem and often worse than silence. - Any guarantee that detection catches everything, which it will not, which is why publication is blocked on human resolution rather than on a clean scan. ### README must contain - That redaction modifies the stored image and deletes the original, because an overlay leaves the pixels in the file - That detection scans the whole capture including browser interface, where the accidents actually happen - That publication is blocked while any detection is unresolved rather than warning about it - That captures are taken before each interaction, so a hotspot lands on what was actually clicked - That detection will miss things, which is why a human resolves every one rather than trusting a clean scan
# Architecture · Arcade ## Stack | Part | Choice | Why | | --- | --- | --- | | Capture | A browser extension recording steps as images with element positions | hotspots need to know where the user clicked, not just what the screen looked like | | Redaction | Applied to the stored image, irreversibly | an overlay leaves the original pixels in the file | | Detection | Automatic identification of likely personal data in captures | the failure is not noticing rather than deciding | | Playback | A small player with hotspots derived from the recorded steps | a demo embedded on a marketing page must not slow it down | | Runtime | TypeScript with object storage for images | the work is capture, image processing and a small player | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Capture | Pre-interaction screens with click positions. | Any recorder, provided the capture precedes the interaction. | | Detection | Whole-image scanning for personal data. | Any detector, provided it covers browser interface areas and runs locally. | | Redaction | Irreversible modification of stored images. | Not swappable for a display overlay, which leaves the pixels present. | | Editing | Reordering, removal and hotspot integrity. | Any interface, provided removal cannot orphan a hotspot. | | Publishing | The gate on unresolved detections. | Not swappable for a warning, which is dismissed under time pressure. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `DATABASE_URL` · required, secret · Demo structure and detection records. - `IMAGE_BUCKET` · required · Redacted images. Originals are deleted rather than stored here. - `REDACTION_METHOD` · required · Removal rather than blur, since some blurs are reversible. - `KEEP_ORIGINALS` · required · Present as a constant. A retained original is the disclosure still on your disk. - `PUBLISH_BLOCKS_ON_DETECTIONS` · required · Present as a constant. A warning is dismissed by whoever is in a hurry. - `DETECTION_MODEL` · required · Captures contain real customer data and should not be sent anywhere to be scanned. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it.
# Agent instructions · Arcade product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: A browser extension recording steps as images with element positions, Applied to the stored image, irreversibly, Automatic identification of likely personal data in captures, A small player with hotspots derived from the recorded steps, TypeScript with object storage for images. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - Capturing after the click means the screenshot shows the result rather than the state the user was looking at when they decided to click, so the hotspot lands on something that is no longer there. Capture before the interaction and record the position separately. - Detecting only in the areas you expect data to appear misses the browser tab title, the notification that popped up, the autocomplete dropdown and the name in the corner of the page, which are exactly where the accidents happen. Scan the whole image, and accept false positives as the cost of not missing one. - Drawing a black rectangle in the player leaves the original pixels in the stored file, so anyone who opens the image directly sees exactly what you thought you had removed, and images on a marketing site are trivially downloadable. Modify the image and delete the original. - A demo that is simply every captured click is too long and includes the three attempts it took to find the right menu, which is exactly what a prospect does not need to see. Make removing and reordering steps the primary editing action rather than an afterthought. - Warning about unresolved detections and publishing anyway means the warning is dismissed by whoever is in a hurry, which is always. Block the publish, name the steps with unresolved detections, and make resolving them the only route forward.
# Delivery milestones · Arcade Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · Capturing steps, not just screenshots A recorded session becomes ordered steps with the click positions kept. ### Steps 1. Capture before the interaction Capturing after shows the result, not what was clicked. Files: `extension/capture.ts` 2. Record click position separately The hotspot needs it and the image cannot carry it. Files: `extension/capture.ts` 3. Normalise capture resolution A demo recorded on one screen must look right on every other. Files: `src/normalise.ts` ### Done when - [ ] Steps capture state before each interaction - [ ] Click positions are recorded separately - [ ] Scrolling and navigation stay coherent - [ ] Capture resolution is consistent ### Watch out - Capturing after the click means the screenshot shows the result rather than the state the user was looking at when they decided to click, so the hotspot lands on something that is no longer there. Capture before the interaction and record the position separately. ## M2 · Finding what should not be published Likely personal data in every capture is detected and shown. ### Steps 1. Scan the whole image Tab titles, notifications and dropdowns are where the accidents are. Files: `src/detect.ts` 2. Report position per detection So resolution is a look rather than a search. Files: `src/detect.ts` 3. Distinguish clean from unscanned A capture nobody scanned should not look like a clean one. Files: `src/steps.ts` ### Done when - [ ] Detection covers the whole image including browser interface - [ ] Every detection carries a position - [ ] Dismissed false positives stay dismissed - [ ] Clean and unscanned are distinguishable ### Watch out - Detecting only in the areas you expect data to appear misses the browser tab title, the notification that popped up, the autocomplete dropdown and the name in the corner of the page, which are exactly where the accidents happen. Scan the whole image, and accept false positives as the cost of not missing one. ## M3 · Redaction that removes pixels Redacted content is gone from the stored image, not covered. ### Steps 1. Modify the stored image An overlay leaves the pixels in the file. Files: `src/redact.ts`, `tests/redaction.test.ts` 2. Delete the original Retaining it means the disclosure risk is still on your disk. Files: `src/originals.ts` 3. Default to removal, not blur Some blurs are reversible. Removal is not. Files: `src/redact.ts` ### Done when - [ ] Redacted regions are unrecoverable from the file - [ ] Originals are deleted - [ ] Redaction records region and method, not content - [ ] Removal is the default over blur ### Watch out - Drawing a black rectangle in the player leaves the original pixels in the stored file, so anyone who opens the image directly sees exactly what you thought you had removed, and images on a marketing site are trivially downloadable. Modify the image and delete the original. ## M4 · A demo that tells a story Captured steps become a walkthrough someone can follow. ### Steps 1. Make editing down the primary action Every captured click includes the three failed attempts. Files: `src/edit.ts` 2. Detect broken and unreachable steps Removing a step should not leave a hotspot pointing nowhere. Files: `src/validate.ts` 3. Keep annotations out of the way An annotation covering the thing it describes is worse than none. Files: `src/annotate.ts` ### Done when - [ ] Reordering and removal keep hotspots valid - [ ] Branching works and unreachable steps are reported - [ ] Thirty clicks edit to eight steps quickly - [ ] Annotations do not obscure their subject ### Watch out - A demo that is simply every captured click is too long and includes the three attempts it took to find the right menu, which is exactly what a prospect does not need to see. Make removing and reordering steps the primary editing action rather than an afterthought. ## M5 · Publishing, blocked until it is clean (production only) A demo cannot be published with an unresolved detection. ### Steps 1. Block publish on unresolved detections A warning is dismissed by whoever is in a hurry, which is everyone. Files: `src/publish.ts`, `tests/publish-block.test.ts` 2. Recheck redaction at publish The last moment before it becomes public is worth one more check. Files: `src/publish.ts` 3. Keep the player small and isolated It sits on a marketing page belonging to someone else. Files: `player/` ### Done when - [ ] Publishing is refused with unresolved detections - [ ] The player is small, asynchronous and style isolated - [ ] Completion reporting is off by default - [ ] Redaction is rechecked at publish ### Watch out - Warning about unresolved detections and publishing anyway means the warning is dismissed by whoever is in a hurry, which is always. Block the publish, name the steps with unresolved detections, and make resolving them the only route forward.
# Operations · Arcade ## Backup Redacted images and demo structure are the artefacts. Originals should not exist to back up, and if your backup contains them the deletion policy is not working. ## Restore Restore and confirm no unredacted originals returned, since a backup taken before deletion would reintroduce exactly the images the redaction removed. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring Detections resolved as acceptable is the number worth watching. A rising rate usually means someone is clearing detections to publish rather than redacting them. ## Incident checklist Customer data visible in a published demo is the failure, and the cause is nearly always an overlay rather than a redaction, or a detection dismissed in a hurry. The redaction audit records which. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Redacted regions are confirmed unrecoverable from the stored file - [ ] Originals are confirmed deleted - [ ] Detection is confirmed to cover browser interface areas - [ ] Publishing is confirmed refused with unresolved detections - [ ] The player is confirmed small and style isolated ## Launch constraint Do not market omitted Arcade capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered.
# Copy to .env and fill in. Never commit .env; this file documents it. # Required · secret. Demo structure and detection records. DATABASE_URL=postgres://localhost:5432/demos # Required. Redacted images. Originals are deleted rather than stored here. IMAGE_BUCKET=s3://demo-captures # Required. Removal rather than blur, since some blurs are reversible. REDACTION_METHOD=remove # Required. Present as a constant. A retained original is the disclosure still on your disk. KEEP_ORIGINALS=never # Required. Present as a constant. A warning is dismissed by whoever is in a hurry. PUBLISH_BLOCKS_ON_DETECTIONS=always # Required. Captures contain real customer data and should not be sent anywhere to be scanned. DETECTION_MODEL=local
$ choose a build depth, inspect the files, then open the complete pack in your agent
People still pay for Arcade because the recording itself is easy; the subscription removes upload, transcoding, sharing, organization, and support work. The recurring cost buys OS permissions, codecs, rendering performance, uploads, storage, links, and viewer analytics, not just the visible interface.
xcapture polish, hosted playback, analytics, personalization, and collaboration
xinstant hosted sharing
xviewer analytics
xteam libraries
xcross-device capture
Arcade pricing
| plan | monthly | annual (per mo) | what you get |
|---|---|---|---|
| free | $0/workspace | $0/workspace | 1 user; 1 published interactive demo plus 1 video; unlimited views; 200 AI credits/month |
| growth | $50/user | $42.50/user | Up to 10 users; unlimited demos and videos; 800 AI credits/month; 1 brand kit |
| enterprise | custom | — | Custom users, demos, security and support; up to 10 brand kits and 100,000 AI credits/year |
free tier1 user, 1 published interactive demo, 1 published video, unlimited views and 200 AI credits/month
billingmonthly + annual; paid creators are seat-based
hidden costsVideos and generated visuals consume credits, roughly 50 credits per 30 seconds of video or per generated visual, while each additional creator requires a paid seat.
verified 2026-08-14 · source ↗
Vibecode Arcade
Kinda. The core of Arcade is buildable in a weekend with the prompt on this page, but there are real gaps: capture polish, hosted playback, analytics, personalization, and collaboration, instant hosted sharing. Read the honest list above before committing.
How much does Arcade cost?
Arcade costs about $50/month (Growth, checked 2026-08-14), which is $600 per year.
What do I lose by replacing Arcade?
Honestly: capture polish, hosted playback, analytics, personalization, and collaboration; instant hosted sharing; viewer analytics; team libraries; cross-device capture. If any of those are load-bearing for you, keep paying.
Is there an open-source alternative to Arcade?
Yes: Cap (Open-source screen recording and sharing product with modern desktop architecture.). Using prior art is also vibecoding; the prompt is for when you want it exactly your way.