❯_ Demo as Code

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

01 · DEFINE Declare the scenario

Infrastructure, seed data, users, and the demo path — all in code, in your repo, reviewed like everything else you ship.

02 · RUN Execute against real APIs

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.

03 · RESET Pristine every time

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.

04 · SHARE Version, diff, test

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.