Skip to main content

Build clean, searchable static books from marimo notebooks and markdown

Project description

marimo-book

Build clean, searchable static books from marimo notebooks and Markdown files.

marimo-book is a Jupyter-Book-style static site generator built specifically for marimo .py notebooks. It produces polished multi-page sites with:

  • Collapsible sidebar and chapter-aware navigation
  • Fast full-text search across prose and baked cell outputs
  • Admonitions, math, figures, tables with Material for MkDocs defaults
  • Anywidgets that render statically (no marimo kernel required)
  • Launch buttons per-chapter for molab / GitHub / download .py
  • Dark-mode toggle that persists across navigation
  • GitHub Pages deploy workflow scaffolded in for you

Status

Alpha (v0.1.0a1, April 2026). marimo-book is usable end-to-end and is actively building a real course site (dartbrains), but the book.yml schema may still change before v1.0. Pin the exact version in your project until we signal stability.

Install

pip install marimo-book

Requires Python 3.11+.

Quickstart

# Scaffold a new book
marimo-book new mybook
cd mybook

# Live-reload dev server (http://127.0.0.1:8000/)
marimo-book serve
#
# Note on macOS: mkdocs's browser auto-reload is flaky on some
# macOS setups. If the browser doesn't refresh automatically after a
# save, hard-refresh (Cmd-R). The preprocessor + rebuild are
# reliable; only the browser push is affected.

# One-shot static build (emits ./_site/)
marimo-book build

# Validate book.yml + content without building
marimo-book check

# Remove build artifacts
marimo-book clean

Deploy to GitHub Pages by pushing the scaffolded workflow (.github/workflows/deploy.yml) to main on a repo with Pages enabled.

How it works

Two-stage build, by design:

