# TinyDemo: capture an owned synthetic walkthrough

Requires Node.js 20 or later. Run in your project:

    npx -y tinyscale@0.10.0 workspace create --name "My demo project" --cohort external --products tinydemo
    npx -y tinyscale@0.10.0 demo origin --origin https://your-owned-domain.com

Publish the returned public challenge as plain text at its returned proofPath
on that origin, then:

    npx -y tinyscale@0.10.0 demo confirm-origin --origin https://your-owned-domain.com

Create a scenario with demo create --scenario-json followed by this JSON,
replacing the origin, path and visible text with an owned synthetic fixture:

    {"version":"tinydemo.v1","title":"Try the product","origin":"https://your-owned-domain.com","dataPolicy":"owned_synthetic","viewport":{"width":1280,"height":720},"scenes":[{"id":"start","caption":"A short walkthrough","alt":"Synthetic product screen","actions":[{"kind":"navigate","path":"/demo"}],"readyText":"Welcome","timeoutMs":10000}],"cta":null}

Then queue and inspect the private capture:

    npx -y tinyscale@0.10.0 demo capture --demo DEMO_ID --revision 1 --idempotency-key demo-first-capture-0001
    npx -y tinyscale@0.10.0 demo status --demo DEMO_ID

Repeat the same idempotency key after a transport failure. Poll until needs_review
or failed; queued/capturing is not proof of completion. Status returns only safe
metadata. Images and captured content are never returned to agents. Inspect the
owner review after workspace claim opens the private human claim page:

    npx -y tinyscale@0.10.0 workspace claim

The human reviews every scene and the optional CTA, then explicitly publishes.
The owner page provides the share URL, sandboxed iframe, unpublish and erasure.
Failed recapture preserves the published revision. New scenarios use demo revise
--demo DEMO_ID --revision CURRENT_REVISION --scenario-json JSON before capture.

Limits: 72-hour Preview, one demo, two captures total, five scenes, 10 MB storage.
Claimed Free: three demos, ten captures per UTC month, eight scenes, 50 MB storage.
Every capture has a 60-second deadline and a two-attempt maximum. PNG scenes are
at most 2 MB. Unpublished drafts expire after seven days. Published images remain
within the storage cap until unpublish/erasure. Expired images are removed by
scheduled cleanup before their reserved storage is released.

Only canonical HTTPS origins and simple paths are allowed. Routes cannot carry
queries, fragments or encoded state. Each scene has 1-4 navigation or named
button/tab click actions and a visible text readiness marker. No scripts, typed
form data, cookies, custom headers or production login. Capture rechecks origin
ownership and public DNS; network writes, cross-origin requests and WebSockets
are blocked. Capture supports at most 20 network requests. Keep synthetic routes
self-contained and turn off analytics injection (for Cloudflare, send
Cache-Control: no-store, no-transform on the fixture response). Form fields and
iframes are masked in images. Use plain captions
and descriptive alt text; optional normalized hotspots advance to the next scene.

Optional CTA: {"label":"Try it","origin":"https://your-owned-domain.com","path":"/start"}.
Only the owner's published revision is delivered. All delivery uses no-store
responses and rechecks publication state; unpublish removes access immediately.
Views, completions and CTA clicks are bounded observations, not unique visitors,
attribution, conversion lift or evidence of demand. Existing workspace keys do
not acquire TinyDemo access; provisioning must explicitly opt in.

To also measure internal setup milestones with TinyActivate, use
--products tinydemo,tinyactivate at workspace creation. The claimed owner's
project page reconciles demo creation and publication as synthetic test events.
This uses one additional checklist and enrollment; it never widens existing keys.
