Skip to content

Create Web Architecture

Taiizor edited this page Jun 5, 2026 · 5 revisions

Create: Web Wallpaper Architecture

This page explains, end to end, how a Web wallpaper actually runs inside Sucrose: how the page is served (a local HTTP server, not file://), how live audio and system data flows from the Backgroundog service across an inter-process channel into your page's JavaScript callbacks, how customization properties are pushed on start and on change, and how mouse and keyboard input reaches your page. It is the developer-facing companion to the creator pages — read it to understand the moving parts behind Create Audio API, Create System API, and Create Property Listener Filters.

Contents

The processes involved

A running Web wallpaper spans several separate Windows processes that coordinate over inter-process channels (Sucrose is multi-process by design — see Architecture Overview):

Process Role in a Web wallpaper
Live engine (Sucrose.Live.WebView or Sucrose.Live.CefSharp) Hosts the browser, serves the page, runs JavaScript, receives the data bundle, and calls your callbacks.
Sucrose.Backgroundog Captures audio (WASAPI loopback → FFT) and polls hardware/media-session info, then ships a bundle to the engine.
Sucrose.Commandog Launches the engine process (via its Live command) when you apply a wallpaper. The type → engine mapping itself is resolved upstream by the shared Sucrose.Shared.Live.Helper.Run.Start() launch logic (which reads SucroseInfo.json's Type and looks up the configured engine) before the Live command is dispatched to Commandog.
Sucrose.Launcher / Sucrose.Portal UI and tray; trigger apply/restart and push customization changes.

Only WebView and CefSharp participate in this data channel. The Backgroundog data pump is web-engine-only — MpvPlayer, Aurora, Nebula, Vexana, and Xavier do not receive the audio/system bundle. See Choosing Engines.

Step 1: Engine launch and the local HTTP server

When you apply a Web wallpaper:

  1. Sucrose reads the theme's SucroseInfo.json, sees Type is Web (value 2), and picks the configured engine for that type.
  2. The Live engine starts and, for a Web type, sets its source to your entry file (Source from the manifest, for example Matrix.html).
  3. Local web content is served by an internal HTTP server (LocalHttpServer) on http://localhost:{port}/ and http://127.0.0.1:{port}/, where {port} is a free loopback port chosen automatically at startup. Content is served over HTTP, not file:// — this matters because some browser security restrictions (modules, fetch, WebGL texture loads) behave differently under file://.

GIF, Video, and YouTube types are loaded through generated HTML wrappers (GifContent.html, VideoContent.html, YouTubeContent.html); the Url type points the engine straight at the remote URL.

Step 2: Properties applied on init

On initialization, the engine reads your SucroseProperties.json (or an encoded variant) and applies all current property values by calling your SucrosePropertyListener once per property. This means your wallpaper always starts in the user's last-saved configuration — you do not need to read settings yourself. See Create Property Listener Filters and Create Customization Controls.

When the user later changes a control in the Portal, the engine's FileSystemWatcher detects the updated properties file and re-pushes the changed values to the running page via the same call — live, no restart. The trigger file is cleaned up after ~3 seconds.

Step 3: The live-data pump

Independently of properties, the Backgroundog service runs a periodic timer. On each tick it:

  1. Calls a Get*Info() collector for each category: Bios, Date, Audio, Memory, Battery, Graphic, Network, Storage, Processor, Motherboard.
  2. Builds a single Backgroundog payload object (ten nullable JSON sub-objects) and serializes it to JSON.
  3. Sends it to the engine over the active transport — exactly one of Pipe, Signal, or Transmission (see below). The producer (Backgroundog) is the client; the engine is the server.

Audio specifically comes from WASAPI loopback capture run through an FFT, producing the Data magnitude spectrum (MaxSample = 128 samples) used by visualizers — see Create Audio API. Hardware and media-session info is polled by the same service — see Backgroundog Service.

Step 4: ExecuteScriptAsync into the page

On the engine side, the transport's handler receives the JSON, deserializes it back into the Backgroundog payload, and stores each non-null sub-object as a JSON string in the engine's internal fields (AudioData, ProcessorData, MemoryData, …). Then, for each non-empty hook you declared in SucroseCompatible.json, the engine formats your template with the stored JSON (string.Format(hook, json)) and runs it via ExecuteScriptAsync on the WebView2/CefSharp page. That call invokes your JavaScript function:

// You declared: "SystemAudio": "SucroseAudioData({0});"
// The engine runs: SucroseAudioData({ "Data":[...], "Title":"...", ... });
window.SucroseAudioData = function (obj) { spectrum = obj.Data; };

If a hook string is empty (or you never declared it), the engine does not fire it — so you only pay for the data categories you request.

Step 5: Input forwarding

When the desktop is focused, mouse and keyboard activity is forwarded into the page. The browser engines reference Sucrose's raw-input layer, translating raw input into Win32 messages (and a synthetic scroll script) so that standard web events — mousemove, click, wheel, keydown — fire inside your wallpaper. This is what makes Web wallpapers interactive (for example, the Fluid Simulation Showcase reacts to the cursor). See Type-Web.

The data bundle

The bundle that crosses the channel is the same regardless of transport — ten nullable JSON sub-objects:

Bios, Date, Audio, Memory, Battery, Graphic, Network, Storage, Processor, Motherboard

Each non-null sub-object is re-serialized on the engine side and fanned out to its matching SucroseCompatible.json hook. The Audio sub-object is the audio-reactive channel; the other nine are the System Status API. Field-by-field documentation lives on Create Audio API and Create System API.

Transport selection

The live-data channel can use one of three interchangeable transports, chosen by the CommunicationType setting (default Transmission). They carry the identical JSON payload — only the carrier differs.

Transport Mechanism Channel name
Transmission (default) TCP on the loopback address (127.0.0.1) at a dynamically allocated port (saved to TransmissionPort) created on demand
Pipe Named pipe (System.IO.Pipes) Sucrose.Wallpaper.Engine.Backgroundog.Pipe
Signal JSON file + FileSystemWatcher under %AppData%\Sucrose\Cache\SignalT Backgroundog.sgnl (with GUID-suffixed instances)

The engine picks the transport from CommunicationType and stands up exactly one server; Backgroundog reads the same setting (and the engine-set *Required/TransmissionPort flags) to know which client to use. Full details, including the Launcher tray-control channel, are on the IPC page.

End-to-end sequence

[Sucrose.Backgroundog]                          [Sucrose.Live.WebView | CefSharp]
  periodic timer
    collect Bios/Date/Audio/Memory/Battery/
            Graphic/Network/Storage/
            Processor/Motherboard (JObject)
    build Backgroundog payload -> JSON
    send over CommunicationType transport  ----> server receives JSON
        (Pipe | Signal | Transmission)               deserialize -> Backgroundog payload
                                                      store each non-null field as JSON string
                                                      for each non-empty SucroseCompatible hook:
                                                        string.Format(hook, json)
                                                        ExecuteScriptAsync(js)  ----> page JS
                                                                                       SucroseAudioData(obj)
                                                                                       SucroseProcessorData(obj)
                                                                                       ...
  (separately) properties applied on init and on change -> SucrosePropertyListener(name, val)
  (separately) raw mouse/keyboard -> Win32 messages -> page events
sequenceDiagram
    participant BG as Backgroundog
    participant Eng as Browser engine
    participant Page as Wallpaper page
    Note over Eng: on apply: start local HTTP server, serve theme
    Eng->>Page: SucrosePropertyListener (init values)
    loop each tick
        BG->>BG: collect 10 categories, build payload, to JSON
        BG->>Eng: send over Pipe / Signal / Transmission
        Eng->>Eng: deserialize, store as JSON strings
        Eng->>Page: for each hook, ExecuteScriptAsync
        Note over Page: SucroseAudioData(obj), SucroseProcessorData(obj), ...
    end
    Note over Eng,Page: property change: FileSystemWatcher then SucrosePropertyListener
    Note over Eng,Page: raw mouse/keyboard then Win32 messages then page events
Loading

Why this matters to creators

  • You receive data; you do not poll for it. Implement the Sucrose*Data callbacks and Sucrose calls them on each tick — there is no API to request a reading on demand.
  • Serve-over-HTTP changes behavior vs file://. Relative paths, modules, fetch, and WebGL all run against http://localhost:{port}/, so author your page as if it were on a tiny web server.
  • Declare only the hooks you use. Each enabled hook adds collection and ExecuteScriptAsync work; unused categories are never pushed.
  • Properties arrive on start and on every change. Keep SucrosePropertyListener cheap and idempotent — it is called repeatedly, including for live re-application.
  • Interactivity is automatic on the browser engines when the desktop is focused; build with normal DOM event listeners.
  • Web-engine only. The whole data pump, JS bridge, and input forwarding apply to WebView/CefSharp. If your callbacks never fire, confirm the wallpaper is running on a browser engine. See Choosing Engines.

See also

Home

Getting Started

Wallpaper Types

Using Sucrose

Settings Reference

Creating Wallpapers

Engine Reference

Automation & Command Line

Architecture & Internals

Data, Files & Diagnostics

Building & Contributing

Help & Support

Clone this wiki locally