Loading Screen
Every WebComPy page shows a loading screen while the PyScript/Pyodide runtime downloads and initializes in the browser. The framework default is tuned for perceived performance: pre-rendered content stays readable, a slim top bar shows staged progress, and the page visually "wakes up" when the app is ready. Everything is configurable through WebComPyAppConfig.loading.
Configuration
from webcompy.app import WebComPyApp, WebComPyAppConfig
app = WebComPyApp(
root_component=AppRoot,
config=WebComPyAppConfig(
loading={
"mode": "auto", # auto | overlay | content
"interaction": "block", # block | inert | passthrough (content mode)
"stages": True, # show staged status labels
"dormant": True, # muted content + wake-up transition
"messages": {
"runtime_download": "Loading Python runtime…",
},
"template": None, # preset name, HTML string, or file path
"reveal_delay_ms": 350, # grace period before any chrome appears
"fade_out_ms": 250, # fade-out duration on boot completion
"timeout_seconds": 30, # stall watchdog (0 disables)
}
),
)
All keys are optional. Unknown keys, invalid values, and unknown messages stage keys are rejected at config construction time.
Modes
auto(default) —contentwhen the page ships pre-rendered content (dev server and SSG always do),overlayotherwise.content— the page stays fully readable; a slim top progress bar and a small bottom-left status label communicate boot progress. A click-blocker prevents interaction until the app is live.overlay— a centered spinner on a translucent backdrop (used when there is no pre-rendered content).
Interaction policies (content mode)
block(default) — a transparent full-screen element intercepts clicks during boot; scrolling and reading stay possible.inert— the mount element carries theinertattribute, additionally blocking keyboard focus and selection.passthrough— nothing is intercepted; links navigate natively (MPA fallback). The dormant treatment is what honestly signals "not interactive yet".
Staged progress
stages: true shows the current boot phase: Preparing Python runtime… → Downloading Python runtime… → Installing packages… → Runtime ready… → Starting app…. Labels are driven by PyScript's py:progress events and can be localized via messages (stage keys are fixed; see the loading-screen spec). With stages: false, the status label is omitted and the progress bar becomes a pure trickle without stage jumps.
Stall watchdog
If no boot progress event arrives within timeout_seconds, a "Taking longer than usual…" message with a reload button appears. Set 0 to disable. The timer resets on every progress event and when the runtime signals ready (py:ready), so it only trips while boot is genuinely stalled.
Custom templates and the toolkit contract
template accepts a preset name ("overlay", "bar", "splash"), an inline HTML string, or a path to an HTML file resolved relative to the app package directory. A custom template must contain exactly one element with id="webcompy-loading" — generation fails with a clear error otherwise. Validation is a lightweight markup scan, so a template that merely mentions the contract ID inside a comment or script may fail the check.
The framework drives documented hooks inside the loading element when present; missing hooks are no-ops:
| Hook | Driven by |
|---|---|
[data-wc-status] |
current stage label |
[data-wc-substatus] |
package-install detail lines (visual only, aria-hidden) |
[data-wc-bar] |
--wc-progress custom property as a unitless 0–1 fraction (e.g. transform: scaleX(var(--wc-progress))) |
[data-wc-timeout] |
revealed by the stall watchdog (the controller keeps it hidden until the watchdog trips, so an initial hidden attribute is optional) |
[data-wc-reload] |
click reloads the page |
Mechanic attributes you may set on the loading element:
| Attribute | Effect |
|---|---|
data-wc-fade |
fade-out duration in ms (defaults to fade_out_ms) |
data-wc-mode |
content / overlay (affects framework CSS) |
When a custom template does not set these attributes itself, generation injects the resolved values automatically — role="status" (when the template does not set a role), data-wc-mode, data-wc-interaction (content mode), and data-wc-fade, plus --wc-delay/--wc-fade style variables. Template-authored values always win. If the loading element already sets its own style attribute, the --wc-delay/--wc-fade variables are not injected and the authored style is preserved unchanged; set data-wc-fade in that case so the fade duration stays configuration-driven.
The framework's base stylesheet is always emitted before the loading element, so a custom template can override any rule with its own <style>. Colors follow the app theme (theme tokens reflecting data-theme, the theme signal, or prefers-color-scheme) and are overridable via CSS custom properties: --wc-accent, --wc-backdrop, --wc-ring, --wc-fg, --wc-dormant-opacity, --wc-dormant-saturation.
The loading controller is an inline classic script — sites with a strict Content-Security-Policy must allow its inline script (or use script-src hashing).
Accessibility
The loading element carries role="status"; stage transitions are announced politely. Under prefers-reduced-motion, rotation, trickle, fade, and the wake-up transition are disabled while the grace period is preserved.