Development

A notebook in C#

A notebook is a class deriving from NotebookApplication that overrides Build. Its members are per visitor, exactly as a document's data members are:

using Divooka.Application.Notebook;
using Divooka.Application.Notebook.Framework;

public class Greenhouse : NotebookApplication
{
    public double Temperature { get; set; }

    protected override void Build()
    {
        Site("Greenhouse");
        Page("Yield");
        Markdown("# Crop yield");
        Slider("Temperature (°C)", 0, 40, 24, t => { Temperature = t; return $"{t} °C"; });
        TextBox("Region", "North", region => NotebookOutputs.Markdown($"**{region}** at {Temperature} °C"));
    }
}

NotebookApplicationProvider provider = new(new Greenhouse(), () => new Greenhouse());
await using NotebookHost host = await NotebookHost.StartAsync(provider, new NotebookHostOptions { Address = "127.0.0.1:5080" });

The provider is given the site's own instance and a way to make another for each visitor; a document run by Compute or dvn is given both by the framework.

Packages

Package What it is
Divooka.Application.Notebook.Application NotebookApplication, cells and output values. References no web library, so a notebook document's own references stay small.
Divooka.Application.Notebook.Framework The driver, NotebookHost, NotebookApplicationProvider, the mapping from Divooka values to outputs, and the self-check.
Divooka.Application.Notebook The ASP.NET Core server, with the page client embedded: AddDivookaNotebook and MapDivookaNotebook.
Divooka.Application.Notebook.Base The wire contracts and the provider interfaces.

A host with pages of its own can implement INotebookPagesProvider and INotebookSessionComputeProvider and map the server into its own application with AddDivookaNotebook and MapDivookaNotebook.

The wire protocol

The page talks to the server over a small JSON API, versioned so a page cached from an older server says to reload rather than misreading the answers: a bootstrap per page load, which creates the session; one call per change, answered with the cell's output and any enabled-state changes; uploads; and a close sent when the page goes away. It is specified in PROTOCOL.md beside the server's source, Parcel.NExT/Packages/Divooka.Application.Notebook.

The page client

The page is built from DivookaFrontendComponents, the Divooka ecosystem's shared React components, and embedded in the server when it is built. Building the server from source therefore needs Node.js and the components' clone at External/DivookaFrontendComponents (External/Setup.ps1 clones it); the build says which is missing.

Tests

UnitTests/Divooka.Application.Notebook.UnitTests serves notebooks on a real loopback port and drives them through the API: visitors kept apart, members shared within a visit, documents authored through the editor session and served interpreted and compiled, dvn, and the shipped example. NOTEBOOK_CHECK=1 - or dvn --check - makes any notebook visit itself once and print what each cell answered.