stroke-viewer-frontend / docs /specs /24-bug-gradio-webgl-analysis.md
VibecoderMcSwaggins's picture
feat: Gradio Custom Component for NiiVue (#29)
227ab66 unverified
|
raw
history blame
6.49 kB

Bug #24: Gradio + WebGL/NiiVue Root Cause Analysis

Date: 2025-12-10 Status: ALL gr.HTML HACKS FAILED - Custom Component Required Issue: HF Spaces stuck on "Loading..." forever Root Cause: The gr.HTML + js_on_load + async import() pattern blocks Svelte hydration Note: Gradio CAN do WebGL via Custom Components (proven by gradio-litmodel3d) Solution: Build Gradio Custom Component (see spec #28)


CONFIRMED: All gr.HTML Hacks Have Failed

Attempt Date Result
CDN import in js_on_load Dec 9 FAILED - CSP blocks external imports
Vendored + dynamic import() in js_on_load Dec 9 FAILED - Blocks Svelte hydration
head_paths with loader HTML Dec 9 FAILED - Same hydration issue
head= with inline import() Dec 10 FAILED - Confirmed DOA

There is no hack that works. The only path forward is spec #28 (Gradio Custom Component).


Why Are We Using Gradio?

What Gradio provides:

  • Quick ML demo UIs with Python only (no frontend code needed)
  • Built-in components: file upload, sliders, dropdowns, image display
  • Easy deployment to HuggingFace Spaces
  • Handles backend/frontend communication automatically

What Gradio does NOT provide:

  • Native support for NIfTI/DICOM medical imaging (closed as "not planned" - Issue #4511)
  • Native WebGL canvas component (closed as "not planned" - Issue #7649)
  • Clean way to embed custom WebGL libraries like NiiVue

The Root Cause: We're Fighting gr.HTML, Not Gradio

What We're Trying To Do

Embed NiiVue (a WebGL2 library) into gr.HTML using JavaScript.

Why gr.HTML + JavaScript Doesn't Work

  1. gr.HTML strips <script> tags - Security feature
  2. js_on_load with async import() blocks Svelte hydration - PROVEN by A/B test
  3. Our A/B test confirmed: Disabling js_on_load makes the app load perfectly
  4. head= parameter with import() - Same hydration blocking issue

Gradio CAN Do WebGL

Important clarification: Gradio supports WebGL via Custom Components. gradio-litmodel3d proves this.

The issue is specifically the gr.HTML + js_on_load + import() pattern, NOT Gradio itself.

Gradio's Official Stance

From Gradio maintainer Abubakar Abid on Issues #4511 and #7649:

"We are not planning to include this in the core Gradio library." "We've now made it possible for Gradio users to create their own custom components."

The official answer is: Create a Gradio Custom Component.


The Four Options (Ranked by Effort)

Option 1: Keep Hacking gr.HTML (Current Approach)

  • Effort: Low
  • Success probability: 30%
  • What we're trying: head=, demo.load(_js=...), gr.Blocks(js=...)
  • Problem: Fighting Gradio's architecture

Option 2: Create a Gradio Custom Component

Option 3: Static HTML Space (No Gradio)

  • Effort: High (rebuild entire UI)
  • Success probability: 99%
  • What it is: Pure HTML/CSS/JS app on HF Spaces
  • Why it works: WebGL works perfectly (Unity, Three.js examples exist)
  • Downside: Lose Gradio's nice features (file upload UX, etc.)

Option 4: 2D Slice Fallback (Remove NiiVue Entirely)

  • Effort: Low
  • Success probability: 100%
  • What it is: Use Matplotlib 2D slices instead of 3D WebGL viewer
  • Why it works: Already works (Static Report tab)
  • Downside: No interactive 3D visualization

Comparison: Custom Component vs Static HTML

Aspect Custom Component Static HTML
Keep Gradio features Yes No
File upload UX Built-in Must build
Sliders/dropdowns Built-in Must build
HF Spaces deployment Works Works
Development time 2-3 days 3-5 days
Maintainability Better (Gradio handles updates) Worse (all custom)

Recommendation

If current PR #28 fails:

  1. First try: demo.load(_js=...) approach (1 hour)
  2. If that fails: Create a Gradio Custom Component for NiiVue (2-3 days)
  3. Nuclear option: Static HTML Space or remove 3D viewer entirely

The Custom Component approach is the "correct" solution - it's what Gradio maintainers recommend for WebGL content. We've been trying to hack around Gradio instead of working with it.


Existing Work We Can Reference

  1. gradio-litmodel3d - WebGL Model3D with HDR support
  2. Unet-nifti-gradio - NIfTI + Gradio integration
  3. papaya-image-viewer-gradio - Medical imaging viewer mentioned in Issue #4511
  4. NiiVue docs - Official NiiVue integration guide

Answer: "What Does Gradio Unblock?"

Gradio unblocks:

  • UI/UX components (dropdowns, sliders, file upload, etc.)
  • Backend/frontend communication
  • Easy HF Spaces deployment
  • Python-only development (no JS required for basic apps)

Gradio does NOT unblock:

  • Custom WebGL content (you need a Custom Component)
  • Medical imaging formats (NIfTI, DICOM)
  • Advanced JavaScript integrations

If we go Static HTML: Yes, we'd have to write all the HTML/CSS/JS ourselves, including file upload handling, UI layout, etc. That's what Gradio provides "for free."


Sources