defuss-shadcn / WYSIWYG Editors / studio
Studio
Rapid Agentic Development, the visual half: compose an app from the system's components, page by page, and hand it to an agent - or take what an agent wrote and finish it by hand. The library is every component of these docs alone - about 1,600 of them, cut from the examples - and every example, about 1,650, under the page that shows them, in the markup agents are told to write; the canvas is the Visual Editor; the preview is the HTML Preview Editor, running the page with every component it uses. Built only from shipped components.
On this page (6)
§Studio
A Border Layout of Panels: drag a divider to resize a side, double-click it (or the panel buttons in the toolbar) to fold it; minimize a panel to its title bar or maximize it over its column. West: the components and examples of the docs under their section and page - each component alone first, then the examples that compose it; pick one and it shows below as it will look on the page; drag it onto the page from the tree or from the preview, or click it to put it into or after the selected element. Center: the page. East: the selection - the path from the page down to it and everything inside it - its properties (the classes in a tag input of the system's classes), and the state of a component that has one. Preview runs the page; Export writes a page, the whole app as a ZIP, the project as JSON - or copies it for an agent. The work is kept in this browser.
§Layout
The Studio is one Border Layout: the toolbar on top, the page in the center, and a resizable side on each hand that is itself a Border Layout. Each divider drags, moves with the arrow keys and folds on a double-click; the toolbar's panel buttons fold the sides too, and the sizes are kept in this browser.
Every view on the sides is a Panel, as in an application's layout. Minimize one and its region shrinks to the title bar, so its neighbour takes the room; the Studio remembers minimized panels in this browser. Maximize one and it covers its column until you restore it. The panel in the middle of a column - Components, Properties - only maximizes: its neighbour's minimize gives it the whole column. Everything is dense (data-density="compact"): the panels' title bars, the trees' rows, the cards.
West, the library - a Tree View of the components of these docs: the sidebar sections that hold components, with their sidebar icons, their pages (sub-pages nested), and on each page first its component alone, in every kind the docs use it - h1 to h4 on Typography, every variant, size and state of Button the docs use - then its examples by name: "Japanese text" on Typography, "Multi-open" on Accordion. The components alone are the individual examples, kept in each component's parts file beside its sources (button.parts.md) - the docs pages show none of them - and verify keeps them complete: every component an example is made of has one of each kind it is used in. A picked entry shows below the tree in a frame of its own, with the page's stylesheets and no script: what a drop puts on the page, as the canvas will show it. One on the page of a wide composition (an organism, a block, a template) is laid out at a desktop width and scaled down. Drag it onto the page - from the preview, or straight from its row in the tree - or click it to put it into or after the selected element. The tree loads with the Studio; a page's entries load when one of them is picked, or when the pointer comes over one of its rows.
East, the inspector - on top, a second Tree View holds the selection: the path from the page down to the selected element, which is highlighted, and every element inside it down to the deepest. Clicking a row selects its element; with nothing selected the tree is the whole page. It takes the height it needs, between a fifth and half of the inspector: a fixed region with the Border Layout's data-fit. Below it, the Property Grid shows the selected element's text, classes and attributes. The classes edit in a Combobox tag input: the element's own classes first, then the classes its component owns (a Card's card-header, card-title...), then every utility class of the system by module - Layout, Sizing, Shapes, Accessibility; type to filter, or to add a class none of them lists. Under the properties sits the component's state, again as high as it needs (data-fit, up to half the column); with no state to show it folds to its title bar.
§State
A component with a script draws its markup from its state: its render() gives the markup of every state, and the next render would undo an edit of that markup. So in the Studio such a component is one locked unit (the Visual Editor's lock()): it moves, copies and goes as a whole, nothing drops into it, and its elements show read only in the Property Grid. It changes through its state - a Tree Grid lists the states of its schema, with the controls of the HTML Preview Editor's State tab.
A change runs where the State tab runs it: a hidden HTML Preview Editor holds the component with its script, the value is set there the way the State tab sets it, and the markup that goes back into the page is what the component's render() gives for the state it landed in. The live markup would not do: it carries what the runtime adds - data-init, ARIA wiring - and a page loading it would not start the component again. A component without a script has no state: the State panel folds to its title bar (the Studio's own fold, not remembered - a panel you minimized stays as you left it), a card in it says so, and every element of the component is edited directly.
§The RAD loop
Rapid Agentic Development has two halves that speak one language: an agent writes markup from the component skills, a person shapes it here, and either one continues from the other's work. Nothing is translated on the way - the Studio's library is the docs' examples, written as the skills teach, its output is markup, and the verifier checks the result the same way it checks every page.
flowchart LR
Skills["component skills<br/>(markup to copy)"] --> Agent["agent writes<br/>a page"]
Agent -- "Open in Studio" --> Studio["person edits<br/>in the Studio"]
Studio -- "Copy for an agent" --> Agent
Studio --> Export["HTML pages<br/>app ZIP"]
Agent --> Verify["verify<br/>tests, e2e"]
Export --> VerifyFrom the docs into the Studio - an example's source travels in the address fragment (full-studio.html#source=, compressed) and opens as a new project. Nothing is sent to a server. The live examples on this site will carry an Open in Studio button for it once the Studio leaves alpha - until then the button is hidden.
From the Studio to an agent - Copy for an agent (Export menu) writes Markdown: the project's pages as HTML and, for every component they use, the link to its skill at this release. Paste it into any harness with the component skills and ask for the next step - the agent changes markup it can read, in the language it was taught. The app ZIP carries the same notes as AGENTS.md.
Kept in this browser - projects are stored locally as they are edited (one store, studio:projects); the project JSON moves them between browsers. An imported project is a copy with a new id, so it never overwrites the one it came from.
§What is exported
A page is a complete HTML document: the page's markup, the system's core and all bundles from the CDN, pinned to this release, plus any extra bundle the page uses (Mermaid, math, the editors). The ZIP holds every page, project.json and AGENTS.md - serve the folder over HTTP and it runs as it previewed.
§Limits
The canvas and the example frames show each component's markup without running it - a chart or a diagram stays empty there until Preview runs the page. An example's scripts are not part of what drops: the canvas's parser removes every <script>, data blocks included, so a component fed by one (a Property Grid's source, a diagram's spec, a grid's records) arrives empty. An example's <style> comes along and is kept with the page. The state of a component is read from its running instance; one that the markup alone cannot tell (an Accordion opened item by item reads as its default state) shows that. Projects stay in this browser unless exported.
Comments, ideas or improvements? Edit this page's source on GitHub