Product demos, defined as code.
Stop rehearsing against production and praying nothing moved. Demo as Code turns your demo into a versioned artifact: a declared scenario, seeded data, real backend behavior, and a pristine reset on every run.
const shop = defineEnvironment({ up: [exec("node server.mjs", { background: true })], ready: [http("http://localhost:4321/health")], # not a guessed sleep seed: [exec("node seed.ts 12 340")], # deterministic data reset: [exec("rm -f store.json"), exec("node seed.ts 12 340")], }); export default defineDemo({ id: "onboarding", environment: shop, scenes: [ terminal({ name: "cli", steps: [ run("curl -s localhost:4321/api/stats", { beat: "3s" }), ]}), browser({ name: "console", baseUrl: "http://localhost:4321", steps: [ goto("/", { untilText: "Overview" }), click({ role: "link", name: "Orders" }, { untilText: "Product" }), expectText("Showing 25 of 340."), # an assertion ]}), ], });
That is a real, running example in the repo — dac check
runs it in CI, dac record turns it into video.
How it works
Infrastructure, seed data, users, and the demo path — all in code, in your repo, reviewed like everything else you ship.
Your application runs against the environment you declared — real requests, real handlers, real data. Steps advance when a condition holds, never on a guessed sleep. No screenshots, no overlays, no fakery.
dac reset tears the state back to the declared
baseline. Seed data is a pure function of a seed, so the tenth
run of the day is byte-identical to the first.
Demos live in git: branch them per prospect, diff them per
release with dac plan, and run dac check
in CI so they break there — not live.
Why demos should be code
Demos rot. The environment drifts, the seed account gets polluted, the feature flag flips, and the person presenting finds out live. A demo defined as code is rebuilt from its definition every run, so it cannot drift.
Click-through demo tools fake it. Screen-capture platforms replay a frontend. When the prospect asks "what happens if I do this instead?" the demo is over. A real backend answers the question.
Untested demos fail at the worst moment. If your demo is code, CI runs it on every merge. Breakage shows up in a pipeline, days before it would have shown up in front of a customer.
A demo never advances because time passed. It advances because a condition held — the server answered, the text appeared, the command returned. Waiting on conditions instead of guessed sleeps is what makes a demo both fast to record and safe to re-run. Deliberate pauses stay, because a human needs a moment to read; they are just never confused with waiting for the product.
Early access
Demo as Code is being built now. If your team runs product demos and you're tired of hoping they work, tell us what you demo and what breaks.