All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[0.1.5] - 2026-05-10

Fixed

  • The overlay component would silently render empty in some host apps even though the router macro had been called and the route was reachable. Root cause: the macro's Application.put_env(:demo_director, :mount_path, ...) ran inline at compile time, which writes to whichever BEAM is doing the compile. During Mix-driven workflows (initial mix phx.server, fresh-clone mix setup flows, some hot reloads) that's often a short-lived compiler subprocess whose env dies before the dev server's runtime BEAM ever sees it — so the overlay component looked up mount_path at runtime, found nil, and rendered empty markup. Macro now computes the full scoped path at compile time (where Phoenix.Router.scoped_path/2 works), bakes it into a module attribute, and registers it via an @on_load callback that fires every time the router module is loaded into a BEAM. Cold boot, hot reload, code purge + reload — all paths converge on a registered runtime env. README troubleshooting section adds the config :demo_director, mount_path: "/path" escape hatch for unusual release-build / umbrella-app setups where @on_load doesn't fire as expected.

[0.1.4] - 2026-05-10

Changed

  • Install task's agent-instructions template (the content that gets dropped into AGENTS.md / CLAUDE.md) was still telling agents "Never invent a CSS selector" and describing data-demo-id as mandatory. The runtime has accepted raw CSS selectors as a fallback since 0.1.2, so the contract was a version behind reality. Template now recommends picking the most stable handle that already exists in the host's markup — semantic ids, form-field ids that <label for=""> points at, distinctive attributes — and to reach for data-demo-id only when no such handle exists. :nth-child chains and deep descendant paths are still called out as fragile. Existing installations keep their old AGENTS.md / CLAUDE.md content; rerun mix igniter.install demo_director to refresh.

Documentation

  • README's selector-contract section rewritten to match the template change above, plus a pacing note for LiveView-driven inputs with phx-debounce (callers should allow the debounce window plus a server roundtrip — ~600–1200ms total — before reading the resulting DOM state). Production-stripping section now describes the deferred sandboxed demo-session primitive inline rather than pointing at an internal MEMORY.md.

[0.1.3] - 2026-05-10

Documentation

  • README's "Replay a saved demo" section pointed at the wrong URL — /dev/director/demos — which neither the install task nor the router macro's default produce. Updated to /dev/demo-director, matching the macro's @default_path. Same fix applied to the mix demo_director.play example URL.
  • README now mentions that the listing page is reachable at the bare mount path (<mount>) in addition to <mount>/demos (added in 0.1.2 but not surfaced in the docs).
  • README's manual wire-up section for the router macro previously used demo_director "/director", which conflicted with what the install task generates and produced confusing URLs. Aligned to demo_director "/demo-director" so the docs match the installer.

[0.1.2] - 2026-05-10

Added

  • The install task now also adds the playback socket to your endpoint (after the existing Phoenix.LiveView.Socket declaration) and writes config :demo_director, pubsub: <OtpApp>.PubSub into config/dev.exs. The post-install notice shrinks from three manual steps to one (the overlay-component HEEx edit), which stays manual on purpose because root layouts aren't AST-editable. Both new edits are idempotent — the task searches for an existing DemoDirector.PlaybackSocket socket declaration / :demo_director config block before adding.
  • Selector resolver in the runtime now falls back to document.querySelector when a string isn't found via data-demo-id. Lets demos target existing semantic ids (#vitals), classes (.btn-primary), or any other CSS selector the host app already has, without forcing ad-hoc data-demo-id annotations. data-demo-id lookup is still tried first, so the recommended idiom is unchanged.
  • fillTyped now dispatches a synthetic keyup event per character alongside the existing input event. Hosts that listen via phx-keyup (rather than phx-change) now react to typed input during demo playback.
  • Demos listing page is now reachable at the bare mount path (e.g. /dev/demo-director) in addition to the original <mount>/demos. Both URLs render the same listing.
  • Listing-page styling switched to a purple palette (Elixir-ish lavender on deep purple). The Play button stays red for contrast. The demo overlay (subtitle bar, highlight ring) is intentionally unchanged — it stays neutral so it works visually on any host app's color scheme.

Fixed

  • mix igniter.install demo_director crashed with FunctionClauseError in Rewrite.update!/2 while seeding AGENTS.md / CLAUDE.md. The install task's updater callback returned a raw string instead of the Rewrite.Source that Igniter.create_or_update_file/4 expects from its 4th argument. Updates the source's :content via Rewrite.Source.update/3.
  • The router edit was not idempotent: re-running the install task appended a duplicate if Application.compile_env(:my_app, :dev_routes) block on every run. The task now searches for an existing import DemoDirector.Router call before adding, mirroring the pattern used by the Tidewave installer.
  • Subtitle bar's text was bidi-flipped on hosts with <html dir="rtl"> — English content's punctuation could land on the wrong side. Subtitle node now carries dir="auto" so its visual direction is determined by the first strong character of the subtitle text itself, regardless of the host page's direction.

Documentation

  • README's "Add to your Phoenix app" section notes that demo_director assumes the host app has a working Phoenix LiveView setup; the installer does not bootstrap LiveView from scratch.
  • The README's manual wire-up step for the overlay component now explains why that step stays manual (HEEx isn't AST-editable like Elixir, so editing root layouts programmatically would be string-level surgery on a frequently-customized file) and notes that the component is prod-safe to leave unconditionally inside <body> (it returns empty markup when no mount path is registered). The install task's post-install notice carries the same explanation in shorter form.

[0.1.1] - 2026-05-10

Changed

  • Reworded package description / README tagline to lead with what the package does ("Narrated, highlighted, animated demos for Phoenix LiveView") before the workflow tagline.
  • Added Hex.pm and HexDocs badges to the README.

[0.1.0] - 2026-05-10

Added

  • Helper API: subtitle/1, highlight/1, fill/2, fill_typed/3, click/1, wait/1. Each emits a JS string the agent passes to browser_eval (or that gets saved into a .exs script).
  • HEEx integration via demo_id/1 for stable selectors through LiveView patches.
  • Overlay component (demo_director_overlay) rendering a word-by-word-revealed subtitle bar and a target-tracking highlight ring.
  • Router macro (demo_director "/director") mounting:
    • static assets (CSS + JS) at <mount>/demo_director.{css,js}
    • a web demos browser at <mount>/demos listing every saved demo
    • a per-demo JSON endpoint at <mount>/demos/<name>.js
    • a playback POST endpoint at <mount>/play (localhost-only)
  • Phoenix channel + socket (DemoDirector.PlaybackSocket) that relays demo JS broadcasts to every connected overlay.
  • mix demo_director.play <name> task that POSTs a saved demo's JS to the running dev server. Reads # @start_at "/path" metadata from the demo file and navigates the browser there before running.
  • Igniter-based install task (mix igniter.install demo_director) that wires the router macro and seeds AGENTS.md / CLAUDE.md with the agent contract.