Pages
An app can show more than one screen. Each page is a function in app.star,
and the panel rotates through them in order, first one screen, then the next,
then back around.
Declare pages
List them in the manifest, the order is the rotation order:
pages: [now, health]
Then define one function per name in app.star (the names must match exactly):
def now(c, ctx):
c.fill("black")
c.text("AQI 42", 4, 12, font="7x12", color="green")
def health(c, ctx):
c.fill("black")
c.text("GOOD", 4, 12, font="7x12", color="green")
A two-page app, Local AQI's rotation:


If you declare a page but forget its function, validation tells you exactly what to add: "manifest lists page 'health' but app.star has no function for it. Add: def health(c, ctx):".
Every page in an app renders at the same width × height, set once in the app's
manifest.yaml. You can't mix a 128×32 page and a 64×32 page in the same app.
Refresh
refresh (seconds) controls how often the panel re-renders your pages with fresh
data, it does not control the rotation speed:
refresh: 300 # re-render every 5 minutes
Use the slowest refresh that still feels live: 60-300 for scores and prices,
3600 for weather or a daily quote.
Each render is one static picture. There's no animation, no scrolling text, a "page" changes when it's re-rendered (new data) or when the panel rotates to the next page.
Under the hood: ?page=N
You normally never touch this, but it explains what gdn render --page does: the
render endpoint takes a 1-based page number that indexes into your list. For
pages: [now, health]:
/render/local-aqi?page=1&zip=90210 # the "now" screen
/render/local-aqi?page=2&zip=90210 # the "health" screen