Four SDKs, four different jobs
Gradio is the default and the best-supported. Its components map onto machine-learning inputs and outputs, it has ZeroGPU support, it exposes an API automatically, and most examples you find are written in it.
Streamlit re-runs your whole script top to bottom on every interaction, with st.session_state holding what must survive. That model is excellent for dashboards and data exploration and awkward for a chat interface, because a long-running generation restarts the script’s reasoning about state. Choose it when the Space is mostly charts and tables over a dataframe.
Docker is the escape hatch. You supply a Dockerfile, the Hub builds and runs it, and anything that listens on port 7860 works: FastAPI, Flask, Node, a Rust binary, a multi-process stack.
Static serves files. No server process, no sleep, no cold start.
The static Space is underrated
With transformers.js from module three, a static Space is a complete AI application that costs nothing and never sleeps:
---
title: Local Sentiment
sdk: static
app_file: index.html
---index.html loads the library from a CDN, downloads an ONNX model into the browser, and runs everything on the visitor’s device. No queue, no container, no per-request compute, and the user’s text never leaves their machine. For classifiers, embeddings, background removal, OCR and short-clip speech recognition, this is frequently the best engineering answer as well as the cheapest.
Its limits are exactly the browser’s: the model must be small enough to download once, and heavy generation is impractical.
Docker Spaces, and the one gotcha
FROM python:3.11-slim
RUN useradd -m -u 1000 user
USER user
ENV PATH="/home/user/.local/bin:$PATH" \
HF_HOME=/home/user/.cache/huggingface
WORKDIR /app
COPY --chown=user requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY --chown=user . .
EXPOSE 7860
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]Three things this gets right, and each of them is a build that fails otherwise:
- Port 7860. The platform routes to it. Listening on 8000 produces a Space that builds, starts and shows a blank page forever.
--host 0.0.0.0. Binding to localhost means nothing outside the container can reach it. Same blank page.- A non-root user with a writable home. Containers run unprivileged, and libraries that try to write a cache into a root-owned directory raise permission errors at import: usually the first confusing failure people meet here.
Reach for Docker when you need a database alongside the app, a system library that pip cannot install, a non-Python runtime, or a custom web front end. Do not reach for it to avoid learning Gradio; you will rebuild a queue, a file upload widget and a streaming response by hand.
Spaces are also a way to read code
Every public Space is a public repository. When you find one that does what you want, click Files and read it. That is a working configuration (the exact dependency versions, the model revision, the hardware, the prompt) which is worth more than documentation because it is running.
This is the fastest way to learn a new technique on the Hub, and it is also why the licence of a Space’s code matters: reading it is always fine, copying it is governed by whatever licence its readme declares, and many declare none. Ask, or write your own from what you understood.
The build is a cache, and caches go stale
All four SDKs share one build system, and it caches layers. Change requirements.txt and the dependency layer rebuilds; change only app.py and it does not. That is why a Space usually restarts in seconds and occasionally takes ten minutes.
It is also why a Space can fail in a way the current code cannot explain: a layer built against a package version that has since been yanked, or a half-downloaded model in the image cache. The factory reboot in the debugging lesson discards all of it and starts clean.
Choosing in one line
- Model demo with inputs and outputs → Gradio.
- Dashboard over a dataset → Streamlit.
- Small model, privacy, zero cost, no sleep → static plus transformers.js.
- Anything else → Docker.
Do this now
Find a public Space that does something close to what you want and read its app.py and requirements.txt end to end. Note the pinned versions and the hardware in the readme. You have just been handed a working configuration for free, which is the single most useful thing the Spaces ecosystem provides.
Every lesson here is open. Your progress is recorded once you pass the Image Generation, in Practice exam.
Check your understanding
A Docker Space builds successfully, reports itself as running, and shows a blank page. What should be checked first?
Pick the one you would defend. Your answer stays private.
Stuck on something?Ask Arjun, your AI tutor
