A Vite + React 19 studio that turns raw source material into a self-contained, audience-tuned technical explainer rendered as a dark editorial SVG scene — exported as one standalone HTML file. An honest early spike, scoped without overclaiming.
Mise en Scène is "the studio": paste a repo, an OpenAPI spec, a README, an incident report, a transcript, or architecture notes, and it produces a polished, editable technical explainer rendered as a dark editorial HTML/SVG scene. Pick an audience and a mode, click the cards, then export the whole thing as one standalone HTML artifact you can hand to anyone.
It solves the editorial-diagram problem: producing a legible, audience-tuned architecture picture from raw notes without hand-drawing it, and shipping it as a portable file. On escoffierlabs.dev it is course 11 — station "l’ardoise", the chalkboard out front — the fleet’s front-of-house explainer surface.
The name is a deliberate counterpart to Brigade’s mise en place. Mise en place is prep — everything in its place before you cook. Mise en scène is stagecraft — the arrangement of a scene so it reads. This tool’s job is composing extracted elements into a legible scene. Being honest about the current spike matters as much as the pitch.
Everything an author touches is one plain Scene object. Blocks are absolutely-positioned cards; edges are directed connectors keyed to the four explainer modes. No backing store — just a typed value.
src/App.tsxtypescripttype SceneBlock = {
id: string; label: string; kicker: string; detail: string;
x: number; y: number; w: number; h: number; // absolute layout
};
type SceneEdge = {
from: string; to: string; label: string;
modes: Array<ExplainerMode>; // which modes light this edge up
dashed?: boolean;
};
type Scene = {
title: string; subtitle: string; summary: string;
facts: string[]; terms: string[];
blocks: SceneBlock[]; edges: SceneEdge[];
};x / y / w / h on every blockCards are absolutely positioned in a fixed 1280x780 viewBox — layout is data, not CSS flow.modes: Array<ExplainerMode>An edge belongs to one or more of the 4 modes; switching mode filters what lights up.facts / terms: string[]These (plus title and card detail) are the parts actually extracted from pasted source.createScene is the transform. Today it is pure local heuristics: it extracts text, then merges it into a fixed block/edge template. Knowing exactly which parts are dynamic vs templated is the key to reading the tool honestly.
SVG <text> cannot wrap or clamp, so early cards overflowed when detail ran long (character-width estimation never holds). The fix: draw the border as a <rect>, then put real HTML inside a <foreignObject> and let CSS line-clamp do the work.
src/App.tsx · src/sceneStyles.tstsx<rect x={block.x} y={block.y} width={block.w} height={block.h} rx="10" className="card-rect" />
<foreignObject x={block.x} y={block.y} width={block.w} height={block.h}>
<div className="card">
<h3>{block.label}</h3>
<p>{block.detail}</p>
</div>
</foreignObject>
/* sceneStyles.ts — the clamp that keeps text in bounds */
.card p {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
}<rect ... /> then <foreignObject>The rect is the visible border; the foreignObject hosts real, wrappable HTML.-webkit-line-clamp: 3CSS clamps detail to 3 lines — the overflow fix that replaced fragile SVG text measuring.styles live in sceneStyles.ts as literalsToken literals (not CSS vars) so the styles can be inlined into the exported SVG.The live studio and the exported file render the same SceneSvg, and the scene’s CSS is injected inside the SVG — so styles travel with the artifact and the export can never visually drift from the app. standaloneHtml serializes a full document with React 19’s renderToStaticMarkup.
src/App.tsxtsxfunction StandalonePage({ scene, mode }) {
return (
<html lang="en">
<head><style>{standaloneCss}</style></head>
<body>
<main>
<section className="scene">
<SceneSvg scene={scene} activeMode={mode} staticExport />
</section>
</main>
</body>
</html>
);
}
// standaloneHtml(scene, mode):
// "<!doctype html>" + renderToStaticMarkup(<StandalonePage scene mode/>)the same <SceneSvg> in both pathsLive app and export share one renderer — a single source of truth, so they cannot diverge.styles injected inside the SVGThe scene’s CSS lives in the SVG, so a saved file looks identical with no external stylesheet.renderToStaticMarkup(<StandalonePage/>)react-dom/server is bundled client-side (≈ a deliberate +bundle tradeoff) to serialize the artifact.The repo does not oversell. Here is the real line between what works today and what is aspirational — the kind of scoping the fleet values.
Mise en Scène is independent of Brigade in code, but its demo scene depicts a future where "Brigade runtime" is the backend that runs grounding, model routing, tool calls, and artifact export once the pipeline grows past local heuristics.