Module 9 — Publishing to a Hugging Face Space
The share link from the previous module is meant for iteration between engineers, not for a durable public URL. When the demo has to live at the same address for weeks and survive your laptop closing, the standard answer for Gradio apps is a Hugging Face Space: a git-backed hosting environment that runs your Python code on a chosen hardware tier and gives you a stable hf.co/spaces/<user>/<name> URL. This module walks through the creation, the mandatory files, secrets, hardware, sleep policy and embedding.
Creating the Space
A Space is a git repository with two special files: an app.py (or app_gradio.py) that Hugging Face will run, and a requirements.txt that lists the Python packages to install. On huggingface.co/new-space, pick a name, select Gradio as the SDK, choose the visibility (public or private) and the hardware tier, and the platform creates an empty repo.
Clone it locally, copy your Gradio app in, and push:
git clone https://huggingface.co/spaces/<username>/<space-name>
cd <space-name>
# Copy your Gradio app as app.py, and drop a minimal requirements.txt:
cat > requirements.txt <<'EOF'
gradio>=4.36
transformers>=4.43
torch>=2.3
EOF
git add app.py requirements.txt
git commit -m "First deploy"
git push
Within a minute or two, the Space is building; within a few more, it is running. The build log is visible on the Space page, and any missing dependency shows up there — not in a silent failure — which is why picking Spaces over a random VM is usually the right first choice.
The files a Space needs
Six files cover the vast majority of Spaces. Four are required, two are optional but worth having.
app.py(required). The Python entry point. It must construct a Gradio demo and calldemo.launch()at the module level. Hugging Face executes this file on start.requirements.txt(required for Python packages). One package per line, optionally pinned with>=or==. Everything is installed in an isolated environment on each build.README.md(required). The first block is YAML frontmatter that configures the Space: title, emoji, colors, SDK version, hardware, and whether the app is pinned. Hugging Face reads it, so it is not optional in practice even ifgit pushaccepts a repo without it..gitignore(optional). Exclude__pycache__/,.env,gradio_cached_examples/. A dirty repo is a dirty deploy.packages.txt(optional). One system package per line —ffmpeg,libsndfile1,poppler-utils— installed withaptbefore Python packages. Needed for audio and PDF workloads.Dockerfile(optional). If you want a custom base image, drop a Dockerfile and change the SDK in the frontmatter todocker. That is an escape hatch, not a default.
A minimal README.md frontmatter looks like this:
---
title: My Chat Assistant
emoji: 🤖
colorFrom: blue
colorTo: green
sdk: gradio
sdk_version: 4.44.0
app_file: app.py
pinned: false
license: apache-2.0
---
The rest of the README is plain Markdown, and it is what visitors see below the demo. Fill it with what the model does, its limitations, examples of prompts to try, and a link to any dataset or paper.
Secrets: API keys never in the repo
If your demo calls an external API — OpenAI, Anthropic, a private endpoint — the API key belongs in the Space's Settings → Repository secrets, not in the code. Secrets are exposed as environment variables inside the Space's runtime, invisible from the file system.
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
On the local machine, use a .env file with python-dotenv, and make sure .env is in .gitignore. Pushing a key to a git repo is the single most common way credentials leak to the internet, and the mistake survives forever in the git history. Rotate immediately if it happens; a two-line audit script that greps for sk- before every commit is cheap insurance.
Hardware tiers
Spaces run on a menu of hardware tiers, from free CPU to A100 GPUs. The full list changes over time, but the shape has been stable enough to plan around:
| Tier | Compute | Best for |
|---|---|---|
| CPU basic (free) | 2 vCPU, 16 GB RAM | Small models, embedding search, static tools |
| CPU upgrade | 8 vCPU, 32 GB RAM | Larger CPU models, faster startup |
| T4 small | 1 GPU, 15 GB VRAM | 7B-parameter chat models in int4 |
| A10G | 1 GPU, 24 GB VRAM | 13B-parameter models, image generation |
| A100 | 1 or 4 GPUs, 40 or 80 GB VRAM | Large models, video, batched inference |
The free CPU tier is enough to publish a text summarizer, a small image classifier or a demo that calls an external API. GPU tiers are billed per hour of active runtime and require a paid Hugging Face plan for personal use. Pick the smallest tier that clears the memory footprint of your model, then measure; if the queue backs up (module 7), upgrade.
The sleep policy
A free Space sleeps after a period of inactivity — a few tens of minutes at the time of writing — to save compute. The first visitor after sleep triggers a cold start that reboots the container and reloads the model, which can take from ten seconds to a full minute depending on the tier and the model size. Subsequent visitors within the active window hit the warm server directly.
For a public demo where a first impression matters — a link on a blog post, a portfolio page — the cold-start hesitation is what most visitors experience. Two mitigations exist. First, upgrade the Space to a tier that does not sleep, which is the honest answer if traffic justifies the cost. Second, keep the Space warm with a scheduled ping from a service like GitHub Actions or a cron job on a small VM, hitting the API endpoint every fifteen minutes. That trick works, and it is fair use — the platform's terms are relaxed about it — but do not abuse it on a free tier if you are not the primary user.
Embedding a Space in your website
A published Space can be embedded in any website with a one-line <iframe>:
<iframe
src="https://your-username-your-space.hf.space"
frameborder="0"
width="100%"
height="720"
></iframe>
The iframe URL is the Space's direct hosting URL, not the huggingface.co browse page. Gradio also provides a JavaScript component, @gradio/client, that lets you call the Space's API from a JS or TS front-end and render the result in your own UI. That is the path when the Gradio interface itself does not match your product's design language.
In summary
- A Space is a git repo with
app.py,requirements.txtand aREADME.mdfrontmatter;git pushdeploys, and the build log is public. - Store API keys in Repository secrets, never in the code; a leaked key in git history survives forever.
- Pick the smallest hardware tier that clears the model's memory footprint, then measure and upgrade; free tiers sleep on idle.
- Embed a Space with an
<iframe>on the.hf.spaceURL, or call its API from your own front-end for a custom UI.
Next module: the full project — a language model demo, streamed, with prefilled examples, a queue, and a Space that ties everything together.