# spec: hugging face spaces + gradio deployment > **Version**: December 2025 > **Status**: APPROVED - Ready for Implementation > **Last Updated**: 2025-12-05 > **Verified**: Cold start claims, pause/restart behavior, ZeroGPU limitations ## important: gradio 6 is now available As of December 2025, **Gradio 6.0.2** is the latest stable release. Our `pyproject.toml` currently specifies `gradio>=5.0.0`, which will install Gradio 6.x. **Key breaking changes affecting our codebase:** | Change | Impact | Our Code | |--------|--------|----------| | `theme`, `css`, `js` moved from `Blocks()` to `launch()` | HIGH | `app.py:111` uses `gr.Blocks()`, `app.py:170` passes theme to `launch()` - **OK** | | `gr.HTML` padding default `True` → `False` | LOW | No visual impact expected | | Chatbot tuple format removed | NONE | We don't use Chatbot | | `show_api` → `footer_links` | LOW | We don't customize this | **Recommendation**: Pin to `gradio>=6.0.0,<7.0.0` for stability, or test with latest and update as needed. **Migration guide**: [Gradio 6 Migration Guide](https://www.gradio.app/main/guides/gradio-6-migration-guide) --- ## purpose This spec documents the requirements, constraints, and best practices for deploying the `stroke-deepisles-demo` Gradio application to Hugging Face Spaces. It identifies potential friction points between our current implementation and HF Spaces constraints, providing concrete guidance before deployment. ## executive summary ### critical friction points identified | Issue | Severity | Current State | Fix Required | |-------|----------|---------------|--------------| | **NVIDIA GPU required** | HIGH | DeepISLES needs CUDA | Use Docker SDK + GPU on HF Spaces | | **JavaScript in `gr.HTML`** | HIGH | ` """ ``` #### the problem From the [Gradio documentation](https://www.gradio.app/guides/custom-CSS-and-JS) and [HF Forums](https://discuss.huggingface.co/t/gradio-html-component-with-javascript-code-dont-work/37316): > "The `gr.HTML` component doesn't support loading scripts via traditional ` """ ``` **Note**: Even this may not work reliably. Testing on HF Spaces is required. #### alternative: gradio custom components (`gradio cc`) For production deployments, Gradio 6 supports first-class **Custom Components** via the `gradio cc` CLI. This is the recommended "production" solution (vs. the `js=` hack for MVP). ```bash # Create a NiiVue custom component gradio cc create NiiVueViewer --template HTML # Development server with hot reload gradio cc dev # Build for distribution gradio cc build # Publish to PyPI and HF Spaces gradio cc publish ``` **Pros**: - First-class support, proper state management - No hacky string interpolation - Reusable across projects **Cons**: - Requires Node.js build step - Higher complexity than `js=` parameter - Overkill for MVP **Source**: [Custom Components In Five Minutes](https://www.gradio.app/guides/custom-components-in-five-minutes) #### alternative: `gradio-iframe` component The [`gradio-iframe`](https://pypi.org/project/gradio-iframe/) package (v0.0.10) provides an iframe component that may execute JavaScript more reliably: ```python from gradio_iframe import iFrame viewer = iFrame( value="...NiiVue code...", label="NiiVue Viewer" ) ``` **Warning**: This is experimental and "not fully tested" per the maintainer. Use with caution. ### css restrictions Custom CSS should use `elem_id` and `elem_classes` rather than query selectors: > "The use of query selectors in custom JS and CSS is not guaranteed to work across Gradio versions as the Gradio HTML DOM may change." **Source**: [Custom CSS and JS Guide](https://www.gradio.app/guides/custom-CSS-and-JS) ### security (gradio 5 audit, inherited by v6) The Trail of Bits security audit was performed on **Gradio 5.0**. All fixes are inherited by Gradio 6.x: - **CVE-2024-47872**: XSS via HTML/JS/SVG file uploads (fixed in 5.0.0) - File type restrictions enforced server-side - Our app uses `gradio>=6.0.0` - we're covered > **Note**: There was no separate Gradio 6 audit. The security improvements from Gradio 5 persist in v6. **Source**: [A Security Review of Gradio 5](https://huggingface.co/blog/gradio-5-security) --- ## readme.md yaml configuration ### required fields for gradio spaces ```yaml --- title: Stroke DeepISLES Demo emoji: 🧠 colorFrom: blue colorTo: purple sdk: gradio sdk_version: "6.0.2" # Latest stable as of Dec 2025 python_version: "3.11" app_file: app.py pinned: false license: mit short_description: "Ischemic stroke lesion segmentation using DeepISLES" # Optional but recommended models: - isleschallenge/deepisles # If we reference it datasets: - YongchengYAO/ISLES24-MR-Lite tags: - medical-imaging - stroke - segmentation - neuroimaging - niivue # For CPU-only demo mode suggested_hardware: cpu-basic # If we need cross-origin isolation (e.g., SharedArrayBuffer) # custom_headers: # cross-origin-embedder-policy: require-corp # cross-origin-opener-policy: same-origin --- ``` ### configuration reference | Field | Type | Description | |-------|------|-------------| | `sdk` | string | `gradio`, `docker`, or `static` | | `sdk_version` | string | Gradio version (e.g., "5.0.0") | | `python_version` | string | Python version (e.g., "3.11") | | `app_file` | string | Entry point (default: `app.py`) | | `suggested_hardware` | string | Hardware for duplicators | | `disable_embedding` | bool | Prevent iframe embedding | | `custom_headers` | dict | COEP/COOP/CORP headers | **Source**: [Spaces Configuration Reference](https://huggingface.co/docs/hub/en/spaces-config-reference) --- ## dependencies ### requirements.txt for hf spaces HF Spaces uses `requirements.txt`, not `pyproject.toml` for dependency installation. ```text # requirements.txt for HF Spaces # Core - Tobias's fork with BIDS + NIfTI lazy loading git+https://github.com/CloseChoice/datasets.git@feat/bids-loader-streaming-upload-fix # HuggingFace huggingface-hub>=0.25.0 # NIfTI handling nibabel>=5.2.0 numpy>=1.26.0 # Configuration pydantic>=2.5.0 pydantic-settings>=2.1.0 # UI - Gradio 6.x (latest stable as of Dec 2025) gradio>=6.0.0,<7.0.0 matplotlib>=3.8.0 # Networking requests>=2.0.0 ``` ### potential issues 1. **Git dependencies**: HF Spaces supports `git+https://...` in requirements.txt 2. **C extensions**: nibabel/numpy compile fine on HF Spaces 3. **Size**: No bloated dependencies (no PyTorch required for demo mode) --- ## deployment paths ### hardware requirements | Component | Requirement | Notes | |-----------|-------------|-------| | GPU | NVIDIA with CUDA 11.3+ | **Mandatory** - no CPU/MPS fallback | | VRAM | 4GB minimum, 12GB+ recommended | For parallel processing | | Docker | Docker + nvidia-container-toolkit | Required for DeepISLES | | Python | 3.8+ (3.11 recommended) | Per project config | > ⚠️ **Apple Silicon (M1/M2/M3) is NOT supported.** DeepISLES requires NVIDIA CUDA. ### path 1: local nvidia gpu (primary development) For day-to-day development and testing on your own NVIDIA GPU machine. ```bash # 1. Ensure Docker + nvidia-container-toolkit installed docker run --rm --gpus all nvidia/cuda:11.3-base nvidia-smi # 2. Pull DeepISLES image docker pull isleschallenge/deepisles # 3. Run the app uv run python -m stroke_deepisles_demo.ui.app ``` **Pros**: - Free (you own the hardware) - Fast iteration - No network dependency **Cons**: - Requires NVIDIA GPU hardware ### path 2: hf spaces docker sdk + gpu (on-demand demos) For showcasing to others. Spin up when needed, pause when done. #### dockerfile for hf spaces ```dockerfile # Dockerfile for HF Spaces FROM isleschallenge/deepisles:latest # Add our application COPY requirements.txt /app/ RUN pip install -r /app/requirements.txt COPY src/ /app/src/ COPY app.py /app/ WORKDIR /app EXPOSE 7860 CMD ["python", "-m", "stroke_deepisles_demo.ui.app"] ``` #### readme.md configuration ```yaml --- title: Stroke DeepISLES Demo emoji: 🧠 colorFrom: blue colorTo: purple sdk: docker app_port: 7860 suggested_hardware: t4-small pinned: false license: mit --- ``` #### cost management: pause/restart api ```python from huggingface_hub import HfApi api = HfApi() SPACE_ID = "your-username/stroke-deepisles-demo" # PAUSE - stops billing immediately api.pause_space(SPACE_ID) # RESTART - spin up for demo api.restart_space(SPACE_ID) # AUTO-SLEEP after 30 min inactivity api.set_space_sleep_time(SPACE_ID, sleep_time=1800) ``` #### billing breakdown | State | Billed? | How to Enter | |-------|---------|--------------| | Running | ✅ $0.40/hr (T4) | `restart_space()` or visitor wakes it | | Sleeping | ❌ $0 | Auto after `sleep_time` inactivity | | Paused | ❌ $0 | `pause_space()` - only owner can restart | **Typical demo session**: 30-60 minutes = **$0.20-$0.40** **Monthly cost if paused**: **$0.00** --- ## niivue integration analysis ### current implementation Our viewer uses NiiVue loaded from unpkg CDN with base64 data URLs: ```python # viewer.py:289-324 return f"""
""" ``` ### potential issues 1. **Script execution**: `