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 (initialmix phx.server, fresh-clonemix setupflows, 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 upmount_pathat runtime, found nil, and rendered empty markup. Macro now computes the full scoped path at compile time (wherePhoenix.Router.scoped_path/2works), bakes it into a module attribute, and registers it via an@on_loadcallback 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 theconfig :demo_director, mount_path: "/path"escape hatch for unusual release-build / umbrella-app setups where@on_loaddoesn'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-idas 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 fordata-demo-idonly when no such handle exists.:nth-childchains and deep descendant paths are still called out as fragile. Existing installations keep their old AGENTS.md / CLAUDE.md content; rerunmix igniter.install demo_directorto 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 themix demo_director.playexample 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 todemo_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.Socketdeclaration) and writesconfig :demo_director, pubsub: <OtpApp>.PubSubintoconfig/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 existingDemoDirector.PlaybackSocketsocket declaration /:demo_directorconfig block before adding. - Selector resolver in the runtime now falls back to
document.querySelectorwhen a string isn't found viadata-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-hocdata-demo-idannotations.data-demo-idlookup is still tried first, so the recommended idiom is unchanged. fillTypednow dispatches a synthetickeyupevent per character alongside the existinginputevent. Hosts that listen viaphx-keyup(rather thanphx-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_directorcrashed withFunctionClauseError in Rewrite.update!/2while seedingAGENTS.md/CLAUDE.md. The install task's updater callback returned a raw string instead of theRewrite.SourcethatIgniter.create_or_update_file/4expects from its 4th argument. Updates the source's:contentviaRewrite.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 existingimport DemoDirector.Routercall 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 carriesdir="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_directorassumes 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 tobrowser_eval(or that gets saved into a.exsscript). - HEEx integration via
demo_id/1for 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>/demoslisting every saved demo - a per-demo JSON endpoint at
<mount>/demos/<name>.js - a playback POST endpoint at
<mount>/play(localhost-only)
- static assets (CSS + JS) at
- 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.