Building API responses by hand means placing every pixel yourself. With the SDK, you describe the content and its appearance, and it generates protocol-compliant response data.
Your API’s JSON response determines what a widget displays; see the API reference for the format. The protocol is simple, but writing everything by hand takes work: breaking text into pixels and calculating rows and columns, coloring each cell of pixel art, or aligning a chart’s matrix with curves, axes and labels while accounting for the app’s rendering constraints. None of this work is specific to your application.
The SDK wraps this work in functions. Choose what to display and how it should look, then call the appropriate function to generate protocol-compliant matrix or layer data. You do not need to assemble pixels by hand.
The SDK provides two levels of functionality:
Drawing primitives: Matrix is a freely drawable pixel grid, with methods for lines, rectangles, circles, polygons, pixel text and image conversion. Layer builders create text, icons, lines, shapes, images and curves. These correspond to the protocol’s basic content elements.
Components: ready-made functions for common displays such as line charts, bar charts, progress bars, progress rings, status strips, heatmaps and metric cards. Each combines matrices, curves and other layers into a complete layout in one call. You supply the data, whether it represents sales, battery level or task progress. Components save layout work without tying you to a particular use case.
Your job is to generate content with the SDK and include it in your API response body.
iThe SDK is a pure function library: it makes no network requests, starts no server and stores no state. Card materials such as glass, solid colors and gradients are configured in the app, independently of the SDK and API.
All nine SDKs provide the same features and pass the same cross-language tests. Select a programming language in any code card to update the whole page; your choice is saved. Previews above the examples come from actual SDK output and use the same rendering rules as the API reference. Select “Output JSON” to inspect the response.
Packageglance-widgets-sdk (import as glance_widgets)
RuntimeRuby 2.6+
Lua
Packageglance-widgets-api-sdk
RuntimeLua 5.4 + lua-cjson
C++
PackageHeader-only, include/glance_widgets
RuntimeC++17
npm install @glance-widgets/api-sdk
✓Only Lua requires a third-party runtime dependency: lua-cjson. If a package is not yet available in your package manager, use the source in the SDK repository’s sdks/<language> directory directly.
Start with where the APIs live. The SDK exposes objects such as Matrix, Box and PixelFont with their methods; content builders for text and charts; and utilities for composition, output and colors. Components such as charts and progress bars are created by functions. The entry points and naming conventions for each language are listed below. Changing the programming language updates this guide, the code examples and the full API reference together.
@glance-widgets/api-sdk · ESM named exports
Classes and instances
Matrix · Box · PixelFont
Import directly from the package. Create instances with new. Matrix.set, line, text and toRoot are instance methods; Box.canvas and Box.fromPt are static methods.
Content builders
text · barChart · progressBar · stat
Import alongside classes and call directly. Chart components are functions and do not require new.
Utilities and presets
merge · toResponse · rgb · themes
Call utility functions directly. Presets such as themes.led and themes.lcd are also exported from the package.
Types
Canvas · MatrixOptions · Composite
Use import type for option and return types. These are not classes you can instantiate at runtime; options are usually plain objects.
Protocol fields in options keep their original names, such as dataPath and fontSizeRatio. Function names, method names and native type members follow each language’s conventions. The example above covers imports, instance creation, instance methods, class or package entry points, and response generation. See the full API reference for parameters.
Set the size.canvas is the widget’s content area in pt. Every app request includes gw_canvas_width_pt and gw_canvas_height_pt. Sizes can differ across devices, in-app previews and the Home Screen, so use the values from each request rather than hard-coding them. The example uses 338 × 158, a common medium widget size on iPhone.
Generate content.pixelTextRoot lays out text in a 5×7 pixel font, then calculates a grid that fills the content area with the text centered horizontally and vertically. maxCellSize caps pixel size, leaving several rows of unlit pixels around the text. theme: 'led' selects glowing round pixels.
Finalize the response.toResponse fills in required protocol fields and validates the result. Serialize the returned object to JSON for your response body.
The SDK uses three coordinate systems for different purposes. Position components such as charts and layers such as text with a frame or Box, expressed as fractions of the widget’s content area.
Coordinates
Unit
Meaning
Typical use
Canvas canvas
pt
{ width, height }: the widget’s content area, taken from gw_canvas_width_pt / gw_canvas_height_pt. The SDK uses the actual aspect ratio to size and arrange matrix cells correctly and choose appropriate text sizes.
Read both values on every request and pass them to functions such as pixelTextRoot and barChart. To draw in part of the area, specify a frame; keep canvas as the full content size.
frame / Box
Fractions of widget width and height, 0–1
A component or layer’s position and size. left and width are relative to the content width; top and height are relative to its height.
For a chart in the lower portion: frame: Box.canvas(canvas).sub(0, 0.4, 1, 0.6). You can also position a title in the top-left corner.
Matrix coordinates
Pixels
(x, y) in a Matrix means (column, row), starting at 0 in the top-left corner.
In 16 × 16 pixel art, art.circle(11, 3, 2, color) draws a circle centered at column 11, row 3.
Canvas canvas
Unitpt
Meaning{ width, height }: the widget’s content area, taken from gw_canvas_width_pt / gw_canvas_height_pt. The SDK uses the actual aspect ratio to size and arrange matrix cells correctly and choose appropriate text sizes.
Typical useRead both values on every request and pass them to functions such as pixelTextRoot and barChart. To draw in part of the area, specify a frame; keep canvas as the full content size.
frame / Box
UnitFractions of widget width and height, 0–1
MeaningA component or layer’s position and size. left and width are relative to the content width; top and height are relative to its height.
Typical useFor a chart in the lower portion: frame: Box.canvas(canvas).sub(0, 0.4, 1, 0.6). You can also position a title in the top-left corner.
Matrix coordinates
UnitPixels
Meaning(x, y) in a Matrix means (column, row), starting at 0 in the top-left corner.
Typical useIn 16 × 16 pixel art, art.circle(11, 3, 2, color) draws a circle centered at column 11, row 3.
Manually calculated frame values quickly become hard to maintain. Box starts with the full content area, then lets you inset and subdivide it before passing the result to a layer or component. The diagram follows the example in Layers:
Box layout: carving layer frames out of the canvasScroll horizontally on narrow screens · Select a step to see the area it produces
Box methods return new Box objects without modifying the original.
Ratios in sub, inset, rows and columns are relative to the current Box. insetPt and gapPt use pt and require canvas information, which Box.canvas(canvas) includes.
Frame width and height are limited to 0.02–1.5. Smaller dimensions expand to 0.02 around the center, so a zero-height Box can specify the position of a horizontal line.
SDK results come in four forms: a root grid (RootMatrix), an unplaced matrix (MatrixPart), layer declarations with their layer objects (Composite), and response fragments (Partial<Response>: any object that follows the response structure, such as a handwritten { data }). Except for MatrixPart, which must be positioned with place first, all of them can be combined directly with merge and finished with toResponse.
SDK output types and compositionScroll horizontally on narrow screens · Select a card to trace its path
Remember two rules: call place on a MatrixPart before merging, and always finalize with toResponse. See Combining components for a complete example.
Use new Matrix(columns, rows, options?) to create a grid of columns × rows initially undrawn pixels. Draw with its methods, then export it as described under “Exporting a root matrix or layer” below. Drawing outside the grid is clipped without an error.
The third argument, options, is optional. By default, undrawn pixels are hidden and the base pixel style is opaque white squares. To customize the appearance, use these three fields:
default: the appearance of undrawn pixels. Defaults to hidden ('empty'); set a color or style for an unlit background.
base: supplies opacity, corner radius, rotation and glow when you draw using only a color.
You can usually use a theme instead of configuring these fields yourself; see “Pixel styles and themes” below.
16 × 16 · lcd theme
import{Matrix, themes, themeOptions, toResponse }from'@glance-widgets/api-sdk';const hills =[[0,15],[0,11],[5,6],[9,10],[12,7],[15,10],[15,15]];const art =newMatrix(16,16,themeOptions(themes.lcd));
art
.circle(11,3,2,'#FFD23F').polygon(hills,'#3E6B33').polygon(hills,'#9BFF6B',{ fill:false}).text('HI',1,1,{ font:'3x5', style:'#FFFFFF'});const response =toResponse(art.toRoot());
Drawing methods
Method
Purpose
set(x, y, style) · get(x, y)
Set or read one pixel; out-of-bounds coordinates throw an error.
fill(style) · clear()
Fill or clear the entire grid.
line(x0, y0, x1, y1, style)
Draw a straight line.
rect · roundRect · ellipse · circle
Draw rectangles, rounded rectangles, ellipses and circles. Use { fill: false } for outlines only.
arc(cx, cy, r, start, end, style)
Draw an arc clockwise from 0° at 12 o’clock; set its width with { thickness }.
polygon(points, style)
Draw a polygon from a list of [x, y] points.
floodFill(x, y, style)
Flood-fill the connected region of the same color from a pixel.
text(content, x, y, options)
Draw pixel text; options can specify font and style.
blit(other, x, y)
Paste another Matrix at a position, skipping empty pixels.
flipX · flipY · rotate90 · crop · clone
Flip, rotate, crop or copy. Returns a new Matrix, leaving the original unchanged.
set(x, y, style) · get(x, y)
Set or read one pixel; out-of-bounds coordinates throw an error.
fill(style) · clear()
Fill or clear the entire grid.
line(x0, y0, x1, y1, style)
Draw a straight line.
rect · roundRect · ellipse · circle
Draw rectangles, rounded rectangles, ellipses and circles. Use { fill: false } for outlines only.
arc(cx, cy, r, start, end, style)
Draw an arc clockwise from 0° at 12 o’clock; set its width with { thickness }.
polygon(points, style)
Draw a polygon from a list of [x, y] points.
floodFill(x, y, style)
Flood-fill the connected region of the same color from a pixel.
text(content, x, y, options)
Draw pixel text; options can specify font and style.
blit(other, x, y)
Paste another Matrix at a position, skipping empty pixels.
flipX · flipY · rotate90 · crop · clone
Flip, rotate, crop or copy. Returns a new Matrix, leaving the original unchanged.
Drawing methods modify and return the current Matrix, so you can chain calls as in the example.
Pixel styles and themes
A style can be a color or a partial pixel style { color, opacity, cornerRadius, rotation, halo }. Omitted fields use the theme’s lit-pixel style. 'empty' explicitly leaves a pixel blank; null restores its undrawn default.
Themes define unlit pixels, lit pixel shapes and spacing. The five built-in themes render the same drawing as follows:
ledRound, glowing pixels with wide spacing
lcdSquare cells with narrow spacing; component default
dotSmall round dots with very wide spacing
diamondDiamonds rotated 45°
softRounded squares with a soft glow
A theme is a preset options object: unlit appearance (default), lit base style (base) and layout (layout). Pass themeOptions(themes.led) to Matrix for the led theme. To customize it, supply overrides as the second argument, for example themeOptions(themes.led, { layout: { gapMode: 'near' } }). default is replaced entirely; base and layout are overridden field by field.
For components, set the theme name directly, such as theme: 'led'. Each theme also has a palette: on (lit), off (unlit), dim (dimmed lit color) and accent (contrasting highlight). Use colors such as themes.led.palette.accent to keep drawings consistent with the theme.
Pixel fonts
The built-in 3x5 and 5x7 fonts include printable ASCII characters and common symbols (° ± × ÷ € ← → ↑ ↓, etc.). Use measureText(text, font) for exact dimensions. Supply custom glyphs to draw Chinese or other scripts.
Character width and monospace text
Pixel text uses each glyph’s own width by default. In 5x7, for example, 1 occupies fewer columns than 2, giving compact text. In clocks and counters, however, changing digits can change the overall width even when the character count stays the same, making the layout shift.
Set monospace: true for stable character widths: 5 columns per character in 5x7, or 3 in 3x5, with narrower glyphs centered in the cell. Spaces and punctuation use the same width. The default is false, which uses each glyph’s width.
Matrix.text, textMatrix, measureText, pixelTextRoot and pixelTextPanel support monospace. Use the same setting when measuring and drawing. Monospace keeps single-line text at a stable width while the character count stays constant; adding characters or line breaks still changes its dimensions.
Loading custom pixel fonts
Custom fonts use the SDK’s FontDefinition format. Define each character as rows of pixels: # for lit and . for blank. Save the definition as JSON, load and parse it in your service, then pass it to the SDK. This seven-row font contains just the characters “中” and “文”; save it as my-font.json:
Register the loaded definition with defineFont, then pass the returned font object or registered name as font. The example follows your selected programming language. File loading and JSON parsing use the language’s standard library; the SDK validates glyphs, lays out text and draws pixels.
import{ readFileSync }from'node:fs';import{ defineFont, pixelTextRoot, toResponse }from'@glance-widgets/api-sdk';// Load and register once at service startupconst definition =JSON.parse(readFileSync('./my-font.json','utf8'));const font =defineFont(definition);// Use each request’s canvas size; font: 'my-cn7' also refers to the registered fontconst canvas ={ width:338, height:158};const response =toResponse(pixelTextRoot('中文',{ canvas, font }));
Font field
Description
name · height · glyphs
Required: font name, rows above the baseline, and character-to-glyph mapping. Each key is one Unicode character; all rows within a glyph must have equal width.
spacing · lineSpacing
spacing is the font definition’s default character spacing; lineSpacing is a text layout option. Both default to 1 and are measured in pixels.
descent
Extra rows below the baseline, default 0. A glyph can contain up to height + descent rows. Glyphs shorter than height are padded with blank rows at the bottom.
advance
Optional uniform character advance. If omitted, individual glyphs can use { rows, advance } to set their own advance.
aliases
Reuse an existing glyph, for example { "a": "A" }.
fallback
Replacement character for missing glyphs; it must exist in the font. If omitted, drawing an unsupported character throws an error.
name · height · glyphs
Required: font name, rows above the baseline, and character-to-glyph mapping. Each key is one Unicode character; all rows within a glyph must have equal width.
spacing · lineSpacing
spacing is the font definition’s default character spacing; lineSpacing is a text layout option. Both default to 1 and are measured in pixels.
descent
Extra rows below the baseline, default 0. A glyph can contain up to height + descent rows. Glyphs shorter than height are padded with blank rows at the bottom.
advance
Optional uniform character advance. If omitted, individual glyphs can use { rows, advance } to set their own advance.
aliases
Reuse an existing glyph, for example { "a": "A" }.
fallback
Replacement character for missing glyphs; it must exist in the font. If omitted, drawing an unsupported character throws an error.
Matrix.text, textMatrix, pixelTextRoot, pixelTextPanel and measureText support custom fonts. In pixel mode, stat uses pixelFont and pixelUnitFont for the value and unit. You may pass a font definition inline without registering it; register it only to reuse it by name. A name cannot be registered twice, so registration normally happens once at service startup. The app receives pixel data and needs no font installation.
i.ttf, .otf, .woff and BDF files cannot be passed directly. The SDK has no parser or converter for these formats. Convert the required characters into the pixel glyph format above outside the SDK first. Font names must be built-in or registered names, not file paths, URLs or system font names.
Exporting a root matrix or layer
Method
Result
Use case
toRoot()
RootMatrix
A widget made entirely of a matrix, such as a clock or pixel art.
toPart()
MatrixPart
A matrix in part of the content area, or combined with text and charts.
toRoot()
ResultRootMatrix
Use caseA widget made entirely of a matrix, such as a clock or pixel art.
toPart()
ResultMatrixPart
Use caseA matrix in part of the content area, or combined with text and charts.
!The app adds a roughly 9% white inner stroke to root-matrix pixels with opacity above 0.4. The API cannot disable it. For flat colors, export a matrix layer with toPart().
Converting images to matrices
pixelate(image, { columns, rows }) downsamples an image into a grid, averaging the source region for each cell. Use palette to restrict colors and alphaThreshold to skip transparent regions. It accepts decoded RGBA pixels{ width, height, data }; you must read and decode the image file yourself.
Widgets can contain text, icons, lines, shapes, images and curves alongside matrices. The SDK provides a builder for each layer type, filling in fields whose app defaults may be unexpected, such as text alignment and icon font metadata, and normalizing colors.
Icons, text and dividers · Layout shown in the Box diagram above
Layer builders produce remote layers, meaning remote: layers declared by the API; a missing remote: prefix on id is added automatically. They accept { id, frame, dataPath?, zIndex?, rotation?, transform?, style? } plus content-specific options. frame is required and accepts a Box. Each function returns a Composite, that is { layers, data }: layers holds the layer declarations, and data holds the layer objects that dataPath points to, including layout, content and style. When dataPath is omitted it is generated from id. Use toResponse(text(...)) to output a single layer, or merge(text(...), icon(...), chart) to combine several layers or components.
Builder
Content
Description
text
text
fontSizeRatio is relative to the shorter side of the widget’s content area, not the layer height.
icon
name, glyph or url
name comes from the built-in catalog (about 5,300 icons). Unknown names throw an error.
horizontalLine · verticalLine
at、from、to
Specify line position and endpoints as fractions of widget dimensions, avoiding manual frame calculations.
line
direction
Draw a horizontal or vertical line inside the frame.
shape
—
Rounded rectangle. The app enforces a 24 pt minimum; use lines or matrices for thinner elements.
image
url
Remote images may fail to load on the Home Screen. Prefer Base64 for small images.
curve
data
Native curve layer. For line charts, you will usually want a chart component.
text
Contenttext
DescriptionfontSizeRatio is relative to the shorter side of the widget’s content area, not the layer height.
icon
Contentname, glyph or url
Descriptionname comes from the built-in catalog (about 5,300 icons). Unknown names throw an error.
horizontalLine · verticalLine
Contentat、from、to
DescriptionSpecify line position and endpoints as fractions of widget dimensions, avoiding manual frame calculations.
line
Contentdirection
DescriptionDraw a horizontal or vertical line inside the frame.
shape
Content—
DescriptionRounded rectangle. The app enforces a 24 pt minimum; use lines or matrices for thinner elements.
image
Contenturl
DescriptionRemote images may fail to load on the Home Screen. Prefer Base64 for small images.
curve
Contentdata
DescriptionNative curve layer. For line charts, you will usually want a chart component.
Components turn common displays into a single function call: supply data and the widget’s content size to get a complete layout.
Bar charts, progress bars and progress rings each come in two drawing styles: barChart, progressBar and ringProgress are built from native layers with round caps and translucent tracks, matching iOS; pixelBarChart, pixelProgressBar and pixelRingProgress are assembled from matrix cells in an LED dot-matrix style. battery and signal exist only in the native-layer style.
Below are all components rendered at the small widget size. Select one to jump to its documentation.
pixelProgressBar, pixelRingProgress, statusStrip, heatmap and calendarHeatmap return a MatrixPart that you position with place.
labeledXxx() returns a Composite: a matrix with text labels, ready to merge. canvas is required to lay out text in pt.
Charts (barChart, lineChart, etc.), progressBar, ringProgress, battery, signal and stat also return Composite.
Common options
Option
Description
canvas
Widget content size in pt. Required for labeled*, charts, progressBar, ringProgress, battery, signal and stat.
frame
Drawing region; defaults to the entire widget content area. Accepts a Box directly.
theme
Theme name or theme object for matrix content, default lcd. barChart, progressBar, ringProgress, battery and signal contain no matrix and do not accept this option.
colors
Component colors. Standard progress bars and rings use fill / track / label; matrix components use their own keys such as on / off.
id
Layer ID prefix. Two components of the same kind in one response must have different IDs.
path
Location in data of the component’s matrix layer object, default data.<id>; the other layer objects are placed according to their own ids. barChart, progressBar, ringProgress, battery and signal contain no matrix and do not accept this option.
zIndex
The component’s stacking order.
canvas
Widget content size in pt. Required for labeled*, charts, progressBar, ringProgress, battery, signal and stat.
frame
Drawing region; defaults to the entire widget content area. Accepts a Box directly.
theme
Theme name or theme object for matrix content, default lcd. barChart, progressBar, ringProgress, battery and signal contain no matrix and do not accept this option.
colors
Component colors. Standard progress bars and rings use fill / track / label; matrix components use their own keys such as on / off.
id
Layer ID prefix. Two components of the same kind in one response must have different IDs.
path
Location in data of the component’s matrix layer object, default data.<id>; the other layer objects are placed according to their own ids. barChart, progressBar, ringProgress, battery and signal contain no matrix and do not accept this option.
zIndex
The component’s stacking order.
iWhen a MatrixPart component receives both canvas and frame, its grid fills that region using the actual aspect ratio. Use the same frame in place to avoid distorted or misaligned pixels. Without canvas, pixels stay square and are centered in the frame passed to place.
Line charts use the app’s native curve layers for smooth lines. Each series can be an array of values, { values, color }, or { points: [[x, y], …] }. All series share the same coordinate range.
{ last, min, max, labels, radius }: mark the last, lowest and highest points with dots; labels shows their values.
xLabels
—
Bottom labels, evenly spaced from left to right.
min · max
Data range
Fix the vertical axis range.
interpolation
monotone
Curve interpolation method.
strokeWidth
2
Line width in pt.
grid
false
Background pixel grid aligned with the plot area.
showAxes · showValueLabels
true
Axes and value labels on the left.
markers
Default—
Description{ last, min, max, labels, radius }: mark the last, lowest and highest points with dots; labels shows their values.
xLabels
Default—
DescriptionBottom labels, evenly spaced from left to right.
min · max
DefaultData range
DescriptionFix the vertical axis range.
interpolation
Defaultmonotone
DescriptionCurve interpolation method.
strokeWidth
Default2
DescriptionLine width in pt.
grid
Defaultfalse
DescriptionBackground pixel grid aligned with the plot area.
showAxes · showValueLabels
Defaulttrue
DescriptionAxes and value labels on the left.
areaChart is a line chart with translucent fill (fillOpacity defaults to 0.3). sparkline is a compact trend line without axes, with the last point marked by default. It needs no canvas unless grid is enabled.
labeledCalendarHeatmap · heatmap · Heatmaps
Calendar heatmaps use one pixel per day and one column per week, ideal for daily activity. start is the date of the first value; each subsequent value advances one day.
import{Box, labeledCalendarHeatmap, toResponse }from'@glance-widgets/api-sdk';const canvas ={ width:338, height:158};const days =[];for(let i =0; i <140; i++) days.push((i *37+(i % 7)*11) % 9);const calendar =labeledCalendarHeatmap(days,{
canvas,
frame:Box.canvas(canvas).inset(0.06),
start:'2026-06-01',});const response =toResponse(calendar);
Option
Default
Description
start
—
Date of the first value in YYYY-MM-DD format. Required.
levels
5
Number of color levels.
scale
Theme’s dark → bright colors
Color stops; at least two.
min · max
Data range
Values corresponding to the first and last colors.
startWeekday
0
First day of the week; 0 is Sunday.
orientation
weekColumns
Use weekRows for one row per week.
missing
'empty'
How to draw null: leave blank or use a specified color.
start
Default—
DescriptionDate of the first value in YYYY-MM-DD format. Required.
levels
Default5
DescriptionNumber of color levels.
scale
DefaultTheme’s dark → bright colors
DescriptionColor stops; at least two.
min · max
DefaultData range
DescriptionValues corresponding to the first and last colors.
startWeekday
Default0
DescriptionFirst day of the week; 0 is Sunday.
orientation
DefaultweekColumns
DescriptionUse weekRows for one row per week.
missing
Default'empty'
DescriptionHow to draw null: leave blank or use a specified color.
heatmap(rows) takes a two-dimensional array and draws a matrix heatmap with a continuous color scale by default. Both heatmap functions return MatrixPart.
A round-capped progress bar returning Composite, ready to merge. thickness is 0.5–8 pt, default 6; min / max default to 0 / 100.
orientation defaults to horizontal; vertical fills upward and reverse flips the direction. label is off by default: true shows a percentage, a string shows custom text.
labelPosition defaults to end and fontSizeRatio to 0.07. Color keys: fill / track / label.
pixelProgressBar · labeledPixelProgressBar · Dot-matrix progress bar
A segmented progress bar made of pixels. labeledPixelProgressBar includes a percentage label; pixelProgressBar returns only the matrix and requires place.
DescriptionStarting angle (0 is 12 o’clock) and direction.
label
DefaultPercentage
DescriptionText in the center.
battery · signal · Battery and signal
battery and signal return a Composite, require canvas and merge directly. Both sit at the left of the frame, vertically centered; min / max default to 0 / 100.
battery is a translucent capsule body with a terminal tab and a round-capped level bar: height 5–12 pt (default 12), width defaults to 2.3 × height. Charge ≤20% is red, ≤40% amber, otherwise green. label is off by default; true shows a percentage to the right, a string shows custom text. Color keys: fill / good / warn / bad / track / label.
signal is a status-bar style set of slim round-capped bars rising from 35% to 100% of the height: bars defaults to 4, height to the frame height (at most 14 pt), barWidth is 0.5–8 pt, defaulting to 26% of the height. Color keys: fill / track.
A label, large value, unit and change indicator. Positive changes show a green upward arrow. Set invertDelta: true for metrics where lower is better, such as latency or error counts.
Change value; determines arrow direction and color.
deltaSuffix · deltaDecimals
— · 1
Change suffix (such as %) and decimal places. deltaText replaces the entire change text.
invertDelta
false
Treat decreases as improvements.
valueStyle
text
Use pixel to display the value in a pixel font.
align
left
left or center.
decimals
0 for integers, otherwise 1
Decimal places for the value.
label · unit
Default—
DescriptionLabel and unit.
delta
Default—
DescriptionChange value; determines arrow direction and color.
deltaSuffix · deltaDecimals
Default— · 1
DescriptionChange suffix (such as %) and decimal places. deltaText replaces the entire change text.
invertDelta
Defaultfalse
DescriptionTreat decreases as improvements.
valueStyle
Defaulttext
DescriptionUse pixel to display the value in a pixel font.
align
Defaultleft
Descriptionleft or center.
decimals
Default0 for integers, otherwise 1
DescriptionDecimal places for the value.
pixelTextRoot · pixelTextPanel · Pixel text
Draw text in a pixel font, automatically sizing pixels to fit the frame. pixelTextRoot creates a root matrix, as used by the clock in Your first response. pixelTextPanel creates a MatrixPart for any region; use the same frame when calling place.
Option
Default
Description
font
5x7
Pixel font name or definition.
theme · color
lcd · Theme’s lit color
Appearance and text color.
align · valign
center
Position of the text block within the region.
lineAlign
Same as align
Alignment of lines within multiline text.
monospace
false
Uses a uniform cell width for every character, including spaces and punctuation, centering narrow glyphs. 5x7 uses 5 columns per character, keeping clocks and counters stable when text length is unchanged. When disabled, each glyph uses its own width.
letterSpacing · lineSpacing
Font default
Character and line spacing in pixels.
unlit
true
Whether to draw unlit pixels.
maxCellSize
—
Maximum pixel side length in pt, preventing short text from becoming oversized blocks.
font
Default5x7
DescriptionPixel font name or definition.
theme · color
Defaultlcd · Theme’s lit color
DescriptionAppearance and text color.
align · valign
Defaultcenter
DescriptionPosition of the text block within the region.
lineAlign
DefaultSame as align
DescriptionAlignment of lines within multiline text.
monospace
Defaultfalse
DescriptionUses a uniform cell width for every character, including spaces and punctuation, centering narrow glyphs. 5x7 uses 5 columns per character, keeping clocks and counters stable when text length is unchanged. When disabled, each glyph uses its own width.
letterSpacing · lineSpacing
DefaultFont default
DescriptionCharacter and line spacing in pixels.
unlit
Defaulttrue
DescriptionWhether to draw unlit pixels.
maxCellSize
Default—
DescriptionMaximum pixel side length in pt, preventing short text from becoming oversized blocks.
Objects merge recursively. At the same path, later scalar values or arrays replace earlier ones.
layers
Layers are appended in order. A later layer with the same ID replaces the earlier one in place.
Root matrix
Replaced as a whole by a later root matrix.
MatrixPart
Cannot be merged directly; call place first. Otherwise an error is thrown.
data
Objects merge recursively. At the same path, later scalar values or arrays replace earlier ones.
layers
Layers are appended in order. A later layer with the same ID replaces the earlier one in place.
Root matrix
Replaced as a whole by a later root matrix.
MatrixPart
Cannot be merged directly; call place first. Otherwise an error is thrown.
Overwrites often indicate duplicate IDs or paths. While debugging, use merge(a, b, { onConflict: 'error' }) to throw an error with the conflicting path. merge does not modify its inputs.
!The response body is limited to 512 KB and the root matrix to 4,096 pixels.
Layer builders and components produce remote layers: the response declares the layer, and its position, content and style all come from the API. The SDK can also generate dynamic content and style for layers that an author adds in the app’s editor.
An editor layer’s position, content and style are saved in the widget configuration. Once the author sets a data path for it, the API only needs to return one layer object at that path: fields present in the object override the editor’s settings, and fields that are absent keep the editor’s configuration. See the merge rules in the API documentation. Editor layers are not written to the response’s layers.
Providing data for an editor layer therefore means using the SDK to build the part of the layer object that needs to change, and placing it under the layer’s data path:
Content: for a matrix, Matrix.toPart() returns { content }, which can be used directly; for an icon, iconGlyph(name) returns { icon, iconCodePoint, iconFont }, to be used as content; for other types such as curves, call the matching layer builder and take only the layer object’s content from the returned data; for text, write { content: { text: '128' } }.
Style: write only the fields that should change with the data, for example { style: { color: '#FF453A' } }. Matrix layers have no style field.
Layout: return frame, zIndex, rotation or transform only when the API needs to change position or size; frame must include width and height.
!Do not hand the whole object returned by a layer builder to an editor layer. Builders require a frame and fill in every default style; once those fields are returned, they override the layout and style the author set in the editor.
In the example below, the author added a matrix layer in the editor and set its data path to data.badge. The server draws the pattern with Matrix and places the result of toPart() at data.badge:
import{Matrix, themes, themeOptions, toResponse }from'@glance-widgets/api-sdk';const heart =newMatrix(9,9,themeOptions(themes.led)).circle(4,4,4,'#FF453A');// The editor's matrix layer reads data.badge: send only the dataconst response =toResponse({ data:{ badge: heart.toPart()}});
The response returns no layout fields, so the matrix keeps its position and size from the editor. The result of toPart() always includes default and layout, which override the editor’s default dot style and spacing; remove those two fields to keep the editor’s settings for them.
✓For matrix, text, curve, line and shape layers in the editor, “Current preview” is set to “Default style” by default. In that state the edit page shows only the editor’s settings and does not apply API data. When debugging, switch it to “API data”; the Home Screen always applies API data.
The SDK does not handle HTTP. For each request, your service should:
Read gw_canvas_width_pt and gw_canvas_height_pt from query parameters (strings with two decimal places) and check that they are valid positive numbers.
Fetch application data and generate a response with the SDK.
Return UTF-8 JSON with Content-Type: application/json.
import{ ringProgress, toResponse }from'@glance-widgets/api-sdk';// params: the request's query parametersexportfunctionbuildWidget(params){const width =Number(params.gw_canvas_width_pt);const height =Number(params.gw_canvas_height_pt);if(!(width >0&& height >0)) throw newError('missing canvas size');const ring =ringProgress(72,{ canvas:{ width, height }});returnJSON.stringify(toResponse(ring));}// Send the string with Content-Type: application/json; charset=utf-8
Verify the request signature
Once you set a secret for the API in the app, every request carries X-GlanceWidgets-Timestamp and X-GlanceWidgets-Signature headers; the secret itself is never sent. Pass both values and your stored secret to verifySignature: it recomputes the signature, compares it in constant time and rejects requests more than 5 minutes (by default) away from your server clock. When it returns false, end the request with 401.
import{ verifySignature,TIMESTAMP_HEADER,SIGNATURE_HEADER}from'@glance-widgets/api-sdk';// headers: request headers with lower-cased names; secret: the key set in the Appconst ok =verifySignature({
timestamp: headers[TIMESTAMP_HEADER.toLowerCase()],
signature: headers[SIGNATURE_HEADER.toLowerCase()],}, secret);if(!ok){// respond 401 and stop}
The header names are exported as TIMESTAMP_HEADER and SIGNATURE_HEADER. The algorithm and a test vector are in the API reference; per-language signatures are in the class reference.
✓If a Home Screen request fails, the widget quietly keeps its last successful content. Only the in-app preview displays errors. Verify your response in the preview before release.
toResponse checks the root matrix, the remote layer declarations and the objects they reference, including field types, paths, dimensions and response limits. Invalid responses throw GlanceValidationError, whose path identifies the failing field:
Use validate(response) for complete handwritten responses.
toResponse and validate check only the remote layers declared in layers. Editor layers do not appear in layers, so the SDK does not know their type and does not validate the layer objects prepared for them; when needed, check one with validateLayerNode(node, type), for example validateLayerNode(response.data.badge, 'matrix'). It follows the same rules as editor layers and allows layout, content and style fields to be omitted. An invalid layer object makes an editor layer in the app fall back to its saved state and a remote layer not draw, so validating early catches such problems before release. See the full API reference for per-language signatures and error types.
Common issues
Symptom
Cause and solution
Colors become transparent or fail validation
Eight-digit colors use #AARRGGBB, with alpha first, unlike CSS #RRGGBBAA.
Correct in preview, distorted or misaligned on the Home Screen
The content area sizes differ. Regenerate for each request’s gw_canvas_* values rather than caching one size’s output.
Remote layer missing, or an editor layer does not apply API data
Check that dataPath points to a layer object, that a remote layer’s object has a frame with width and height, and that the fields in content and style belong to the layer type. For editor layers, also confirm that “Current preview” is set to “API data”.
Matrix pixels are stretched or misaligned
Different frames were used to build the MatrixPart and to call place.
Right-aligned numbers appear at the top left
The app forces top-left alignment when text exceeds the layer width. Allow enough width in custom text layers; components already account for text width.
Text is larger or smaller than expected
fontSizeRatio is relative to the content area’s shorter side, in the range 0.02–0.28.
Shapes are larger than specified
The app enforces a 24 pt minimum for shape. Use line layers for thin lines and matrices for narrow bars.
Lit root-matrix pixels have white borders
This is inherent to root matrices. Use toPart() and place to create a matrix layer instead.
Unexpected numbers or app crashes
Do not put integers with an absolute value of 9.2 × 10¹⁸ or greater in data.
Colors become transparent or fail validation
Eight-digit colors use #AARRGGBB, with alpha first, unlike CSS #RRGGBBAA.
Correct in preview, distorted or misaligned on the Home Screen
The content area sizes differ. Regenerate for each request’s gw_canvas_* values rather than caching one size’s output.
Remote layer missing, or an editor layer does not apply API data
Check that dataPath points to a layer object, that a remote layer’s object has a frame with width and height, and that the fields in content and style belong to the layer type. For editor layers, also confirm that “Current preview” is set to “API data”.
Matrix pixels are stretched or misaligned
Different frames were used to build the MatrixPart and to call place.
Right-aligned numbers appear at the top left
The app forces top-left alignment when text exceeds the layer width. Allow enough width in custom text layers; components already account for text width.
Text is larger or smaller than expected
fontSizeRatio is relative to the content area’s shorter side, in the range 0.02–0.28.
Shapes are larger than specified
The app enforces a 24 pt minimum for shape. Use line layers for thin lines and matrices for narrow bars.
Lit root-matrix pixels have white borders
This is inherent to root matrices. Use toPart() and place to create a matrix layer instead.
Unexpected numbers or app crashes
Do not put integers with an absolute value of 9.2 × 10¹⁸ or greater in data.
canvas requirementOptional (fills frame when provided)
Layer count1 after placement
pixelTextPanel
ReturnsMatrixPart
canvas requirementRequired
Layer count1 after placement
pixelTextRoot
ReturnsRootMatrix
canvas requirementRequired
Layer count0
The public SDK APIs below are organized by class and function, including constructors, instance methods, functions, parameter types and constants. Language selection is shared with the examples above. Search by name or purpose, then expand an entry for parameters, return values and related types.
Import from @glance-widgets/api-sdk. Pass options as plain objects; returned objects serialize directly to JSON.
TypeScript · 26 / 310 entries
Signatures use the selected language. Parameter tables use shared structural notation and preserve option and protocol field names. Refer to each language’s signature for optional arguments, native types and error returns.
MatrixClassA mutable pixel grid. Coordinates are (column, row), starting at 0 in the top-left. Drawing methods modify and return this instance; transforms return independent matrices.
Drawing style: a color or an object specifying color, opacity and other properties.
style — object fields
colorOptional
string
Protocol color; alpha comes first in eight-digit notation.
opacityOptional
number
Opacity, 0–1.
cornerRadiusOptional
number
Pixel corner radius ratio.
rotationOptional
number
Rotation angle.
haloOptional
number
Pixel glow intensity.
optionsOptional
ArcOptions
Optional settings; fields are listed below.
options — object fields
thicknessOptional
number
Line, ring or progress bar thickness in pixels.
Returns: this (current instance; supports chaining)
Related types
Matrix.polygonMethodDraw a closed polygon from at least three [x, y] vertices.
TypeScript signature
ts
Matrix.polygon(points:ReadonlyArray<readonly [number, number]>, style:PixelInput, options?:FillOptions): this
Parameters
pointsRequired
readonly (readonly [number, number])[]
Ordered coordinate points.
styleRequired
PixelInput
Drawing style: a color or an object specifying color, opacity and other properties.
style — object fields
colorOptional
string
Protocol color; alpha comes first in eight-digit notation.
opacityOptional
number
Opacity, 0–1.
cornerRadiusOptional
number
Pixel corner radius ratio.
rotationOptional
number
Rotation angle.
haloOptional
number
Pixel glow intensity.
optionsOptional
FillOptions
Optional settings; fields are listed below.
options — object fields
fillOptional
boolean
Fill the interior; false draws only the outline.
Returns: this (current instance; supports chaining)
Related types
Matrix.floodFillMethodFlood-fill a connected region of matching style. diagonal includes diagonally adjacent pixels.
TypeScript signature
ts
Matrix.floodFill(x: number, y: number, style:PixelInput, options?:FloodFillOptions): this
Parameters
xRequired
number
Horizontal coordinate (column); pt for geometric rectangles.
yRequired
number
Vertical coordinate (row); pt for geometric rectangles.
styleRequired
PixelInput
Drawing style: a color or an object specifying color, opacity and other properties.
style — object fields
colorOptional
string
Protocol color; alpha comes first in eight-digit notation.
opacityOptional
number
Opacity, 0–1.
cornerRadiusOptional
number
Pixel corner radius ratio.
rotationOptional
number
Rotation angle.
haloOptional
number
Pixel glow intensity.
optionsOptional
FloodFillOptions
Optional settings; fields are listed below.
options — object fields
diagonalOptional
boolean
Include diagonally adjacent pixels.
Returns: this (current instance; supports chaining)
Related types
Matrix.textMethodDraw pixel text; the default font is 3x5.
TypeScript signature
ts
Matrix.text(content: string, x: number, y: number, options?:DrawTextOptions): this
Parameters
contentRequired
string
Content to display: a string for text drawing, or a content object for layer creation.
xRequired
number
Horizontal coordinate (column); pt for geometric rectangles.
yRequired
number
Vertical coordinate (row); pt for geometric rectangles.
optionsOptional
DrawTextOptions
Optional settings; fields are listed below.
options — object fields
styleOptional
PixelInput
Drawing style: a color or an object specifying color, opacity and other properties.
style — object fields
colorOptional
string
Protocol color; alpha comes first in eight-digit notation.
opacityOptional
number
Opacity, 0–1.
cornerRadiusOptional
number
Pixel corner radius ratio.
rotationOptional
number
Rotation angle.
haloOptional
number
Pixel glow intensity.
fontOptional
FontInput
Font name, font definition or PixelFont.
font — object fields
nameRequired
string
Name.
heightRequired
number
Height.
descentOptional
number
Extra rows below the baseline.
spacingOptional
number
Default character spacing.
advanceOptional
number
Horizontal advance after drawing a glyph.
fallbackOptional
string
Fallback glyph for missing characters.
aliasesOptional
Record<string, string>
Character alias mapping.
glyphsRequired
Record<string, GlyphDefinition>
Character-to-glyph mapping.
letterSpacingOptional
number
Empty columns between characters. Defaults to the font’s spacing (1 for built-in fonts). Negative integers bring characters closer together.
monospaceOptional
boolean
Use a uniform width per character. Default false uses each glyph’s width. When true, 5x7 uses 5 columns per character and centers narrow glyphs, ideal for clocks and counters. Spaces and punctuation also use the same width.
lineSpacingOptional
number
Empty rows between text lines; default 1.
maxWidthOptional
number
Maximum columns before text wraps.
boxWidthOptional
number
Region width in columns for horizontal alignment.
alignOptional
TextAlign
Allowed values: "left""center""right"
Horizontal alignment.
Returns: this (current instance; supports chaining)
Related types
Matrix.cloneMethodCopy the matrix into an independent object.
TypeScript signature
ts
Matrix.clone():Matrix
No parameters.
Returns: Matrix
Related types
Matrix.flipXMethodFlip horizontally, returning a new matrix.
TypeScript signature
ts
Matrix.flipX():Matrix
No parameters.
Returns: Matrix
Related types
Matrix.flipYMethodFlip vertically, returning a new matrix.
TypeScript signature
ts
Matrix.flipY():Matrix
No parameters.
Returns: Matrix
Related types
Matrix.rotate90MethodRotate in 90° steps, positive clockwise. Odd numbers of turns swap rows and columns.
TypeScript signature
ts
Matrix.rotate90(turns?: number):Matrix
Parameters
turnsOptional
number
Number of clockwise 90° turns; negative is counterclockwise.
Returns: Matrix
Related types
Matrix.cropMethodCrop a rectangle; areas outside the original remain undrawn.
Horizontal coordinate (column); pt for geometric rectangles.
yRequired
number
Vertical coordinate (row); pt for geometric rectangles.
widthRequired
number
Width.
heightRequired
number
Height.
Returns: Matrix
Related types
Matrix.toRootMethodExport a root matrix, compacting repeated styles and completing defaults and layout.
TypeScript signature
ts
Matrix.toRoot():RootMatrix
No parameters.
Returns: RootMatrix
Related types
Matrix.toPartMethodExport a MatrixPart whose content holds pixels, default, layout and batch. Bind the whole object to an editor layer or position it with place.
TypeScript signature
ts
Matrix.toPart():MatrixPart
No parameters.
Returns: MatrixPart
Related types
pixelateFunctionConvert RGBA pixels to a Matrix by averaging source regions, with optional palette and alpha threshold.