content/*.md + *.py + book.yml
  → marimo-book preprocessor
  → _site_src/docs/*.md  +  _site_src/mkdocs.yml
  → mkdocs build (Material theme)
  → _site/
  1. The preprocessor reads book.yml and walks the TOC. For each .md it applies small content transforms (MyST :::{glossary} fence stripping, {download} role rewrite, ../images/ path fixups, .ipynb.md cross-ref rewriting). For each marimo .py it runs marimo export ipynb --include-outputs and converts the cells into Markdown + inline HTML, translating marimo custom elements (<marimo-callout-output>, <marimo-anywidget>) into their static analogs.
  2. Material for MkDocs (or later, zensical — which reuses mkdocs.yml verbatim) builds the final HTML.

The preprocessor is not a mkdocs plugin — it emits plain Markdown + inline HTML. This keeps the shell swappable: Material today, zensical tomorrow, or a hand-rolled Jinja shell as a last-resort fallback.

book.yml

title: My Book
description: A static site from marimo notebooks + Markdown.
authors:
  - name: Your Name
    orcid: 0000-0000-0000-0000       # optional
repo: https://github.com/you/yourbook
branch: main

theme:
  palette:
    primary: "#1976D2"
    accent:  "#FF9800"

launch_buttons:
  molab: true          # "Open in molab" button on every .py page
  github: true         # "View on GitHub"
  download: true       # "Download .py source"

# Per-widget default state for anywidgets whose JS needs initial model
# values to render on first paint. Literal kwargs from the cell override
# these; unset keys fall through to the widget's own JS defaults.
widget_defaults:
  CompassWidget:
    b0: 3.0

toc:
  - file: content/intro.md
  - section: Part I
    children:
      - file: content/chapter1.py
      - file: content/chapter2.py
  - section: Part II
    children:
      - file: content/chapter3.py
      - url: https://example.org/external-reading
        title: External Reading

See marimo-book new for a full starter template with comments on every field.

What's supported in v0.1

Material for MkDocs handles natively (free):

  • Full-text search, dark mode, keyboard shortcuts, code-copy buttons, collapsible sidebar, breadcrumbs, next/previous navigation, admonitions (!!! note / !!! tip / !!! warning / etc.), math, responsive theme, edit-this-page link, analytics, top-of-page banner

Preprocessor adds:

  • book.ymlmkdocs.yml generation (TOC, theme, palette, fonts, extensions, plugins all derived)
  • .py → rendered Markdown + inlined anywidget / callout / image outputs
  • Static rehydration of anywidgets via a small JS shim (marimo_book.js, loaded via extra_javascript)
  • Launch-button row per chapter (molab / GitHub / download)
  • MyST {download}\label
  • :::{glossary} fence stripping (definition lists pass through natively)
  • [text](Foo.ipynb)[text](Foo.md) cross-ref rewrite when Foo.md exists in the staged tree
  • ../images/images/ relative-path fixup when content/ is flattened
  • First-code-cell hiding (the setup-imports convention) — opt out via defaults.hide_first_code_cell: false

Notebook dependencies

Notebooks need their imports satisfied at build time (marimo re-executes every cell to capture outputs). marimo-book supports two modes; pick in book.yml:

dependencies:
  mode: env       # default — reuse the active venv
  # mode: sandbox # per-notebook PEP 723 isolation via uv

env mode (default). Whatever Python env runs marimo-book provides the deps. The typical consumer has a pyproject.toml at the book root listing notebook dependencies (numpy, pandas, your domain package, etc.), installs with pip install -e . or uv pip install -e ., and runs marimo-book from that env. Fast, straightforward, good when all notebooks share the same stack.

sandbox mode. Passes --sandbox to marimo export. Each notebook must declare its own deps via PEP 723 inline script metadata:

# /// script
# dependencies = [
#     "marimo>=0.23",
#     "numpy>=2.0",
#     "pandas>=2.0",
# ]
# ///

import marimo
# ...

At build time, marimo uses uv run --isolated to provision a fresh env per notebook. ~5–10 s on first run, cached after. Notebooks become portable — copy a .py into any repo with uv installed and it just works. The book root doesn't need a pyproject.toml.

Override per invocation:

marimo-book build --sandbox    # force sandbox regardless of book.yml
marimo-book build --no-sandbox # force env mode
marimo-book serve --sandbox    # slower iteration, but reproducible

Use env for local dev loops and sandbox on CI where reproducibility matters more than rebuild speed.

Broken-link checking

mkdocs build --strict (use marimo-book build --strict) already fails on broken in-tree links and anchors. For external URLs and image src attributes, opt into the htmlproofer plugin:

# book.yml
check_external_links: true
pip install 'marimo-book[linkcheck]'
marimo-book build --strict

External link checking hits the live web, so it's slow (~1–3 s per link). Keep it off on CI unless you're cutting a release.

Not in v0.1 (planned):

  • WASM / hybrid render modes — static only in v0.1; architecture already supports the branch
  • Dependency-graph-aware incremental build cache
  • BibTeX citations with hover-cards (no book needs them yet)
  • PDF / EPUB export — opt-in via mkdocs-with-pdf if needed

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

marimo_book-0.1.0a2.tar.gz (86.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

marimo_book-0.1.0a2-py3-none-any.whl (45.3 kB view details)

Uploaded Python 3

File details

Details for the file marimo_book-0.1.0a2.tar.gz.

File metadata

  • Download URL: marimo_book-0.1.0a2.tar.gz
  • Upload date:
  • Size: 86.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for marimo_book-0.1.0a2.tar.gz
Algorithm Hash digest
SHA256 26f63efcf7010c3ce531158044172ec056dd3d5f1316014f73a9cb3172872070
MD5 61cfec29f3daea8a036e3b14317af550
BLAKE2b-256 914d891cadbc6ea29d41d451cbf68aed1f491bda34d9fcf08cd2331466339c9c

See more details on using hashes here.

Provenance

The following attestation bundles were made for marimo_book-0.1.0a2.tar.gz:

Publisher: publish.yml on ljchang/marimo-book

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file marimo_book-0.1.0a2-py3-none-any.whl.

File metadata

  • Download URL: marimo_book-0.1.0a2-py3-none-any.whl
  • Upload date:
  • Size: 45.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for marimo_book-0.1.0a2-py3-none-any.whl
Algorithm Hash digest
SHA256 3c87ac3c796e880a701766b017cd5ddbbdad23d4c0106c188d95bf60ca14ab7a
MD5 3b79177e1d1882919dd97786410eb384
BLAKE2b-256 9be8349a21fbea7a9faa939fd212a8ecb9e30fa4c2adf5bb5e30a87a0218f01e

See more details on using hashes here.

Provenance

The following attestation bundles were made for marimo_book-0.1.0a2-py3-none-any.whl:

Publisher: publish.yml on ljchang/marimo-book

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page