Docs menu

How it works

How slowapps work

Cards, feeds, jobs and grants: the ideas you need to write a slowapp, in any language.

A slowapp is a small program, packaged as a container image, that draws cards for Slowboard screens. The hub runs it now and then, the app draws pictures, and the hub passes them to the screens. An app never talks to a screen directly and never sees another app’s data.

If you haven’t yet, the quickstart builds one in fifteen minutes. This page explains the ideas behind it.

Cards

A card is one picture plus a short title. The picture, the card body, is drawn by your app at an exact size in the screen’s colours. On the Slowboard 1085 those are four inks: black, white, yellow and red, with no shades in between.

Below each card body, slowd draws a thin strip. It shows the title of the next card and what each key does right now. Your app supplies the text (a title, and an optional peek line); slowd draws the strip itself.

Feeds and decks

A feed is a named stream of cards from one app. The Weather app has three feeds, left, middle and right; Reminders has one, prompts. The layout refers to a feed as <app>/<feed>, for example weather/middle.

Each time a feed is drawn, the app writes a short list of cards. The first is the home card: what the screen shows normally. The rest are detail cards, one key press away. Weather’s middle feed, for example, has a home card with today’s conditions and a detail card with the next 24 hours.

The screen is divided into slots by the layout, and each slot shows the cards of one or more feeds, in order. That list is the slot’s deck. You choose which feeds go in which slot when you edit the layout; the app doesn’t decide where its cards appear.

Surfaces

A feed is always drawn for an exact surface: a width, a height and a set of inks, written 452x444.k4. On the Slowboard 1085’s default layout the slots are 452 or 456 pixels wide and 444 high (the strip takes the rest). With size = "slot" in the manifest, the hub tells the app the real size on every run, so the same app works in any slot.

Jobs

An app does its work in jobs. A job is one short run: the container starts, does one thing and exits.

  • render draws the app’s feeds. The hub runs it just before the screen needs new cards.
  • event receives answers to the app’s questions (see Questions and answers).
  • Scheduled jobs, such as a sync every 15 minutes, can fetch data on their own clock, separate from rendering.

A render job is told what to draw and for when. It always draws for the time the cards will be shown, not the time it runs, because the hub starts it a little early. It says how long its cards stay true (valid_until). If the app stops producing cards, the screen keeps the old ones and marks them “as of” a time rather than going blank.

When it exits, the app’s exit code tells the hub what happened: new cards, nothing changed, a temporary failure such as a network error (try again later), or missing configuration such as an API key (wait until someone fixes it). The container contract lists the codes.

What an app may use: grants

The manifest declares what the app may use, and the hub enforces it. These are the grants:

  • Network: none, or outgoing access. Outgoing access reaches your home network as well as the internet, so only grant it to apps you trust.
  • Secrets, such as API keys, given to the app as files.
  • Data: a private folder that survives between runs, with a size limit.
  • Memory and scratch space, as hard limits.
  • Time: a job that runs too long is stopped.
  • Questions: whether the app may put questions on the screen.

An app gets nothing it didn’t ask for. Ask for as little as you can. The manifest reference has the keys.

Examples and fixtures

Every app includes test renders, called examples. An example has a fixed time, a folder of test data (a fixture) and the feeds to draw. The checking tools and CI render every example without network or secrets, twice, and require the same pixels both times. Your app has to be deterministic: the same input must always give the same picture.

For an app that fetches data, the fixture is a saved copy of what it fetched. Test without hardware explains how to make one.

Settings and pages

An app can declare settings (a time zone, a city, a checkbox), which the hub shows as a form. It can also serve its own web page through the hub, for things a form can’t do, such as editing a list of reminders. See Settings, schedules and pages.

Publishing and installing

  1. Write the app and its examples, and check them locally (Test without hardware).
  2. Push to GitHub. CI renders the examples and builds the image for every hub platform.
  3. Tag a release. CI publishes the image (Publish a slowapp).
  4. Add the app to a hub and place its feeds in the layout (Install a slowapp).

Python, or anything else

Python apps start from the template repository, build on a base image, and use the Python SDK (slowapp_kit), which checks every card before it is written. Any other language works as long as the container follows the container contract; Slowapps in any language has a Go example.

Next

Updates, now and then

A short note when there is a new board, a new slowapp, or kit news. Rarely more than one a month.