Make an app

An app is a folder with two small files, written in Lua in any text editor. Nothing to compile or install.

An example

Here's a whole app. app.json says what it is and main.lua is the code. It counts presses of B and remembers the count.

{
  "id": "hello",
  "name": "Hello",
  "version": "1.0.0",
  "author": "you",
  "description": "Counts presses of B, and remembers the count.",
  "category": "fun",
  "api": 1
}
local count = tonumber(unidex.data.read("count") or "0")

function draw()
  unidex.header("Hello")
  unidex.centered(80, tostring(count), "large")
  unidex.hints("", "add", "reset")
end

function onB()
  count = count + 1
  unidex.data.write("count", tostring(count))
  return "partial"
end

function onBHold()
  count = 0
  unidex.data.write("count", "0")
  return "partial"
end

For more, look at the apps in the store, or start from the template. Building apps explains how an app runs, how to lay out a screen and how to keep data through sleep.

The API

Your code defines the functions the device calls: draw, onA, onB, onBHold, onBack, tick, onEnter and onExit. To draw and save, it calls unidex.*.

Each button function returns "partial", "full" or nothing, depending on whether the screen needs a refresh.

AreaWhat it can do
Drawingheader, hints, text, centered, wrap, rect, fill, line, qr, icon, bitmap, in five font sizes, black or white
ButtonsA, B, hold B and hold A, the same way the built-in apps use them
Its own filesunidex.data.read, write, append, list, remove, in the app's own folder
The devicetime, battery, toast, wake_in, random
The webunidex.http.get over HTTPS, with the "wifi" permission

Every call, in full ↗

Plugins

A plugin adds to one of the built-in apps instead of being an app of its own. It's the same kind of folder, with "type": "plugin" and "extends".

For now, Badge is the app you can extend. Your badge() function draws a badge each time Badge shows it, so it can show today's date, a countdown or a QR code. It appears in Badge after the picture badges.

Writing plugins has the details and a template.

The sandbox

Each app is kept apart from the rest of the device:

  • Its own memory (about 512 KB) and its own folder on the SD card, up to 512 KB of data.
  • A time limit of about 2 seconds on each call, so a loop can't freeze the device.
  • No way to reach the WiFi password, API keys, notes or other apps' files. It can only use the internet with the "wifi" permission, which people see before they install.
  • If an app breaks a limit or hits a bug, the device shows App error with the line it stopped on, and the rest of the device carries on.

Try it

  1. Without a device. Open Try unidex, the emulator, and choose your app's folder under Try your app. It installs the way the store does, and shows what your code print()s.
  2. On your unidex. Plug it in, press a button, and run python3 tools/appinstall.py install path/to/your-app from a copy of the unidex repository.
  3. Automatically. node emu/test/app_smoke.mjs path/to/your-app opens it, presses every button, and tells you if it ever shows App error. The store runs the same check.

Send it in

  1. Fork unidex-apps and add your folder as apps/<id>/.
  2. Open a pull request. Automatic checks try it in the emulator and attach screenshots.
  3. A person reads it. Then it's either accepted, and appears on the Apps page within a few hours, or declined with a reason you can fix. What gets checked.