Claude Code for Gradio ML UI — Workflow Guide
The Setup
You are building machine learning demo interfaces with Gradio, a Python library that creates web UIs for ML models with minimal code. Gradio provides pre-built input/output components (text, image, audio, video) and automatically generates a web interface from a Python function. Claude Code can create Gradio apps, but it over-engineers the UI with Flask/React instead of using Gradio’s declarative approach.
What Claude Code Gets Wrong By Default
-
Builds a Flask API + React frontend. Claude creates a REST API with Flask and a React UI for the ML demo. Gradio replaces both — a single
gr.Interface(fn=predict, inputs="text", outputs="text")creates the full web app. -
Writes custom file upload handling. Claude implements multipart form upload with validation. Gradio components like
gr.Image(),gr.Audio(), andgr.File()handle upload, preprocessing, and type conversion automatically. -
Ignores Blocks for complex layouts. Claude stacks components linearly with
gr.Interface. For complex UIs with tabs, columns, and conditional visibility, Gradio hasgr.Blocks()— a more flexible layout system withgr.Row(),gr.Column(), andgr.Tab(). -
Does not use Gradio’s sharing features. Claude deploys to a cloud server for sharing. Gradio has
share=Truethat creates a public URL through a tunnel, and Hugging Face Spaces for permanent free hosting — no server deployment needed.
The CLAUDE.md Configuration
# Gradio ML Demo Project
## UI Framework
- Library: Gradio (Python ML web interfaces)
- Simple: gr.Interface for basic input/output
- Complex: gr.Blocks for custom layouts
- Hosting: Hugging Face Spaces or share=True
## Gradio Rules
- gr.Interface: fn, inputs, outputs for simple demos
- gr.Blocks: with gr.Blocks() as demo for complex UIs
- Components: gr.Textbox, gr.Image, gr.Audio, gr.Slider, etc.
- Events: component.change(), button.click() for interactivity
- Preprocessing: Gradio converts uploads to numpy/PIL/etc.
- State: gr.State for session-persistent data
- Queue: demo.queue() for concurrent request handling
## Conventions
- Keep predict function pure — Gradio handles I/O
- Use gr.Blocks for anything beyond simple in/out
- gr.Examples for preloaded example inputs
- CSS: gr.Blocks(css="...") for custom styling
- Launch: demo.launch(server_name="0.0.0.0") for containers
- Queue for long-running inference
- Type hints on functions for better component inference
Workflow Example
You want to create a demo for an image classification model. Prompt Claude Code:
“Create a Gradio app for an image classification model. Use gr.Blocks with an image upload, a classify button, a label output showing top 5 predictions with confidence bars, and example images. Add a queue for handling multiple requests.”
Claude Code should create a gr.Blocks() layout with gr.Image(type="pil") for upload, gr.Button("Classify"), gr.Label(num_top_classes=5) for output, gr.Examples with sample images, connect the button click to the prediction function, and call demo.queue().launch().
Common Pitfalls
-
Not using queue for ML inference. Claude launches without
.queue(). ML inference is slow — without queuing, concurrent requests fail or timeout. Always adddemo.queue()before.launch()for production demos. -
Loading model inside the prediction function. Claude loads the model on every request with
model = load_model()inside the predict function. Load the model once at module level — Gradio reuses the function for every request. -
Missing Hugging Face Spaces configuration. Claude creates a Gradio app but does not include the
requirements.txtorapp.pynaming expected by Spaces. Hugging Face Spaces expectsapp.pyas the entry point andrequirements.txtfor dependencies.