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/
- The preprocessor reads
book.ymland walks the TOC. For each.mdit applies small content transforms (../images/path fixups,.ipynb→.mdcross-ref rewriting). For each marimo.pyit runsmarimo export ipynb --include-outputsand converts the cells into Markdown + inline HTML, translating marimo custom elements (<marimo-callout-output>,<marimo-anywidget>) into their static analogs. - Material for MkDocs (or later, zensical — which reuses
mkdocs.ymlverbatim) 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.yml→mkdocs.ymlgeneration (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 viaextra_javascript) - Launch-button row per chapter (molab / GitHub / download)
[text](Foo.ipynb)→[text](Foo.md)cross-ref rewrite whenFoo.mdexists in the staged tree../images/→images/relative-path fixup whencontent/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-pdfif needed
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file marimo_book-0.1.3.tar.gz.
File metadata
- Download URL: marimo_book-0.1.3.tar.gz
- Upload date:
- Size: 151.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
662fb4fb342b1e736d2ac34a1049c4460ff9281f6a907efdac2f4027eb59614d
|
|
| MD5 |
d0c99531c38fdadd12d2c9a6c873e7cd
|
|
| BLAKE2b-256 |
8bba17d07538e3bb83850ce3a84a4c54317bc5f4cb727aaf42cd764b57e20a60
|
Provenance
The following attestation bundles were made for marimo_book-0.1.3.tar.gz:
Publisher:
publish.yml on ljchang/marimo-book
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
marimo_book-0.1.3.tar.gz -
Subject digest:
662fb4fb342b1e736d2ac34a1049c4460ff9281f6a907efdac2f4027eb59614d - Sigstore transparency entry: 1393343558
- Sigstore integration time:
-
Permalink:
ljchang/marimo-book@d31b99286ee18ce48ac65af03a8bf86f589165ce -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/ljchang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d31b99286ee18ce48ac65af03a8bf86f589165ce -
Trigger Event:
push
-
Statement type:
File details
Details for the file marimo_book-0.1.3-py3-none-any.whl.
File metadata
- Download URL: marimo_book-0.1.3-py3-none-any.whl
- Upload date:
- Size: 77.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c11bd51eea8c339e53348f83b68a91f646a9caa4e392ba28d2a4eacdf823834
|
|
| MD5 |
7120da71b3e84dc09629db7e6d0d9831
|
|
| BLAKE2b-256 |
ee90c5f237ad70526d3ea3982f80ef39bf21cdcb749e721f059c0ec8de82605f
|
Provenance
The following attestation bundles were made for marimo_book-0.1.3-py3-none-any.whl:
Publisher:
publish.yml on ljchang/marimo-book
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
marimo_book-0.1.3-py3-none-any.whl -
Subject digest:
7c11bd51eea8c339e53348f83b68a91f646a9caa4e392ba28d2a4eacdf823834 - Sigstore transparency entry: 1393343573
- Sigstore integration time:
-
Permalink:
ljchang/marimo-book@d31b99286ee18ce48ac65af03a8bf86f589165ce -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/ljchang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d31b99286ee18ce48ac65af03a8bf86f589165ce -
Trigger Event:
push
-
Statement type: