Skip to main content

Author notebook cells

Notebook accepts cells from four helpers. Each helper wraps a source string in one Notebook Kit cell mode. Notebook Kit analyzes references between cells and reruns dependent cells when values change.

HelperCell source
obs.js(...)Standard Notebook Kit JavaScript
obs.ojs(...)Observable JavaScript
obs.md(...)Markdown
obs.html(...)HTML

Top-level declarations in JavaScript cells form a reactive graph: when a value changes, every cell that references it runs again. Move the exponent control to recompute the readout in the browser.

import observablejs as obs

notebook = obs.Notebook(
obs.js(
"""
const exponent = view(Inputs.range(
[1, 8],
{label: "Exponent", step: 1, value: 2}
));
""",
key="exponent_control",
),
obs.js(
'html`<p>Two to the power of ${exponent} is <strong>${2 ** exponent}</strong>.</p>`',
key="readout",
),
)

full_view = notebook.view()
full_view

The first cell defines exponent. The readout references it, so Notebook Kit runs that cell again when the input changes. Notebook Kit schedules cells from their dependencies, independent of source order.

JavaScript cells

An expression cell displays its value implicitly.

obs.js("Plot.lineY(aapl, {x: 'Date', y: 'Close'}).plot()")

A program cell contains declarations or statements. Call display(...) when a program cell should render a value.

obs.js(
"""
const formatter = new Intl.NumberFormat("en-US");
display(formatter.format(42000));
"""
)

view(...) displays an input and defines a reactive value from its events.

obs.js(
'const radius = view(Inputs.range([2, 12], {value: 5, label: "Radius"}));'
)

JavaScript view(...) controls belong to their rendered view. For a control that receives Python updates or shares browser input with sibling views, use an Observable JavaScript viewof declaration.

Observable JavaScript cells

obs.ojs creates an Observable JavaScript cell, which extends JavaScript with reactive declarations. Use it for existing Observable JavaScript source, viewof declarations, and imported Observable notebook code.

obs.ojs(
'viewof radius = Inputs.range([2, 12], {value: 5, label: "Radius"})'
)

Both cell modes participate in the same Notebook Kit graph.

Markdown and HTML cells

obs.md renders Markdown. obs.html renders HTML. Both interpolate JavaScript expressions inside ${...} and rerun when referenced values change.

notebook = obs.Notebook(
obs.js("const total = 42;", display=False),
obs.md("## ${total} records"),
obs.html("<p><strong>Total:</strong> ${total}</p>"),
)

Cell options

Every helper accepts the same options.

obs.js(
"const filtered = [1, 2, 3].filter((value) => value >= 2);",
key="filtered_rows",
display=False,
pinned=True,
)
  • key is the public identity used by notebook.cells["filtered_rows"], notebook.view("filtered_rows"), readback, and graph lookup. It survives Notebook Kit HTML round trips.
  • display=False hides the cell output while keeping its values in the graph.
  • pinned=True exposes the source when the cell is selected and the notebook enables show_pinned_source. See Themes and source.
  • raw=True preserves the source string exactly, including indentation and surrounding newlines.
  • id is Notebook Kit serialization metadata. output and notebookkit_attrs expose mode-specific Notebook Kit metadata.

See Cell helpers for the full signature and error behavior, and Browser execution for the builtins available to each cell.