{"course":{"slug":"hugging-face","title":"Hugging Face, End to End","url":"https://addaly.com/learn/hugging-face","level":"intermediate","track":"create"},"lesson":{"slug":"the-space-configuration","title":"The README front matter is the deployment config","url":"https://addaly.com/learn/hugging-face/the-space-configuration","position":32,"of":75,"minutes":8,"answer":"A Space's deployment configuration is YAML front matter in README.md, so it is versioned like code.","keyIdea":"A Space's deployment configuration is YAML front matter in `README.md`, so it is versioned like code, and the two fields that decide whether it still builds in six months are `sdk_version` and pinned dependency versions in `requirements.txt`."},"body":{"format":"markdown","text":"## Where the settings live\n\nA Space's configuration is YAML at the top of `README.md`. Not a dashboard, not a hidden file: the readme:\n\n```yaml\n---\ntitle: Sentiment Three Ways\ncolorFrom: indigo\ncolorTo: blue\nsdk: gradio\nsdk_version: 5.9.1\napp_file: app.py\npinned: false\nlicense: apache-2.0\nshort_description: Three-way sentiment on English text, not calibrated.\n---\n\nEverything below the fence is the readable page.\n```\n\nThere is also an `emoji` field, which takes one character and appears on the gallery card; it is omitted above because nothing depends on it. This is the same pattern as model and dataset cards, and it means the deployment configuration is versioned, diffable and reviewable in a pull request like anything else.\n\n## The fields that actually change behaviour\n\n**`sdk`**: `gradio`, `streamlit`, `docker` or `static`. It decides the whole build.\n\n**`sdk_version`**: the one people leave off, and the one that causes the mystery. Omit it and the Space builds against whatever the platform currently considers default. Gradio 4 to 5 changed component APIs; a Space that worked in March can fail to start in October with no commit in between. Pin it. If a Space suddenly breaks, this is the first thing to check.\n\n**`app_file`**: defaults to `app.py`. Set it if your entry point is elsewhere.\n\n**`python_version`**: pin this too when a dependency is version-sensitive.\n\n**`models`** and **`datasets`**: lists of repository ids your Space uses. They create links on the Hub in both directions, which is how the \"Spaces using this model\" counter from module one gets populated. It is metadata, and it is how other people find your work.\n\n**`hardware`** and **`suggested_hardware`**: the second is a hint to anyone duplicating your Space, so they do not try to run a diffusion model on free CPU and conclude it is broken.\n\n**`pinned`**: pins it to your profile.\n\n## `requirements.txt`, and pinning properly\n\n```\ngradio==5.9.1\ntransformers==4.46.2\ntorch==2.5.1\nsentencepiece==0.2.0\n```\n\nUnpinned dependencies are the second-largest cause of a Space that stops building. Install resolution happens at build time, so a new release of any transitive dependency can break you overnight while your code is untouched.\n\nThree practical notes:\n\n- **`torch` is large.** On free CPU hardware, installing the CPU-only build (`torch --index-url https://download.pytorch.org/whl/cpu`) cuts the image size and the build time substantially, because the default wheel carries CUDA libraries you will never use.\n- **System packages** go in a `packages.txt`, one per line: `ffmpeg`, `poppler-utils`, `tesseract-ocr`. Audio and PDF Spaces fail without this and the error appears at runtime, not at build.\n- **`pre-requirements.txt`** exists for the rare case where something must be installed before the main resolution, such as a specific `pip` version.\n\n## Files that do not belong in the repository\n\nA Space is a git repository, so everything in it is public unless the Space itself is private. Weights, datasets and credentials should live in their own repositories and be fetched at startup, not committed here. Use `.gitignore`, and use the Hub:\n\n```python\nfrom huggingface_hub import snapshot_download\nlocal = snapshot_download(\"your-name/your-private-model\", token=os.environ[\"HF_TOKEN\"])\n```\n\nThat keeps the Space small, the build fast, and the weights versioned where they belong.\n\n## The readme below the fence matters too\n\nIt renders under the app on the Space page. What to put there, in order of how much it helps a visitor:\n\n1. What the thing does, in one sentence, without marketing.\n2. What it will do badly: language coverage, length limits, known failure cases.\n3. Which model it uses, linked, with the revision if you pinned one.\n4. Whether anything a user types is stored. Say \"nothing is stored\" if nothing is, because visitors cannot tell from the outside and will assume the worst or the best, both wrongly.\n5. The licence of your code, which is not automatically the licence of the model inside it.\n\n## Do this now\n\nOpen the readme of any Space you have built or duplicated and add two things: a pinned `sdk_version`, and a sentence saying whether user input is stored. Both take a minute. The first prevents a failure; the second is the difference between a demo and something a stranger can trust."},"check":{"question":"A Space that has not been committed to in eight months suddenly fails to start, with an error inside a Gradio component constructor. What is the most likely cause?","options":[{"text":"No `sdk_version` is pinned, so the Space rebuilt against a newer Gradio whose component API changed.","correct":true},{"text":"The free-tier container was migrated to newer hardware, and the compiled wheels in the cache no longer match the architecture.","correct":false,"tempting":"Invents an architecture mismatch; wheels are resolved at build time for the target platform."},{"text":"The model repository it loads changed on `main`, and the new revision is incompatible with the component types.","correct":false,"tempting":"Unpinned model revisions do cause real failures, but they surface in loading or inference rather than in constructing UI components."},{"text":"Spaces expire their build cache after six months, forcing a rebuild that exceeded the free tier's disk limit.","correct":false,"tempting":"Attributes the failure to a storage policy rather than to the traceback's actual location in the UI library."}]},"prev":{"slug":"duplicate-a-space","title":"Duplicate it, and the app becomes yours to change","url":"https://addaly.com/learn/hugging-face/duplicate-a-space"},"next":{"slug":"hardware-sleep-and-zerogpu","title":"Hardware, sleep, and the bill that runs while you are asleep","url":"https://addaly.com/learn/hugging-face/hardware-sleep-and-zerogpu"},"authorship":"Founder and series editor: Dr Mustafa Mun. Written by AI models to a written standard. Exam keys checked blind by a second model: 3,665 of 3,666 agreed. Academic review invited.","review":{"status":"Draft, open for academic review"},"cite":"Addaly (2026) 'The README front matter is the deployment config', in Hugging Face, End to End. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/hugging-face/the-space-configuration (Accessed: 13 October 2026).","licence":{"name":"CC BY-NC-SA 4.0","url":"https://creativecommons.org/licenses/by-nc-sa/4.0/"},"reader":{"schema":1,"title":"The README front matter is the deployment config","courseTitle":"Hugging Face, End to End","module":{"index":4,"slug":"spaces-and-shipping-something","title":"Spaces: putting something in front of people"},"answer":null,"keyIdea":"A Space’s deployment configuration is YAML front matter in `README.md`, so it is versioned like code, and the two fields that decide whether it still builds in six months are `sdk_version` and pinned dependency versions in `requirements.txt`.","hero":{"kind":"plate","image":null,"alt":null,"caption":null},"blocks":[{"t":"h2","id":"where-the-settings-live","runs":[{"text":"Where the settings live"}]},{"t":"p","runs":[{"text":"A Space’s configuration is YAML at the top of "},{"text":"README.md","code":true},{"text":". Not a dashboard, not a hidden file: the readme:"}]},{"t":"code","lang":"yaml","label":"YAML","text":"---\ntitle: Sentiment Three Ways\ncolorFrom: indigo\ncolorTo: blue\nsdk: gradio\nsdk_version: 5.9.1\napp_file: app.py\npinned: false\nlicense: apache-2.0\nshort_description: Three-way sentiment on English text, not calibrated.\n---\n\nEverything below the fence is the readable page."},{"t":"p","runs":[{"text":"There is also an "},{"text":"emoji","code":true},{"text":" field, which takes one character and appears on the gallery card; it is omitted above because nothing depends on it. This is the same pattern as model and dataset cards, and it means the deployment configuration is versioned, diffable and reviewable in a pull request like anything else."}]},{"t":"h2","id":"the-fields-that-actually-change-behaviour","runs":[{"text":"The fields that actually change behaviour"}]},{"t":"p","runs":[{"text":"sdk","b":true,"code":true},{"text":": "},{"text":"gradio","code":true},{"text":", "},{"text":"streamlit","code":true},{"text":", "},{"text":"docker","code":true},{"text":" or "},{"text":"static","code":true},{"text":". It decides the whole build."}]},{"t":"p","runs":[{"text":"sdk_version","b":true,"code":true},{"text":": the one people leave off, and the one that causes the mystery. Omit it and the Space builds against whatever the platform currently considers default. Gradio 4 to 5 changed component APIs; a Space that worked in March can fail to start in October with no commit in between. Pin it. If a Space suddenly breaks, this is the first thing to check."}]},{"t":"p","runs":[{"text":"app_file","b":true,"code":true},{"text":": defaults to "},{"text":"app.py","code":true},{"text":". Set it if your entry point is elsewhere."}]},{"t":"p","runs":[{"text":"python_version","b":true,"code":true},{"text":": pin this too when a dependency is version-sensitive."}]},{"t":"p","runs":[{"text":"models","b":true,"code":true},{"text":" and "},{"text":"datasets","b":true,"code":true},{"text":": lists of repository ids your Space uses. They create links on the Hub in both directions, which is how the “Spaces using this model” counter from module one gets populated. It is metadata, and it is how other people find your work."}]},{"t":"p","runs":[{"text":"hardware","b":true,"code":true},{"text":" and "},{"text":"suggested_hardware","b":true,"code":true},{"text":": the second is a hint to anyone duplicating your Space, so they do not try to run a diffusion model on free CPU and conclude it is broken."}]},{"t":"p","runs":[{"text":"pinned","b":true,"code":true},{"text":": pins it to your profile."}]},{"t":"h2","id":"requirements-txt-and-pinning-properly","runs":[{"text":"requirements.txt","code":true},{"text":", and pinning properly"}]},{"t":"code","lang":"","label":"Text","text":"gradio==5.9.1\ntransformers==4.46.2\ntorch==2.5.1\nsentencepiece==0.2.0"},{"t":"p","runs":[{"text":"Unpinned dependencies are the second-largest cause of a Space that stops building. Install resolution happens at build time, so a new release of any transitive dependency can break you overnight while your code is untouched."}]},{"t":"p","runs":[{"text":"Three practical notes:"}]},{"t":"ul","items":[[{"text":"torch","b":true,"code":true},{"text":" is large.","b":true},{"text":" On free CPU hardware, installing the CPU-only build ("},{"text":"torch --index-url https://download.pytorch.org/whl/cpu","code":true},{"text":") cuts the image size and the build time substantially, because the default wheel carries CUDA libraries you will never use."}],[{"text":"System packages","b":true},{"text":" go in a "},{"text":"packages.txt","code":true},{"text":", one per line: "},{"text":"ffmpeg","code":true},{"text":", "},{"text":"poppler-utils","code":true},{"text":", "},{"text":"tesseract-ocr","code":true},{"text":". Audio and PDF Spaces fail without this and the error appears at runtime, not at build."}],[{"text":"pre-requirements.txt","b":true,"code":true},{"text":" exists for the rare case where something must be installed before the main resolution, such as a specific "},{"text":"pip","code":true},{"text":" version."}]]},{"t":"h2","id":"files-that-do-not-belong-in-the-repository","runs":[{"text":"Files that do not belong in the repository"}]},{"t":"p","runs":[{"text":"A Space is a git repository, so everything in it is public unless the Space itself is private. Weights, datasets and credentials should live in their own repositories and be fetched at startup, not committed here. Use "},{"text":".gitignore","code":true},{"text":", and use the Hub:"}]},{"t":"code","lang":"python","label":"Python","text":"from huggingface_hub import snapshot_download\nlocal = snapshot_download(\"your-name/your-private-model\", token=os.environ[\"HF_TOKEN\"])"},{"t":"p","runs":[{"text":"That keeps the Space small, the build fast, and the weights versioned where they belong."}]},{"t":"h2","id":"the-readme-below-the-fence-matters-too","runs":[{"text":"The readme below the fence matters too"}]},{"t":"p","runs":[{"text":"It renders under the app on the Space page. What to put there, in order of how much it helps a visitor:"}]},{"t":"ol","start":1,"items":[[{"text":"What the thing does, in one sentence, without marketing."}],[{"text":"What it will do badly: language coverage, length limits, known failure cases."}],[{"text":"Which model it uses, linked, with the revision if you pinned one."}],[{"text":"Whether anything a user types is stored. Say “nothing is stored” if nothing is, because visitors cannot tell from the outside and will assume the worst or the best, both wrongly."}],[{"text":"The licence of your code, which is not automatically the licence of the model inside it."}]]},{"t":"h2","id":"do-this-now","runs":[{"text":"Do this now"}],"role":"try"},{"t":"p","runs":[{"text":"Open the readme of any Space you have built or duplicated and add two things: a pinned "},{"text":"sdk_version","code":true},{"text":", and a sentence saying whether user input is stored. Both take a minute. The first prevents a failure; the second is the difference between a demo and something a stranger can trust."}]}],"check":{"question":[{"text":"A Space that has not been committed to in eight months suddenly fails to start, with an error inside a Gradio component constructor. What is the most likely cause?"}],"options":[{"text":[{"text":"No "},{"text":"sdk_version","code":true},{"text":" is pinned, so the Space rebuilt against a newer Gradio whose component API changed."}],"correct":true,"tempting":null},{"text":[{"text":"The free-tier container was migrated to newer hardware, and the compiled wheels in the cache no longer match the architecture."}],"correct":false,"tempting":[{"text":"Invents an architecture mismatch; wheels are resolved at build time for the target platform."}]},{"text":[{"text":"The model repository it loads changed on "},{"text":"main","code":true},{"text":", and the new revision is incompatible with the component types."}],"correct":false,"tempting":[{"text":"Unpinned model revisions do cause real failures, but they surface in loading or inference rather than in constructing UI components."}]},{"text":[{"text":"Spaces expire their build cache after six months, forcing a rebuild that exceeded the free tier’s disk limit."}],"correct":false,"tempting":[{"text":"Attributes the failure to a storage policy rather than to the traceback’s actual location in the UI library."}]}],"order":[2,0,3,1],"why":null},"prev":{"slug":"duplicate-a-space","title":"Duplicate it, and the app becomes yours to change","minutes":9},"next":{"slug":"hardware-sleep-and-zerogpu","title":"Hardware, sleep, and the bill that runs while you are asleep","minutes":9}}}