Skip to main content

Build Setup

This section covers configuring your widget's metadata, appearance, settings, and preview functionality. Proper configuration ensures your widget integrates seamlessly with the platform and provides users with a flexible, customizable experience.

Configuring Widget Metadata

Full spec

This section covers the fields you'll commonly set. For the full field-by-field spec (identity, widgetType, layout, url, version, …) see Widget Metadata in the Manual, and for widgetDetails and the settings form see Widget Overview → Widget Configuration.

Note: This configuration is already set up when you scaffold the widget — see AI Quickstart → Step 4.

Basic Widget Configuration

widget-config.json:

{
"id": 210,
"port": 5210,
"name": "ACME_KpiTracker",
"issuer": "ACME Corporation",
"widgetType": 1,
"vendorPrefix": "acme",
"tenentSlug": "acme",
"exposes": {
"./Widget": "./src/widget/widget",
"./WidgetSettings": "./src/widget/widget-settings",
"./WidgetPreview": "./src/widget-preview/widget-preview"
},
"widgetDetails": {
"title": "KPI Tracker",
"type": "Informer",
"description": "Displays key performance indicators with real-time updates and third-party integrations",
"innerTags": [],
"tags": ["Analytics", "Dashboard", "KPI", "Real-time"]
},
"layout": {
"minW": 5,
"maxW": 24,
"minH": 5,
"maxH": 12
},
"settingsSchema": { /* form fields — see Widget Configuration → Widget Settings */ }
}

port and id

The widget's port is derived from its GitLab Project ID (which is also the id in widget-config.json): port = 5{id}. For example, GitLab Project ID 210"port": 5210. The setup wizard sets both correctly when scaffolding; you only need to know this if you're updating an existing widget's config manually.

Widget Types

Widgets are one of three types — Platform (0), Dashboard (1), or Universal (2). For what each type is and when to use it, see Widget Overview → Widget Types.

What matters for configuration is that the widgetType determines which entry points the widget must expose to the host application:

widgetTypeRequired exposes
0 (Platform)./Widget
1 (Dashboard)./Widget, ./WidgetSettings, ./WidgetPreview
2 (Universal)./Widget, ./WidgetSettings, ./WidgetPreview

In the actual template the paths point to your widget folder — e.g. "./Widget": "./src/{widget-name}/{widget-name}". The create-invent-widget skill sets these up for you when scaffolding.

Preview Image

Create a preview image at public/preview.svg:

Context Rules

Context rules control when a widget is offered in the Composer's Micro App Library based on the dashboard URL's query params — configured via the contextRules object under widgetDetails in widget-config.json.

Full guide

See Widget Overview → Context for the rule types (dynamic, strict, none), regular-expression keys, and examples.


Using Theming and Styling

Reference:

  • Themes — the platform theme contract (host side)
  • Using Themes — the full token reference, runtime sync, and dark mode (widget side)

Widgets are styled with Tailwind CSS v4 utility classes plus a set of CSS design tokens, and use the shadcn-based components from @invent/wl-ui-kit-next. The host injects the live platform theme at runtime, so referencing tokens keeps a widget on-brand and dark-mode-ready with no per-widget wiring.

Deprecated: styled-components

Older widgets used styled-components with useTheme() and helper functions like getColor() / getSizeBy() / getTypography() from @invent/wl-ui-kit. That approach is deprecated — there is no useTheme, no styled.*, and none of those helpers in current widgets. Use tokens and Tailwind utilities instead. The Using Themes page has a full old→new mapping.

Styling with tokens

Style with Tailwind utilities that reference the theme tokens. Token names follow the shadcn convention, where each surface has a paired -foreground for content on top of it (bg-card / text-card-foreground):

// Base surface + text, muted secondary text, a token with an opacity modifier
<div className="flex h-full w-full flex-col bg-background text-foreground">
<p className="text-sm text-muted-foreground">Secondary label</p>
<AlertTriangle className="size-10 text-destructive/50" />
</div>

Common color tokens: background/foreground, primary, secondary, accent, muted, destructive, success, warning, card, popover, border, input, ring, and chart-1chart-5. Spacing (p-4, gap-2), radius (rounded-lg), fonts (font-sans, font-medium), and shadows (shadow-sm) are all token-driven Tailwind utilities. See Using Themes for the complete list.

Prefer the UI-Kit components

