The music store, running here
Everything below the line is the example itself: the same plugin sources
examples/music ships, on the same @datalayer/reactor build, assembling
themselves into a store.
What you are looking at
Nothing in that frame is drawn by this page. The application mounts four plugins and an extension and renders four empty slots; every pixel arrived as a contribution.
Try these, in this order:
- Add a song to the cart. The badge in the header updates — the header plugin reads a store the shop plugin owns, and neither imports the other's component.
- Hover the cart badge. The overlay has a Checkout button in it. The
header does not know that button exists: it offers a
cart-actionsslot, and the checkout plugin fills it. - Untick
@music/checkoutin the Plugins panel on the right. Both Checkout buttons go — the one in the overlay and the one under the songs — and the store carries on. Tick it back and they return. - Untick
@music/mood. The playlist's rule chooser empties, because disabling a plugin withdraws its contributions. The playlist plugin, which owns the point those rules were made to, is untouched. - Untick the Python
catalogplugin, under Backend plugins. The catalog and the shop disappear: both React plugins declarerequiredBackendPlugins: ['catalog'], so a slot component gated on it stops rendering. - Untick the Python
playlistplugin. Nothing disappears — the frontend declared that one optional, and the card says so instead. - Press View plugin graph. Sixteen nodes and thirty-two relationships, derived from what the plugins declare rather than drawn by hand: extensions delivering plugins, plugins depending on each other, the contribution points they offer and fill, and the dashed lines reaching across the wire to the Python tier. The application does not draw that button — the graph plugin contributes it, which is why unticking Graph in the list takes the button with it.
Steps 5 and 6 are the same mechanism with two different strengths declared; see Cross-tier Dependencies.
The graph in step 7 is worth a second look while switching things off: it is drawn from the platform, so a plugin leaving the list leaves the picture, and the edges that vanish with it are the ones nobody had to write down.
What is different from npm run dev
Three things, and no fourth:
- There is no uvicorn. A documentation site is a static file, so the four
Python plugins' endpoints —
GET /plugins,POST /plugins/{name}/toggle,GET /api/catalog/songs,POST /api/checkout,GET /api/playlist/rules,GET /contributions— are answered in the browser bysrc/components/MusicDemo/backend.ts, with the same manifests and the same toggle semantics. The Python half of the panel is live rather than a screenshot, and the backend half of the graph is drawn from that same answer. Running the real backend changes nothing about what you see. - The graph is a button, not an address. The example gives the
plugin graph its own
/graphroute, andpushStateis its whole router. A page inside a documentation site cannot take over the URL bar, so the same state lives in auseStatehere. Nothing downstream changes: the slot, the button and the plugin that owns both are the example's. - The theme is pinned. The header contributes Datalayer's appearance
controls, and running the example they repaint the whole viewport. Here the
viewport is somebody else's, so the demo fixes itself to the Datalayer theme
in
autocolor mode — following your system preference, as the page around it does — and the control is hidden rather than left visible and inert.
The plugin sources are imported unmodified — the site's webpack configuration
aliases @datalayer-examples/reactor-music-* to examples/music/*/src/index.tsx,
exactly as the example's own vite.config.ts does. There is no forked copy of
the example in this repository, which is the only way a demo stays true.