Gameface is the modern HTML, CSS, and JavaScript UI layer. Reliable modding requires more than loading a web page: resource registration, Python view, Wulf window, Gameface engine, DOM, view model, input surface, and owning lobby or battle context must all agree.
Existing-view injection
Decorate or extend a native Gameface screen without replacing it.
Standalone overlay
Place an independent panel-sized Gameface view over the hangar or battle HUD.
Diagnostics
Trace resource, parent-window, model, DOM, sizing, and lifecycle failures in order.
Choose capabilities from current evidence
Beyond status overlays, Gameface can support settings screens, inventory-like browsers, charts, animated indicators, localized controls and packaged video. Each feature still needs a native owner and matching model/input lifecycle. HTML transforms do not create game-world entities, and a rendered button can request only actions implemented by its Python/native owner.
Start with Frontend Capabilities for DOM/CSS/rendering choices, Media and Rendering for playback and audio, and Transport and Storage for browser services. Gameface support depends on the version embedded in World of Tanks. Check features against your target client; newer vendor documentation may describe APIs it does not support.
Gameface delivery path
The complete stack also includes route/view registration before construction and teardown after the frontend lifetime. Embedded or remote web content adds a separate browser instance, handler collection, authentication/network layer, and navigation lifetime; see Embedded Browser & Native Bridge.
Choose an integration pattern
| Requirement | Recommended pattern | Primary owner |
|---|---|---|
| Add controls, labels, styles, or behavior to an existing Gameface screen | Attach a small injected child view to the native parent, then augment its DOM or read its model. | The native Gameface parent view |
| Show an independent floating panel in the hangar or battle | Create a standalone Gameface ViewImpl in a panel-sized Wulf WindowImpl.
|
The active lobby or battle page |
| Modify a specific legacy Scaleform control | Integrate with that Scaleform control. A separate Gameface panel does not replace its internals. | The Scaleform view or injector |
Runtime layers
A feature is ready only when each layer it depends on is ready. An imported Python class does not prove that its resource accessor resolves; a loaded Wulf window does not prove that Gameface built its DOM; a visible DOM does not prove that the native surface has the correct size.
Diagnose the owning layer
| Symptom | Likely boundary to verify |
|---|---|
| The page or bundle loads, but native calls are absent | Confirm the owning native view/browser and its bridge-handler collection; browser rendering alone proves only frontend delivery |
| A handler name exists, but the command is unavailable | Confirm that this concrete view registered that handler family and that its native owner is still alive |
| A known route no longer opens the expected screen | Recheck current route registration, state-machine ownership, and generated frontend bundle |
| An asynchronous JavaScript result updates a closed screen | Bind the request to view/browser identity and discard it after route change or teardown |
| The DOM renders correctly but integration still fails | Verify model readiness, native surface sizing, input ownership, bridge availability, and Python-side callbacks separately |
| Reopening duplicates state or listeners | Check browser/view generation, observer cleanup, handler finalizers, and owned callback cancellation |
Native models can have several projections
A header, standalone widget, tooltip, and result route may display the same underlying concept through different model shapes and update events. Do not force one fabricated model state into every surface.
See Models & Native Projections for root
ownership, window.model versus window.subViews, placeholder
replacement, native ordering, and host update signals.
Follow state through the frontend
Read Communication and Updates after choosing an integration pattern. It follows initial state and commands through transactions, model callbacks, late child attachment, React reconciliation and staged payload application. Continue with structural control discovery and retained-parent cleanup when augmenting an existing page.