Gradio 6 quietly added a feature that changes the rules of prototyping: gr.HTML now supports custom templates, scoped CSS and interactive JavaScript. What does that mean? You can build almost any web component and ask an LLM (like Claude or another front model) to generate everything in a single Python file: frontend, backend and state handling ready to run.
What gr.HTML does and why it matters
If you've ever been stuck between writing a React component and hooking it to your model, this is for you. gr.HTML lets you embed html_template, css_template and js_on_load inside a Gradio component. In other words: all UI code lives in a single class or instance that serializes with Python state.
html_templatedefines the HTML structure.css_templatecontains styles, with scope to avoid global leaks.js_on_loadhooks native interactivity and can updateprops.value.
Communication is simple: props.value injects state from Python to JS, and when JS changes props.value and calls trigger('change'), the state travels back to Python. That's the whole API to sync frontend and backend.
In practice: you describe what you want, the LLM generates a single
app.py, you run it, you improve it and repeat. Each iteration takes seconds with Gradio's reload mode.
Real examples that prove the power
They tested full apps, each in a single Python file and without build steps. A few ideas that show the range:
-
Pomodoro with pixel-art tree: the tree animation is just
@keyframesincss_templateand state changes injs_on_load. No extra React components. -
GitHub-style contribution heatmap: clickable cells that change state, color themes and pattern generators. Live stats that update as you edit.
-
Kanban: drag and drop between columns, inline edit with double click and search that filters in real time. All with native HTML5 events and sync to Python.
-
Spin-to-Win: smooth CSS animation and persistence of state across rerenders. Great for random decisions or team selection.
-
Detection Viewer: specialized viewer for detection, segmentation and pose estimation results. Renders bounding boxes, masks, keypoints and connections, and plugs straight into your model pipeline.
The community also showed creative components:
-
3D control with Three.js inside Gradio: a full viewport where uploaded images interact with camera parameters that feed an image-editing model.
-
Real-time transcription: an interface showing WPM, animated badges and active transcription with Voxtral, without standing up a separate frontend.
How to build a reusable component
The API is minimalist. Here's a direct usage example:
import gradio as gr
comp = gr.HTML(
value={"count": 0},
html_template='<button>Clicked ${value.count} times</button>',
css_template='button { background: #667eea; color: white; }',
js_on_load='''
element.querySelector('button').onclick = () => {
props.value = { count: props.value.count + 1 };
trigger('change');
};
'''
)
And if you want to reuse this component, subclass it so it behaves like any gr.Image() or gr.Slider():
class Heatmap(gr.HTML):
def __init__(self, value=None, theme="green", **kwargs):
super().__init__(
value=value,
theme=theme,
html_template=TEMPLATE,
css_template=STYLES,
js_on_load=SCRIPT,
**kwargs
)
# Now Heatmap() is used in Blocks, receives events and keeps state.
Practical considerations and security
-
One-shot flow: asking an LLM to generate a single Python file with all the HTML/CSS/JS is ideal. You avoid instructions like "create the stylesheet file" or "set up the build".
-
Debug fast: use
demo.launch(share=True)orgradio deployto get onto Spaces in seconds. The describe → generate → run → tweak loop is very short. -
Performance: for prototypes and ML interfaces this is great. If your UI grows a lot in complexity or traffic, consider splitting frontend and backend for maintenance and performance reasons.
-
Security: the component accepts JavaScript. In public environments review XSS risks or execution of unwanted code. For demos and quick prototypes it works perfectly; in production validate and limit what runs.
Why this changes the experience with LLMs and ML
Because now an LLM can return not just a snippet, but a complete app that accepts inputs, shows complex outputs and maintains state. That reduces friction for researchers, product managers and developers: less setup, more iteration.
If you have a specific output format for your model, you build a gr.HTML that renders it exactly how you want and use it like a native component. Combining that with frontier models to generate code makes prototyping a full idea a matter of minutes.
Give yourself a couple of hours to experiment with a prototype: describe the UI to your LLM, ask for the app.py file and run it. You'll see the difference between building and actually shipping a demo.
Original source
https://huggingface.co/blog/gradio-html-one-shot-apps
Summary: Gradio 6 expands gr.HTML with HTML templates, scoped CSS and interactive JS, letting you create full web apps in a single Python file. This makes one-shot prototypes generated by LLMs easier, from timers and Kanban boards to detection viewers and 3D controls, all deployable on Hugging Face Spaces.
