Lux widgets

concept australia Updated Sep 29, 2026 2 min read widgets.md
Raw file servicenow.com

A widget in Lux is a custom UI unit authored for a specific application. The platform ships no widgets; every widget on an instance was authored for an app.

This topic covers what a widget is, how it gets registered, and how the runtime resolves one by tag name. To learn how to build a Lux widget, see https://raw.githubusercontent.com/ServiceNow/ServiceNowDocs/australia/markdown/australia/application-development/build-a-widget-from-scratch.md.

Everything you render in a Lux app is a Lit widget. A Lux widget is a Lit custom element, registered as a sys_aix_widget record, extending one of two platform base classes. Both give it Tailwind/DaisyUI styling, and server-side rendering (SSR) safety; the difference is discoverability and how it gets its data.

Project shape

CSS
my-widget/                ├── aiux.json              # { "basename": "my-widget", "scope": "x_demo_widget", "scopeId": "…" }                ├── now.config.json                ├── package.json                └── widgets/                ├── _shared/           # NOT a widget (no index.js): discovery skips it                │   └── chart.js                ├── weather/                │   └── index.js       # <x-demo-weather>                └── air-quality/                └── index.js       # <x-demo-air-quality>

Discovery convention: each sub directory of widgets/ that contains an index.{js,ts} is one widget. Sub directories without an index entry (helpers, fixtures, shared modules like _shared/) are ignored silently, with no warning. Widgets and pages coexist: a project can contain only widgets/, only pages/, or both, and the build discovers whatever is present.

Choosing a base class

AIUXWidgetElement extends AIUXElement: it's a superset, so the real question is whether the widget needs what the superset adds. The choice affects runtime capabilities, not how the file builds: both go through the same discovery, analysis, and bundling pipeline.

Base class Use it for Adds
AIUXElement A presentational widget that receives its data through @property from a parent, or a page; every pages/<route>/page.js extends AIUXElement Tailwind + DaisyUI styling, this.loaderData, getLayoutData(key), the static async loader(ctx) convention, this.server, and trackEvent() telemetry
AIUXWidgetElement A discoverable, self-contained widget that owns its data; the platform can register it and the AI can place it Everything AIUXElement has, plus a reactive this.data populated by this.server's result, dependency injection through this.deps, and chat context through setAiContext()

Note: this.server and trackEvent() live on the shared AIUXElement base and are available either way. AIUXWidgetElement is what makes this.server's result land in a reactive this.data. Reach for AIUXWidgetElement when you need that reactive property, not to get this.server itself.

Start with AIUXElement. Reach for AIUXWidgetElement only when the widget genuinely needs to be a discoverable, self-fetching unit; because it's a superset, you can upgrade later without rewriting render logic. Pages are always AIUXElement. Never extend LitElement directly; that loses the automatic styling, loaderData/data, and the loader and server-script conventions.

Keywords WidgetsProject shapeChoosing a base classThe extends chain may be transitiveDiscoverabilityMetadata decoratorsrequiresPageTypeResolving a widget at runtimeSee also
Search documentation
Search document titles and file paths on the australia branch