← BUILD YOUR FIRST AI APP IN 10 DAYS
DAY 5 OF 10
3-4 hours 3 GOALS

Day 5 of 10

Notebooks That Think For Themselves

Install Marimo, port your Day 4 assistant into a live interactive app, and share it with a single command.

TODAY'S GOALS

Jupyter has a secret problem. You can run cells in any order. Most people do. Cell 5 uses a variable defined in Cell 8. Cell 2 ran three times with different values. The notebook “works,” but when someone else opens it, it breaks silently and produces wrong results.

The notebook lies about what it computed.

Marimo fixes this at the root. Cells in Marimo are reactive: they update automatically when their inputs change, exactly like a spreadsheet formula. There is no “run order” to get wrong because order is determined by dependencies, not by you. The notebook always reflects reality.

The second thing Marimo does changes what “sharing a project” means entirely: one command turns your notebook into a clean web application. No Flask. No React. No backend. Same code, now it is a UI.

Install Marimo

Marimo runs locally. But first, meet uv — the tool you will use for all local Python work from here on.

uv is a Python package manager that is 10–100x faster than pip and handles virtual environments automatically. No more global installs. No more “it works on my machine.” Every project gets its own clean environment.

Install uv once:

curl -LsSf https://astral.sh/uv/install.sh | sh

Then create your project:

uv init ai-assistant
cd ai-assistant
uv add marimo groq

uv add installs the package and records it in your project. Anyone who clones your repo can run uv sync and get the exact same environment.

Store your API key in a .env file. Never paste it directly into code you might share.

# Create the .env file
echo "GROQ_API_KEY=paste-your-key-here" > .env

# Make sure git never sees it
echo ".env" >> .gitignore

Also create a .env.example so collaborators know what keys are needed:

echo "GROQ_API_KEY=" > .env.example

Now open your notebook:

uv run --env-file .env marimo edit assistant.py

uv run --env-file .env loads your .env into the environment before running. Your os.environ.get("GROQ_API_KEY") calls just work. No dotenv library needed, no manual export in the terminal.

Yes, .py. Marimo notebooks are plain Python files. No hidden JSON, no corrupted metadata, no merge conflicts you cannot read. Open one in any text editor and you see exactly what it does.

The Reactive Difference

Open the notebook Marimo creates. Define a variable in one cell:

name = "builder"

Use it in another:

print(f"Hello, {name}.")

Now change name in the first cell. Watch the second cell update instantly without you touching it. That is reactivity. You never think about “did I run this in the right order?” because there is no wrong order.

Port Your Assistant

Take the specialized assistant you built on Day 4 and bring it into Marimo with a real interactive UI. Marimo has built-in UI components that work as reactive inputs.

import marimo as mo
from groq import Groq
import os

client = Groq(api_key=os.environ.get("GROQ_API_KEY"))
# Your system prompt from Day 4
SYSTEM = """Paste your system prompt here.
The one that made the chatbot actually useful for your domain."""
# Personality selector
personality = mo.ui.dropdown(
    options=["Your Day 4 Persona", "Socratic Teacher", "Devil's Advocate", "Direct Coach"],
    value="Your Day 4 Persona",
    label="Assistant mode"
)
personality
# Question form — .form() adds a Submit button and only fires the next cell when submitted
question = mo.ui.text(placeholder="Ask anything...", full_width=True).form(
    submit_button_label="Ask →"
)
question
# This cell only runs when the form is submitted
mo.stop(question.value is None, mo.md("*Type a question and click Ask.*"))

system_prompts = {
    "Your Day 4 Persona": SYSTEM,
    "Socratic Teacher": "Answer every question with a question that leads the student toward the answer themselves. Never give the answer directly.",
    "Devil's Advocate": "Argue the opposite of whatever position the user takes. Be rigorous, not contrarian.",
    "Direct Coach": "Give one clear action. Skip the context. Skip the options. Just the move.",
}

response = client.chat.completions.create(
    model="llama-3.3-70b-versatile",
    messages=[
        {"role": "system", "content": system_prompts[personality.value]},
        {"role": "user", "content": question.value}
    ]
)

mo.md(f"**{personality.value}:**\n\n{response.choices[0].message.content}")

This is no longer a notebook. It is a UI. The user picks a mode, types a question, clicks Ask. The cell that depends on ask_btn.value fires, the answer appears. No print(). No code visible unless you want it.

Run as an App

uv run --env-file .env marimo run assistant.py

Same file. Now it opens as a clean web application: no cell controls, no code, just the interface. You built an app without learning a single web framework.

Share it locally: uv run --env-file .env marimo run assistant.py --host 0.0.0.0 opens it to anyone on your network.

Share It

Push assistant.py to a public GitHub repo. Go to marimo.io, connect your GitHub, deploy. Anyone with the link can use your app. No server to manage, no infrastructure cost.

This is the thing you share today. Not a screenshot. A live link to a working product with your name on it.

What Colab Taught vs What Marimo Teaches

Colab taught you to build. Marimo teaches you to present.

The gap between “a working notebook” and “something a non-technical person can use” used to require weeks of web development. Marimo closes that gap to a single command.

Tomorrow you give your app something it doesn’t have yet: the ability to know things about you.