Skip to main content

Export Notebook Kit HTML

to_notebook_html() returns the current notebook definition as a Notebook Kit document. Loaded documents preserve import rewrites requested during construction.

import observablejs as obs

notebook = obs.Notebook(
obs.md("# Report", key="title"),
obs.js(
"const total = rows.reduce((sum, row) => sum + row.value, 0);",
key="total",
display=False,
),
obs.js("html`<p>Total: ${total}</p>`", key="summary"),
title="Weekly report",
theme="glacier",
variables={"rows": [{"value": 12}, {"value": 30}]},
)

print(notebook.to_notebook_html())
<!doctype html>
<notebook theme="glacier">
<title>Weekly report</title>
<script id="1" type="text/markdown" data-pyobservablejs-key="title">
# Report
</script>
<script id="2" type="module" data-pyobservablejs-key="total" hidden="">
const total = rows.reduce((sum, row) => sum + row.value, 0);
</script>
<script id="3" type="module" data-pyobservablejs-key="summary">
html`<p>Total: ${total}</p>`
</script>
</notebook>

The output is a standard Notebook Kit document: title becomes a <title>, the theme becomes the <notebook> attribute, display=False becomes hidden, and each cell keeps its key and assigned id.

What the HTML does not carry

The document is the definition, not the session. Two kinds of state stay in Python:

  • Python variables. The exported HTML references rows, but the value lives in the session. A consumer of the document must define rows itself or load the HTML back with from_html(..., variables=...).
  • File attachment records. FileAttachment("name") calls stay in the source, but the registered data URLs and URL records are session state. When the text is consumed independently, its environment must provide the referenced files.

Cell keys use the data-pyobservablejs-key script attribute. Loading the HTML restores the same public identity. The script id remains Notebook Kit serialization metadata.

Round trips

Exported HTML loads back with full fidelity of the definition:

html_text = notebook.to_notebook_html()
restored = obs.Notebook.from_html(html_text, variables={"rows": []})

ObservableHQ-derived notebooks record their classic standard-library profile in the exported document, so a round trip through from_html preserves require and the other classic builtins.

Use with Notebook Kit tooling

The exported file is valid input for Notebook Kit's own tooling, so a notebook authored in Python can graduate to a standalone Observable project:

from pathlib import Path

Path("report.html").write_text(notebook.to_notebook_html(), encoding="utf-8")

See Notebook.to_notebook_html for the serialization contract and File attachments for the attachment boundary.