Skip to main content
3 min read

The ctx object

Every page function is called with two arguments: the canvas c, which you draw with, and ctx, which is everything your app knows about the world it's drawing into.

def main(c, ctx):
c.clear()
c.text(ctx.inputs.get("msg", "HELLO").upper(), 4, 12, font="5x7", color="white")

ctx has four fields. That's the complete list — there's nothing else on it.

FieldWhat it is
ctx.inputsThe values the user filled in on the setup form.
ctx.nowThe current time, as nine integers (UTC).
ctx.widthPanel width in pixels, from the manifest.
ctx.heightPanel height in pixels. Always 32.

ctx.inputs

A dictionary keyed by the key of each input you declared in manifest.yaml. Read it with .get(key, fallback) so a blank or missing value degrades into something drawable instead of erroring:

zip_code = ctx.inputs.get("zip", "90210")
units = ctx.inputs.get("units", "metric")

Values come back as strings, except type: number inputs, which come back as an int (or a float if they aren't whole). An input the user left blank falls back to the default from your manifest before your code ever sees it.

Every key you declare must be read somewhere in app.star — validation fails an app with a setting its code never uses. See Inputs & configuration.

ctx.now

Nine integers describing the moment the panel is drawing, always in UTC, and frozen for the whole render:

FieldRangeNotes
ctx.now.unixSeconds since 1 Jan 1970. Use this for any arithmetic.
ctx.now.yeare.g. 2027
ctx.now.month1–12January is 1
ctx.now.day1–31
ctx.now.hour0–2324-hour
ctx.now.minute0–59
ctx.now.second0–59
ctx.now.weekday0–6Monday is 0
ctx.now.yday1–3661 Jan is 1

There's no date type, no strftime, and no timezone. For local time, formatting, countdowns and day names, see Handling time.

ctx.width and ctx.height

The panel size your manifest asked for. ctx.width matches c.width — use either, and use them instead of writing 128 into your code, so the same app still lays out correctly on a wider sign.

def main(c, ctx):
c.clear()
c.hline(0, 16, ctx.width, "green") # spans any panel width

What ctx doesn't have

There's no location, no timezone, no device id, no user name, and no way to store anything between renders. Each render starts fresh and knows only what's in the table above. If your app needs something about the user, ask for it as an input or fetch it over HTTP.