User interfaces
The UI is outside the Rust core. It is a client of the core's API (REST plus websocket, or the same JSON shapes over an in-app bridge), and more than one UI can exist. This page lists what any notebook UI needs, whatever it is written in.
Required pieces:
- Cell list with command and edit modes, keyboard shortcuts, move, split, merge, copy, paste, undo.
- Code editor: CodeMirror 6 (JupyterLab default) or Monaco. Language mode comes from
kernel_info_reply.language_info.codemirror_mode. - Completion and inspection popups wired to
complete_requestandinspect_request. - Markdown cells: CommonMark + GFM tables, math via KaTeX or MathJax, sanitized HTML, cell attachments.
- Output area with a MIME renderer registry and a priority order:
application/vnd.jupyter.widget-view+json,text/html,image/svg+xml,image/png,image/jpeg,text/markdown,text/latex,text/plain, plusapplication/json, Vega/Vega-Lite, Plotly.text/htmlwith<script>andisolatedmetadata means iframe sandboxing. - Stream handling: merge consecutive chunks from the same stream, honor
\r(progress bars),\b, and ANSI SGR colors. clear_output(wait=True),update_display_databydisplay_id, output truncation for runaway loops, iopub rate limiting.- Execution indicators:
In [*],In [n], busy/idle, queued, aborted. input()prompt in the cell output area, password mode.- Kernel picker, status bar, restart/interrupt controls.
- File browser, open/save, autosave, "dirty" tracking, checkpoints.
- Trust model: HTML/JS outputs in a notebook you did not execute are untrusted and must be sanitized until re-executed. The server keeps the signatures (Jupyter's
nbsignatures.db) and marks code cellsmetadata.trustedwhen it serves a notebook; a UI sendstrusted: trueon cells whose output it produced, andPOST /api/contents/{path}/trusttrusts a notebook on request.
UI implementations, each a separate client of the same API:
- Existing Jupyter frontends: VS Code, JupyterLab's static bundle, Juno Connect. No UI work; the API is the contract they test.
- A TypeScript web UI. Reuse CodeMirror, KaTeX, and optionally
@jupyterlab/rendermimeand@jupyterlab/outputareaas libraries without the rest of JupyterLab. Runs in a browser, or inside a native shell's web view. ganymede-ui is a prototype of this one, built on JupyterLab's notebook through datalayer/jupyter-ui. - A native shell with a web view for rendering, such as a Swift app on iPadOS with
WKWebView. The shell owns navigation, files, keyboard, and app lifecycle; the web view runs the renderers from option 2, sincetext/htmloutputs, math, Vega, Plotly, and widgets are JavaScript. The shell talks to the core over HTTP, or in-process through a bridge. - Fully native rendering (SwiftUI, or GPUI as Zed does). Loses
text/htmloutput, which breaks pandas, plotly, bokeh, altair, and widgets. Fine for a REPL, not for a general notebook.
What the core owes every UI: a documented, stable API, and nothing that assumes which UI is on the other end. Rust UI frameworks (Leptos, Dioxus, Yew, egui) are out of scope.