VersoFeature

Five layouts, one notebook file, no host changes

A layout decides how a notebook is arranged and rendered, and it is an extension like any other: five samples on NuGet turn one file into a graph, a deck, a spreadsheet, a dashboard, and an image editor.

Verso ships three layouts. Notebook is the linear list of editable cells, Dashboard turns cells into tiles you can move, resize, and run, and Presentation hides the editing chrome to show results. Pick one from the View panel and the notebook redraws beside the list, cells and outputs untouched: a layout decides only how they are arranged.

All three are extensions, written against the interfaces we publish. I have said that before, and it is easy to write and hard to believe. So the repository now carries five sample layouts that make the case the only way it can be made: installable from NuGet, on the public interfaces, turning a notebook into something you would not guess it could be.

Extension What the notebook becomes Package Renderer Bundled JavaScript
DAG Notebook A reactive graph: cells linked by the variables they share Verso.Showcase.DagNotebook Inline None
Slide Studio A deck editor with a filmstrip, a split view, and a presenter Verso.Showcase.SlideStudio Inline None
Grid Studio An editable spreadsheet bound to a kernel variable Verso.Showcase.GridStudio Isolated Jspreadsheet CE 4.15.0, jsuites 5.13.3
Form Studio A dashboard you build by dragging, driving the notebook's code Verso.Showcase.FormStudio Isolated Chart.js 4.4.6
Image Studio A layered image compositor with a canvas and a layer stack Verso.Showcase.ImageStudio Isolated None

All five published 1.2.2 on 2026-09-04, all MIT, each referencing Verso.Abstractions and nothing else. Installed, they show up in the View panel beside the three built-ins, with nothing marking them as newcomers.

Two ways a layout draws

A layout picks one of two renderer modes and stays on it.

An inline layout returns HTML from RenderLayoutAsync with a placeholder where each cell goes. The host matches every [data-cell-slot] element to a cell and mounts the real cell component into the slot. That is why the editor in a Slide Studio deck is the same Monaco editor, run button and all.

An isolated layout draws its own surface instead. It sets RendererIsolation to Isolated and returns its own bundle from GetRendererPackageAsync, and the host mounts that in a sandboxed iframe with a window.verso bridge as the only channel out.

Inline host page layout HTML data-cell-slot one slot per cell, filled by the host Isolated host page sandboxed frame renderer module window.verso no network inside the frame
Two renderer modes, one interaction contract: the same handler serves both, whichever mode delivered the event.

The frame is sandboxed with scripts allowed and nothing else, and the base policy sets connect-src 'none', so an isolated layout cannot fetch anything. Data arrives the other way: read from a kernel variable on the C# side, pushed into the live frame, with edits coming back as interactions.

What each one shows

DAG Notebook links cells by the variables they share, marks a cell stale when its inputs have run more recently, and with auto-run on re-runs a finished cell's dependents in dependency order. The graph is a heuristic scan of the source rather than a proof: a name written by two cells gets warning chips and no edges, and cycles stay out of the cascade. It makes the biggest claim of the five: a layout can change execution semantics, not just how things look. We walked a notebook driven this way in a dial at the top.

Slide Studio is a deck editor: a filmstrip of cell previews, the selected cell's live editor and rendered output behind a draggable splitter, and a full-screen presenter mode. Three checkboxes per cell decide whether a slide is included and whether it shows source, output, or both, and presenting never re-executes anything. It declares cell editing and execution but not insert, delete, or reorder: a deck is arranged here and restructured in the notebook layout.

Grid Studio binds a kernel variable to an editable, Excel-like grid. The schema drives the columns, so numbers edit as numbers and booleans as checkboxes, and committing an edit writes a rebuilt DataBlock back to the same variable. A System.Data.DataTable, such as the results a SQL cell shared, is read-only on purpose: a DataTable can be wired to a data adapter, so writing edits back could prime a database update nobody asked for.

Form Studio is a drag-and-drop dashboard builder. Sliders, dropdowns, toggles, text fields, labels, and charts drop onto a canvas, each input binds to a kernel variable by name, and with auto-run on it re-runs the notebook and pushes fresh data into the charts. The compute cell reads its inputs with Variables.Get<T>("name"), which returns a default before any widget is bound, so the notebook still runs on its own.

Image Studio is a layered compositor: canvas in the middle, layer stack on the right, tools on the left. Layers can be solids, gradients, patterns, text, or procedural, and a procedural layer defers its drawing to a kernel variable, so re-running a code cell repaints it. While it is active it adds PNG Image and SVG Image to the host's Export menu, absent everywhere else.

The habits they share

They theme through the host's --verso-* CSS variables rather than asking what the theme is, so they re-color on a switch without knowing a palette by name. A canvas is the exception, so Form Studio reads the tokens into its chart options.

They persist their own state through layout metadata: a dashboard's widgets, a deck's slide flags, a compositor's layer stack, and a grid's binding all travel in the .verso file, with no sidecar files.

And they read data by reflection rather than by reference. Grid Studio and Form Studio work with DataBlock values from Datafication.Core without referencing that package, reading whichever assembly the kernel loaded with #r "nuget: ...".

Opening one, and building one

Each sample has a notebook beside it naming its package in extensions.required, so the host fetches, loads, and activates the layout before the first render, and an activeLayout entry opens the file straight into it. For a notebook of your own, search Verso.Showcase in the Extensions pane, which finds all five, install one, and trust it when asked, per notebook and pinned to that version.

To write your own, work in the build loop instead. Each sample builds standalone against the local Verso.Abstractions project, then loads with a #!extension line naming the built assembly.

dotnet build samples/showcase/grid-studio/src/Verso.Showcase.GridStudio
#!extension ./src/Verso.Showcase.GridStudio/bin/Debug/net8.0/Verso.Showcase.GridStudio.dll

Why I built five of them

The layout system arrived with 1.1, and the test of an extension surface is whether someone outside the team could build something surprising on it. A spreadsheet with write-back, a presenter, and an image editor with its own document model usually need a fork. Here they are five packages, and the host does not know they are special.

They are samples, not products, each small enough to read in an afternoon. Install one, open a notebook you already have in it, and tell me what the layout gets wrong about your file. The Showcase Extensions pages cover all five, and the Layout Authoring Guide covers the interfaces underneath them.