🍃 Share notebooks from GitHub!

Badge generator

Teaching methods

The marimo team supports educators trying marimo. Reach out for help with course design, molab best practices, classroom deployment, or anything else.

Contact us

There are many ways to teach with marimo notebooks:

  1. Follow-along: pre-written code lets learners run and modify examples as they read.
  2. Notebooks can be used as assignments (i.e., “fill in these cells”).
  3. Assignments: distribute a notebook with empty cells for learners to complete, like a structured problem set.
  4. Lab reports: learners build notebooks from scratch to document their work, the closest format to how notebooks are used professionally.

As always, the devil is in the details: the patterns below are a great place to start. Much of this section is inspired by or taken from Teaching and Learning with Jupyter. We are grateful to its authors for making their work available under an open license.

Shift-Enter

Learners start with a complete notebook and re-execute the cells in order, optionally filling in prose cells with analysis or description. This pattern is well suited to introducing new topics or checking understanding through warmup exercises, and works with any audience in a synchronous setting. It gives learners a working example immediately, though engagement tends to be low because learners are not yet making decisions.

Fill in the Blanks

Some code cells are provided complete; learners must complete the rest. This reduces cognitive load by directing attention to a single concept, such as filtering a dataset, and works for any audience in assignments and lab sessions. The risk is that learners delegate the task to an AI tool, and the difficulty of the blanks can be hard to calibrate for a mixed-ability group.

Tweak and Twiddle

Learners start with a complete, working notebook and are asked to alter parameters in order to achieve a specified goal. This pattern supports compare-and-contrast exercises and the acquisition of domain knowledge. It is particularly effective for learners who have domain knowledge but little programming experience, in fixed-time workshop exercises or pair programming sessions. It helps learners overcome anxiety about code. The main difficulties are that learners may not know where to start, or may spend time following unproductive tangents.

Notebook as App

The notebook is presented as an interactive dashboard, with prose kept in a separate document so the interface looks like a standalone application. This pattern is designed for non-programmers exploring datasets. It can replace slides in a lecture if the instructor knows the material well enough to navigate live, or it can be used after a physical lab experiment for data analysis. It requires less effort to build than a custom UI, but it demands thorough testing and does not develop learners' programming skills.

Top-Down Delivery

Learners are given just enough control to reach a motivating result quickly. The goal is engagement on the first day of a course or workshop. This pattern works for any audience but is most effective with learners who have limited programming experience, in tutorials and synchronous workshops. Student engagement is the main advantage; the main challenge is finding the right level of detail for a group with mixed abilities.

Coding as Translation

Learners convert prose to code, or code to prose. The purpose is to connect concepts to implementations and implementations to concepts. It is well suited to learners who understand theory but struggle with coding, or the reverse. A notebook with scaffolding text and possibly some pre-written code works well as the format. The barrier to entry is low for learners with limited programming background; the challenge, again, is calibrating difficulty for a mixed-ability group.

Symbolic Math

Learners use SymPy to do symbolic mathematics inside the notebook, extending the coding-as-translation pattern to include converting mathematical expressions to code or code to mathematical expressions. This works well for STEM students interested in theory and fits any format. It introduces another real-world tool, but SymPy's syntax is yet another thing to learn on top of the mathematics itself.

Numerical Methods and Simulation

Learners use calculation or simulation rather than closed-form analysis to make a concept tangible before the mathematical abstraction is introduced. This requires some programming skill and fits any format. Going from specific to general is often more engaging and approachable than the reverse, but debugging numerical code can be difficult.

Learn an API

A key library or API is introduced example by example, in order of increasing complexity or decreasing frequency of use. The purpose is to direct learner attention toward tools they will use in other parts of the course. This works for learners with some programming skill and patience. It guides learning in a sensible order, which AI tools sometimes struggle to provide on their own. The risk is that learners lose sight of the larger goal, or prefer to ask an AI for help as needed rather than building systematic knowledge.

Choose Your Data

Learners replace the dataset in a provided notebook with one of their own choosing, possibly making some modifications to the code. The goal is engagement through personal relevance, and it works well for learners with a specific domain interest such as sports analytics. A common structure is a shared first half followed by independent exploration, sometimes leading to presentations. It improves self-efficacy, but learners may struggle to find suitable data, encounter data that is too messy to work with, or have interests that do not overlap enough for a shared debrief.