Reach for the ready-made, already-themed components from @invent/wl-ui-kit-next/ui before hand-styling — they consume the same tokens, so they inherit the platform theme and dark mode automatically:

import { Button, Card, CardContent, CardHeader, CardTitle, Badge } from '@invent/wl-ui-kit-next/ui';
import { Plus } from 'lucide-react'; // icons come from lucide-react

<Card>
<CardHeader>
<CardTitle>KPI Tracker</CardTitle>
</CardHeader>
<CardContent className="flex flex-wrap gap-2">
<Button>Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="destructive">Destructive</Button>
<Button size="icon-lg"><Plus className="size-5" /></Button>
<Badge variant="outline">Outline</Badge>
</CardContent>
</Card>;

Responsive design

A widget can be sized many different ways on a dashboard while the browser window stays large, so container queries — which respond to the widget's own width — are the right tool. Tailwind's default sm: / md: prefixes are viewport media queries (they track the browser window, not the widget), so they won't react as the widget itself is resized.

Opt a subtree into container queries with @container, then use container variants (@[600px]:, @sm:, @md:). This is the pattern the core -next widgets use:

<div className="@container flex-1 overflow-auto">
<div className="grid grid-cols-1 gap-3 @[600px]:grid-cols-2 @[960px]:grid-cols-3">
{/* reflows based on the widget's width, not the window's */}
</div>
</div>

For layout that depends on the widget's dashboard grid size, you can also read the platform layout prop (grid w/h) — see Layout and Testing.

The viewport breakpoints still exist (sm, md, lg, … plus the extra-small xxs at 20rem and xs at 26.5625rem), but reach for them only when you genuinely want window-relative behavior.


Creating Widget Settings

Widget settings are defined by the settingsSchema in widget-config.json and rendered by the platform. The full walkthrough — form types, the settingsSchema structure, the JsonForm settings component, and how settings reach your widget as props — lives in one place.

Implementing Widget Preview

Widget preview is displayed in the Dashboard Composer (Host application) when users add widgets to dashboards.

Widget Preview Component

The preview component should be an SVG React component for optimal performance and scalability.

src/widget-preview/widget-preview.tsx:

import React, { SVGProps } from "react";

function KpiTrackerPreview(props: SVGProps<SVGSVGElement>) {
return (
<svg
width="88"
height="64"
viewBox="0 0 88 64"
xmlns="http://www.w3.org/2000/svg"
style={{ display: "block" }}
{...props}
>
{/* Header */}
<rect x="4" y="4" width="80" height="8" rx="2" fill="#13B7D1" />

{/* KPI Cards */}
<rect x="4" y="16" width="25" height="20" rx="2" fill="#EDF5FA" />
<rect x="32" y="16" width="25" height="20" rx="2" fill="#EDF5FA" />
<rect x="60" y="16" width="24" height="20" rx="2" fill="#EDF5FA" />

{/* Card labels */}
<rect
x="7"
y="19"
width="19"
height="3"
rx="1"
fill="#204E6E"
opacity="0.6"
/>
<rect
x="35"
y="19"
width="19"
height="3"
rx="1"
fill="#204E6E"
opacity="0.6"
/>
<rect
x="63"
y="19"
width="19"
height="3"
rx="1"
fill="#204E6E"
opacity="0.6"
/>

{/* Card values */}
<rect x="7" y="25" width="18" height="5" rx="1" fill="#13B7D1" />
<rect x="35" y="25" width="18" height="5" rx="1" fill="#13B7D1" />
<rect x="63" y="25" width="16" height="5" rx="1" fill="#13B7D1" />

{/* Trend indicators */}
<rect x="7" y="32" width="10" height="2" rx="1" fill="#0CA660" />
<rect x="35" y="32" width="10" height="2" rx="1" fill="#0CA660" />
<rect x="63" y="32" width="10" height="2" rx="1" fill="#F33309" />

{/* Footer */}
<rect
x="4"
y="42"
width="40"
height="3"
rx="1"
fill="#204E6E"
opacity="0.4"
/>
</svg>
);
}

export default KpiTrackerPreview;

Alternative: Image Preview

Widgets can also display a preview using an image URL specified in widget-config.json:

{
"widgetDetails": {
"title": "KPI Tracker",
"type": "Informer",
"description": "Displays key performance indicators",
"customLogo": "https://example.com/path/to/preview-image.png"
}
}

When customLogo is provided, it will be used instead of the SVG preview component in the Micro App Library.