Factory.ai

Open-Source Wikis

/

Stable Diffusion WebUI

/

Systems

/

UI

AUTOMATIC1111/stable-diffusion-webui

UI

Active contributors: AUTOMATIC1111, w-e-w, missionfloyd, light-and-ray

Purpose

Builds the Gradio Blocks web interface — the txt2img / img2img / Extras / Train / Settings / Extensions tabs — and wires every component to the right server-side handler. This subsystem is the largest in the repo: roughly 6,000 lines across modules/ui*.py.

Directory layout

modules/
├── ui.py                              # top-level create_ui() — assembles every tab
├── ui_common.py                       # generation gallery, save buttons, infotext fields
├── ui_components.py                   # FormRow, FormColumn, InputAccordion, ToolButton
├── ui_toprow.py                       # the prompt + Generate area shared by tabs
├── ui_extra_networks.py               # the Lora/embedding/hypernet browser
├── ui_extra_networks_*.py             # per-type browser pages
├── ui_extensions.py                   # the Extensions tab (install/update/restart)
├── ui_settings.py                     # the Settings tab (per-section forms)
├── ui_loadsave.py                     # ui-config.json read/write
├── ui_postprocessing.py               # the Extras tab
├── ui_prompt_styles.py                # prompt styles dropdown
├── ui_checkpoint_merger.py            # the Checkpoint Merger tab
├── ui_gradio_extensions.py            # script_path / mtime-based static asset injection
├── ui_tempdir.py                      # cleanup of /tmp Gradio uploads
└── infotext_utils.py                  # round-tripping generation params <-> components
javascript/                            # browser-side helpers loaded by ui_gradio_extensions
style.css                              # all UI styling

Key abstractions

Type File Description
create_ui() modules/ui.py Top-level builder; returns the gr.Blocks instance assigned to shared.demo.
Toprow modules/ui_toprow.py The shared prompt textarea + Generate / Skip / Interrupt buttons.
FormRow, FormColumn, FormGroup, InputAccordion, ToolButton, DropdownMulti, DropdownEditable modules/ui_components.py Custom Gradio elements; InputAccordion lets the open/closed state be a parameter.
create_output_panel() modules/ui_common.py Builds the gallery + Save / Send to img2img / Open folder cluster used by every tab.
UiSettings modules/ui_settings.py Iterates shared.opts.data_labels to render the Settings tab; one section per category.
ExtraNetworksPage and subclasses modules/ui_extra_networks.py Renders the per-type model browser cards.
UiLoadsave modules/ui_loadsave.py Persists slider/dropdown defaults to ui-config.json.
connect_paste() and paste_fields modules/infotext_utils.py The "Read generation parameters" and PNG-info round-trip plumbing.

How it works

create_ui() is the single place that builds the Gradio Blocks tree. It's a long, mostly imperative function:

graph TD
    A[create_ui] --> B[script_callbacks.before_ui_callback]
    A --> C[ui_extra_networks.initialize]
    A --> D[ScriptRunner.initialize_scripts<br/>per tab]
    A --> E[Toprow + paste_fields per tab]
    A --> F[script_runners[tab].setup_ui<br/>builds custom-script UI]
    A --> G[connect Generate / Skip / Interrupt]
    A --> H[settings_interface.create_ui<br/>build Settings tab]
    A --> I[ui_extensions.create_ui<br/>Extensions tab]
    A --> J[script_callbacks.ui_tabs_callback<br/>extension-supplied tabs]
    A --> K[gr.Blocks(shared.demo)]

Each "tab build" follows a recipe:

  1. Create a Toprow for the prompt area.
  2. Build the parameters column (sampler, steps, CFG, seed, dimensions, batch).
  3. Hand control to the tab's ScriptRunner.setup_ui() — this is where alwayson scripts and the Script dropdown render their controls.
  4. Build the output gallery via create_output_panel.
  5. Wire the Generate button to a handler in modules/txt2img.py or modules/img2img.py, wrapped with wrap_gradio_gpu_call() from modules/call_queue.py.
  6. Register paste_fields so the "Read generation parameters" flow can fill the controls back in.

The Settings tab is the only "data-driven" section: it iterates shared.opts.data_labels and creates a Gradio component per option. Because new settings can be registered by extensions through script_callbacks.on_ui_settings, the Settings tab is rebuilt every time create_ui() is called.

Extra networks UI

modules/ui_extra_networks.py registers a FastAPI route per type (/sd_extra_networks/thumb, /sd_extra_networks/page, /sd_extra_networks/cards) so that the JavaScript browser (javascript/extraNetworks.js) can lazy-load thumbnails. The Python side is responsible for:

  • Listing model files for each type (Lora, hypernet, embedding, checkpoint).
  • Reading per-card metadata from <filename>.json and <filename>.preview.png.
  • Generating the HTML for each card.

Extensions add new browser tabs by subclassing ExtraNetworksPage and registering it in ui_extra_networks.register_page().

Settings page

The Settings tab works through data_labels — a dict of {key: OptionInfo} populated at boot in modules/shared_options.py. Each OptionInfo carries metadata (label, component class, default value, validation, refresh function) that UiSettings uses to render the right Gradio control. Extensions add their settings via the on_ui_settings callback. The "Show all pages" toggle just expands collapsed sections.

The "Apply settings" button POSTs to /sdapi/v1/options, which delegates to modules/api/api.py set_config(). Some setting changes trigger onchange callbacks declared in OptionInfo.onchange; for example, sd_model_checkpoint triggers a model reload.

JavaScript bridge

script.js is loaded once and provides gradioApp(), the helper that unwraps Gradio's shadow DOM. Every file in javascript/ is then auto-loaded by ui_gradio_extensions.javascript_html(). Modules can request a server function be invoked from JavaScript with the _js="myFn" parameter on a Gradio event:

button.click(
    fn=actual_handler,
    inputs=[a, b],
    outputs=[c],
    _js="myJsFunction",  # called first; can transform inputs or open dialogs
)

Most "open folder", "context menu", "drag and drop image to UI", "live preview" features are implemented this way.

Integration points

  • Settings registrationscript_callbacks.on_ui_settings. See script-callbacks.md.
  • Custom tabsscript_callbacks.on_ui_tabs; return a list of (component, label, elem_id) tuples.
  • Custom train tabsscript_callbacks.on_ui_train_tabs.
  • Adding/replacing componentsscript_callbacks.on_after_component (most common). Inspect kwargs["elem_id"] and react.
  • Localisation — the JSON file dropped into localizations/ (or shipped by an extension) is consumed by javascript/localization.js.
  • Themesshared_gradio_themes.py exposes the theme dropdown; users can also set --gradio-theme and --gradio-theme-cache.

Entry points for modification

To add a new tab, register it via on_ui_tabs:

def on_ui_tabs():
    with gr.Blocks() as ui:
        gr.HTML("<h2>Hello</h2>")
    return [(ui, "My tab", "my_tab")]
script_callbacks.on_ui_tabs(on_ui_tabs)

To change something in an existing tab, prefer on_after_component(elem_id="...") over editing ui.py directly. To restyle, edit style.css; selectors are based on the elem_id and elem_classes attributes set in ui.py.

For a holistic refactor of ui.py, the natural slice points are the per-tab with gr.Tab(...) blocks; each tab's setup is roughly self-contained. See scripts-and-extensions.md for how ScriptRunner plugs into the build.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

UI – Stable Diffusion WebUI wiki | Factory