QAEM/DEV

Build your own EdgeOS widget

Make a custom widget for EdgeOS from a widget.json and an index.html: options, live system and media data, text size, and how iCUE widgets run inside EdgeOS.

Updated 24 Sept 2026

An EdgeOS widget is a small web page. You write plain HTML, CSS and JavaScript, describe the widget in a widget.json, and EdgeOS puts it on the XENEON EDGE next to the built-in widgets, with the same options panel, looks and text sizes. Your own widgets are free to build and import.

What a widget is

A folder, or a zip of one, with two files:

my-widget/
├── widget.json     name, size, options
└── index.html      the widget, plain HTML/CSS/JS

Add any other files the page needs (scripts, styles, images) next to them. Relative paths to them work.

Import it

Add the widget

Either open the Widgets page in EdgeOS and choose Import widget…, or drop the folder into %LOCALAPPDATA%\EdgeOS\widgets\.

Place it

The widget appears under Imported on the Widgets page and in the layout picker. Add it to any profile and it shows in Desktop Mode, in the iCUE widget and in the app's preview.

widget.json

{
  "id": "hello-widget",            // folder name after import; letters, digits, - _ .
  "name": "Hello Widget",
  "description": "One line for the catalogue card.",
  "author": "You",
  "version": "1.0.0",
  "entry": "index.html",           // optional, default index.html
  "w": 3, "h": 1,                  // default size in grid units (desktop grid is 12 × 4)
  "options": [                     // optional; shown on the Widgets page and per placement
    { "key": "greeting", "label": "Greeting", "type": "text",   "default": "Hello, Edge" },
    { "key": "showCpu",  "label": "Show CPU", "type": "switch", "default": true },
    { "key": "unit",     "label": "Unit",     "type": "seg",    "default": "c", "values": [["c", "°C"], ["f", "°F"]] }
  ]
}
  • id becomes the folder name after import, and it's what keeps your widget's storage across updates. Use letters, digits, -, _ and ..
  • w and h are the default size in grid units. The desktop grid is 12 × 4.
  • options show on the Widgets page and on each placement. text is a text box, switch an on/off toggle and seg a segmented choice from values, each a [value, label] pair.

index.html

EdgeOS loads your page in a sandboxed iframe that fills the tile, with allow-scripts allow-same-origin allow-forms allow-popups.

Each widget is served from an origin of its own:

http://w-<hash>.localhost:57140/custom/<id>/

The hash comes from the widget's id, so it stays the same when you update the widget and your localStorage is kept.

What your page receives

WhenHowPayload
On loadQuery string?mode=desktop or ?mode=widget, plus &options= and the options as JSON
On load, and when options changepostMessage{ type: "edgeos-options", options, mode }
Every second while visiblepostMessage{ type: "edgeos-state", state }

state is the same object the built-in widgets use:

{
  "edge":   { "found": true, "mode": "desktop", "bounds": { "x": 1920, "y": 0, "w": 2560, "h": 720 }, "icue": true },
  "system": { "cpu": 12, "gpu": 4, "gpuAvailable": true, "ramUsed": 11.2, "ramTotal": 31.1, "ramPct": 36 },
  "media":  { "title": "…", "artist": "…", "album": "…", "status": "playing|paused|stopped|none", "position": 42, "duration": 213, "thumbKey": "…" }
}

A minimal listener:

window.addEventListener("message", e => {
  const m = e.data || {};
  if (m.type === "edgeos-options") applyOptions(m.options);
  if (m.type === "edgeos-state") draw(m.state);
});

Design notes

Background

Make the body background transparent so the dashboard's tile colour and corner radius show through, or paint your own.

Text size

EdgeOS sets the font-size of your page's <html> element to the user's text size (Appearance → Text size × the widget's own Text size under Widgets → Customize) and mirrors it as --scale on the same element. Size your text in em or rem and it follows both sliders. Fixed px sizes ignore them.

Touch

The Edge is a touchscreen. Keep tap targets 44 px or larger, avoid controls that only appear on hover, and don't expect a keyboard.

Sizes

The same widget can be 1 × 1 in Widget Mode and 4 × 2 on the desktop. Use container-relative units (cqmin, percentages) rather than fixed pixels.

Network and the OS

Network access is up to your page: EdgeOS doesn't proxy requests. Anything that needs the operating system, such as launching apps or reading files, belongs in a helper process, the way Launchify and Deckord do it.

iCUE widgets in EdgeOS

Any .icuewidget imports the same way. EdgeOS unpacks it and serves its index.html with a script at the top of <head> that provides what iCUE itself does:

  • window.iCUE = { isPreview: false };
  • one global let per x-icue-property meta tag, holding the value set in EdgeOS, or its data-default;
  • let icueEvents. icueEvents.onICUEInitialized() runs once the page has loaded and icueEvents.onDataUpdated() whenever a value changes. Changes apply live: changing a setting in EdgeOS never reloads the widget.

Every property shows in Customize → Options, in the widget's own x-icue-groups panels, with slider units from data-unit-label.

  • Screen colours. The four names iCUE reserves for the screen's colours (accentColor, backgroundColor, textColor and transparency) are set under Appearance instead, as the tile's look: its accent, text colour and background. A tile with a background of its own makes the widget see-through over it (transparency 90).
  • Text size. Appearance → Text size, times the global Text size, multiplies the widget's own textScale slider, or one named …TextScale. A widget without one is zoomed.
  • Following colours. A widget with a followIcueColors switch has it turned on while the tile sets a colour.
  • Links. The link provider (widgetbuilder.linkprovider) is shimmed: window.plugins.Linkprovider.open(url) has EdgeOS open an http(s) link in the default browser. Other required_plugins don't have a shim yet, and the widget will report that feature as missing.

The widget catalogue

EdgeOS can install widgets from a catalogue that QAEM publishes as a JSON file:

{
  "widgets": [
    { "id": "hello-widget", "name": "Hello Widget", "description": "…", "author": "QaemDev", "version": "1.0.0",
      "kind": "custom",                       // or "icue"
      "download": "https://…/hello-widget.zip",
      "homepage": "https://…" }
  ]
}

Installing downloads the zip over https and imports it. Installing from the catalogue is an EdgeOS Pro feature; importing your own files is free. The catalogue page is on its way, so for now the Widgets page has only Import widget….