ExamplenotebookbeginnerRunnablenotebook-to-app
Tutorial: Notebook to Web App in Five Minutes
This notebook shows how to turn a small Python function into a shareable interface with Gradio or Streamlit. It focuses on one clear input -> processing -> output flow so the app wrapper stays explicit and easy to review.
Key Facts
- Level
- beginner
- Runtime
- Notebook • Streamlit / Gradio
- Pattern
- Notebook to shareable application
- Interaction
- Runnable sandbox • Notebook
- Updated
- 21 March 2026
Navigate this example
Library
Browse examplesReopen the wider library to compare adjacent patterns and linked learning paths.Interaction
Run sandbox nowTry the interaction directly in this example’s guided sandbox surface.Source
Open full sourceRead the real implementation, highlighted checkpoints, and runtime requirements.MCP
Call via MCPUse the same resource inside agents, deterministic exports, and MCP setup flows.
Linked principles
1-notebook-to-web-app.ipynb
json
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Tutorial: Notebook to Web App in Five Minutes\n",
"\n",
"This notebook shows how to turn a small Python function into a shareable interface with Gradio or Streamlit. It focuses on one clear input -> processing -> output flow so the app wrapper stays explicit and easy to review.\n",
"\n",
"**Audience**\n",
"- Data scientists and AI builders who prototype in notebooks first.\n",
"\n",
"**Prerequisites**\n",
"- Basic Python functions\n",
"- Jupyter notebooks\n",
"- Optional: `gradio` or `streamlit` installed locally\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Outline\n",
"\n",
"1. Start with one clear function\n",
"2. Make the input and output contract explicit\n",
"3. Wrap the function with Gradio\n",
"4. Wrap the same function with Streamlit\n",
"5. Decide when this should stay staged instead of fully productized\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from __future__ import annotations\n",
"\n",
"def predict_sentiment(text: str) -> str:\n",
" lowered = text.lower()\n",
" if \"good\" in lowered:\n",
" return \"Positive\"\n",
" if \"bad\" in lowered:\n",
" return \"Negative\"\n",
" return \"Neutral\"\n",
"\n",
"samples = [\n",
" \"The launch looked good and the team felt calm.\",\n",
" \"The handoff went bad after the last deployment.\",\n",
" \"We need one more review before deciding.\",\n",
"]\n",
"\n",
"[(sample, predict_sentiment(sample)) for sample in samples]\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 1 - Keep the notebook logic narrow\n",
"\n",
"The function above is the real asset. If the notebook cannot point to one bounded function, the app wrapper usually becomes messy too.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"app_contract = {\n",
" \"input\": \"One sentence from the user\",\n",
" \"processing\": \"Run predict_sentiment(text)\",\n",
" \"output\": \"A single label: Positive, Negative, or Neutral\",\n",
"}\n",
"\n",
"app_contract\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 2 - Gradio wrapper\n",
"\n",
"Gradio is a fast choice when you want a lightweight demo or model surface.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import gradio as gr\n",
"\n",
"gradio_snippet = \"\"\"\n",
"demo = gr.Interface(\n",
" fn=predict_sentiment,\n",
" inputs=gr.Textbox(label=\"Enter your sentence\"),\n",
" outputs=gr.Label(),\n",
")\n",
"demo.launch()\n",
"\"\"\"\n",
"\n",
"print(gradio_snippet)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 3 - Streamlit wrapper\n",
"\n",
"Streamlit is useful when the notebook is becoming more dashboard-like and you need a little more layout structure.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import streamlit as st\n",
"\n",
"streamlit_snippet = \"\"\"\n",
"st.title(\"Sentiment Predictor\")\n",
"text = st.text_input(\"Enter your sentence\")\n",
"if text:\n",
" st.write(predict_sentiment(text))\n",
"\"\"\"\n",
"\n",
"print(streamlit_snippet)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Step 4 - Review the execution path\n",
"\n",
"This example is staged executable rather than a full in-product runtime. The key review questions are:\n",
"\n",
"- Is the notebook function clean enough to expose directly?\n",
"- Are the user input and output labels explicit?\n",
"- Does the team need a quick demo surface or a more durable product wrapper?\n",
"- Is it acceptable to stay at notebook-plus-wrapper stage for now?\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Related principles
- P1delegationDesign for delegation rather than direct manipulationDesign experiences around the assignment of work, the expression of intent, the setting of constraints, and the review of results, rather than requiring users to execute each step manually.Open principle →
- P4trustApply progressive disclosure to system agencyProvide the minimum information necessary by default, while enabling users to inspect additional detail when confidence, understanding, or intervention is required.Open principle →
- P7trustEstablish trust through inspectabilityUsers should be able to examine how a result was produced when confidence, accountability, or decision quality is important.Open principle →
- P9orchestrationRepresent delegated work as a system, not merely as a conversationWhere work involves multiple steps, agents, dependencies, or concurrent activities, it should be represented as a structured system rather than solely as a message stream.Open principle →