Gradio
// Build and deploy ML demo interfaces with proper state management, queuing, and production patterns.
$ git log --oneline --stat
stars:1,933
forks:367
updated:March 4, 2026
SKILL.mdreadonly
SKILL.md Frontmatter
nameGradio
descriptionBuild and deploy ML demo interfaces with proper state management, queuing, and production patterns.
metadata[object Object]
Gradio Patterns
Interface vs Blocks
gr.Interfaceis for single-function demos — usegr.Blocksfor anything with multiple steps, conditional UI, or custom layout- Blocks gives you
.click(),.change(),.submit()event handlers — Interface only has one function - Mixing Interface inside Blocks works but creates confusing state — pick one pattern per app
State Management
gr.State()creates per-session state — it resets when the user refreshes the page- State values must be JSON-serializable or Gradio silently drops them — no custom classes without serialization
- Pass State as both input AND output to persist changes:
fn(state) -> state— forgetting the output loses updates - Global variables shared across users cause race conditions — always use
gr.State()for user-specific data
Queuing and Concurrency
- Without
.queue(), long-running functions block all other users — always calldemo.queue()before.launch() concurrency_limit=1on a function serializes calls — use for GPU-bound inference that can't parallelizemax_sizein queue limits waiting users — without it, memory grows unbounded under load- Generator functions with
yieldenable streaming — but they hold a queue slot until complete
File Handling
- Uploaded files are temp paths that get deleted after the request — copy them if you need persistence
gr.File(type="binary")returns bytes,type="filepath"returns a string path — mismatching causes silent failures- Return
gr.File(value="path/to/file")for downloads, not raw bytes — the component handles content-disposition headers - File uploads have a default 200MB limit — set
max_file_sizeinlaunch()to change it
Component Traps
gr.Dropdown(value=None)withallow_custom_value=Falsecrashes if the user submits nothing — set a default or make it optionalgr.Image(type="pil")returns a PIL Image,type="numpy"returns an array,type="filepath"returns a path — inconsistent inputs break functionsgr.Chatbotexpects list of tuples[(user, bot), ...]— returning just strings doesn't rendervisible=Falsecomponents still run their functions — usegr.update(interactive=False)to disable without hiding
Authentication
auth=("user", "pass")is plaintext in code — useauth=auth_functionfor production with proper credential checking- Auth applies to the whole app — there's no per-route or per-component auth without custom middleware
share=Truewith auth still exposes auth to Gradio's servers — use your own tunnel for sensitive apps
Deployment
share=Truecreates a 72-hour public URL through Gradio's servers — not for production, just demos- Environment variables in local dev don't exist in Hugging Face Spaces — use Spaces secrets or the Settings UI
server_name="0.0.0.0"to accept external connections — default127.0.0.1only allows localhost- Behind a reverse proxy, set
root_path="/subpath"or assets and API routes break
Events and Updates
- Return
gr.update(value=x, visible=True)to modify component properties — returning just the value only changes value - Chain events with
.then()for sequential operations — parallel.click()handlers race every=5on a function polls every 5 seconds — but it holds connections open, scale carefullytrigger_mode="once"prevents double-clicks from firing twice — default allows rapid duplicate submissions
Performance
cache_examples=Truepre-computes example outputs at startup — speeds up demos but increases load time- Large model loading in the function runs per-request — load in global scope or use
gr.Statewith initialization batch=Truewithmax_batch_size=Ngroups concurrent requests — essential for GPU throughput