Test-Driven Learning

The instructor provides a notebook full of tests; learners must write code that makes those tests pass. This teaches learners to think in terms of a specification. It works for learners who want firm goalposts and fits homework exercises well. The task is well-defined and easy to stay focused on, but it is very easy for learners to have an AI generate the code without understanding it.

A useful pattern is to place a stub function in one cell and pytest tests in a separate cell. Because of marimo's reactive execution, every time the learner edits their implementation the tests rerun automatically, giving immediate feedback on correctness without giving away the answer. For example, the stub cell might contain:

def add(x, y):
    """Return the sum of x and y."""
    # your code here
    pass

and the test cell:

def test_add_integers():
    assert add(5, 6) == 11

def test_add_floats():
    assert isinstance(add(4, 2.1), float)

Bug Hunt

Learners are given a notebook with one or more bugs, which may include misleading prose. The purpose is to develop critical reading skills, which is especially important for learners who regularly use AI tools. It requires enough programming experience to debug systematically and works well as a homework exercise. Some learners find the detective aspect genuinely engaging, and the skill is extremely valuable. The main challenges are calibrating bug difficulty and helping learners know when they are done.

Adversarial Programming

Given a notebook full of code, learners write tests designed to break it. This is the reverse of the bug hunt. The purpose is to develop critical thinking, and it requires the same level of programming experience. It works well as a homework exercise. It helps learners appreciate the difficulty of writing robust code and sharpens their debugging skills, but learners sometimes find repetitive ways to break the code rather than probing for distinct failure modes.

Things to Watch Out For

  • Variable names: Underscore-prefixed variable names in marimo have a meaning different from their common usage in Python and require some understanding of lexical scope. The recommended remedy is a functions-early teaching methodology, which has a sound pedagogical basis and prepares learners for idiomatic Python.
  • Image files: For security reasons, marimo requires local image files to be placed in a folder named public directly below the directory from which the notebook is launched, and to be referenced in Markdown as /public/image.ext. This occasionally trips up beginners who don't yet understand how file system paths work. The mo.image function works around this restriction but cannot be embedded inside a Markdown string.
  • Testing: Using pytest in marimo is straightforward, provided that each test cell contains only tests and nothing else.
  • Math rendering: marimo uses KaTeX rather than MathJax for rendering mathematics. The two systems are largely compatible but differ in some commands and environments. See the appendix for details.

KaTeX vs. MathJax

marimo uses KaTeX for rendering math rather than MathJax. KaTeX is faster and has slightly narrower coverage, and it fails silently when it encounters an unsupported command.

Use Raw Strings

LaTeX lives in Python strings in marimo, so use r"..." to preserve backslashes:

mo.md(r"$\frac{1}{2}$")   # correct
mo.md("$\frac{1}{2}$")    # wrong: \f is a form-feed character

MathJax to KaTeX

CategoryMathJaxKaTeX
Text\mbox, \bbox\text{}
Text style\textsc, \textsl\text{}
Environments\begin{eqnarray}\begin{align}
\begin{multiline}\begin{gather}
References\label, \eqref, \ref\tag{} for manual numbering
Arrays\cline, \multicolumn, \hfill, \vlinenot supported
Macros\DeclareMathOperator\operatorname{} inline
\newenvironmentnot supported
Spacing\mspace, \setlength, \strut, \rotateboxnot supported
Conditionals\if, \else, \fi, \ifxnot supported

The following commands do work in KaTeX despite claims to the contrary in some older references: \newcommand, \def, \hbox, \hskip, \cal, \pmb, \begin{equation}, \begin{split}, \operatorname*.

Shared Macros Across Cells

\newcommand works inline within a single cell. For macros that need to be available across multiple cells, use mo.latex(filename="macros.tex") in the same cell as your import marimo statement.

Migration Checklist

  1. Find and replace \mbox{ with \text{.
  2. Wrap all LaTeX strings in raw string literals (r"...").
  3. Replace \begin{eqnarray} with \begin{align}.
  4. Replace \DeclareMathOperator with \operatorname{}.
  5. Remove \label and \eqref; use \tag{} where manual numbering is needed.
  6. Verify the output visually, since KaTeX fails silently.

References

Get notified about new features and updates