Writing a Kamoji Mini App
A Kamoji Mini App is a folder of a few small text files: a manifest that says what the mini app is, a layout of on-screen widgets, and optionally a Lua script. No firmware build, no toolchain: you write the files, zip the folder and install it from the Kamoji app. This section is the reference for mini app authors.
How a mini app runs
- Each installed mini app is one folder in Kamoji's storage,
/storage/apps/<app id>/. Kamoji finds them there at start-up and after every install or removal, and adds every valid one as a mode after the last built-in mode, in alphabetical order of their ids. Mini app modes are numbered from 6 up, in that order. - Foreground only. A mini app runs only while it is on screen. When it comes on screen, Kamoji starts a fresh, sandboxed Lua interpreter for it, builds its widgets and runs its script; when it leaves, everything is stopped and freed. Nothing carries over from one visit to the next.
- Kamoji re-evaluates the mini app's bindings 10 times a second and redraws a widget only when its value changed. Sensor values are refreshed at the same rate.
- The screen is a 240 × 240 px round display on a black background. Anything outside the circle of radius 120 around (120, 120) is cut off.
Folder layout
my-app/
manifest.json required: id, name, version, settings, data sources
layout.json optional: the widgets and what they show
main.lua optional: script with functions and event handlers
config.json optional: current values of the settings (Kamoji writes it)
| File | Size limit | Notes |
|---|---|---|
manifest.json | 16 KB | See Manifest. A missing or broken manifest makes the mini app unavailable |
layout.json | 128 KB | See Layout and Widgets |
main.lua | 128 KB | See Expressions and Lua |
config.json | 16 KB | Written when the user changes a setting. See settings |
A file over its limit is ignored as if it were missing, so keep them well
under. The folder name must be exactly the mini app's id.
Your first mini app
A counter: the top tap adds one and plays a click, a top hold resets it, and every bump in the road adds one too.
hello-counter/manifest.json
{
"id": "hello-counter",
"name": "Hello Counter",
"version": "1.0.0",
"author": "Your Name",
"api_version": 1,
"permissions": ["events.drive", "touch"],
"params": [
{ "key": "label", "type": "string", "label": "Caption", "default": "taps and bumps" }
]
}
hello-counter/layout.json
{
"widgets": [
{ "type": "label", "font": "huge", "align": "center", "y": -12, "text": "{{ state.n }}" },
{ "type": "label", "font": "small", "align": "center", "y": 58, "color": "grey",
"text": "{{ param.label }}" }
],
"on": {
"top_tap": "state.n = state.n + 1; kamoji.play('touch_single')",
"top_hold": "state.n = 0"
}
}
hello-counter/main.lua
state.n = 0
function on_bump(magnitude)
state.n = state.n + 1
end
Zip the contents of the folder, so manifest.json sits at the root of the
zip, and install it with Install from file in the Kamoji app (see
Sideloading). Tap right past the last built-in mode
and your counter is there.
Debugging
print(...)in Lua writes a line to Kamoji's log, taggedapp.lua. Errors in expressions and handlers are logged too, taggedapps, with the app id. You can read the log over USB with ESPHome's logger (see Firmware).- An expression that fails shows
—in its label and leaves other properties as they were. The mini app keeps running. - A Lua syntax error in
main.lua, invalid JSON inlayout.json, or 30 errors in a row stops the mini app and shows an error card: its name and the message, in red. Tap left or right to leave it. - A mini app with a broken manifest does not appear as a mode at all;
APPS_LISTreports it withok= 0. - To jump straight to your mini app, set Kamoji's mode to its number (6 and
up) with
SET_MODEover Bluetooth or theui_modesetting on Kamoji's web page.
Publishing to the Mini Apps store
When your mini app is ready for everyone, submit it at the Kamoji developer portal, developer.kamoji.bot:
- Sign in with your email: you get a sign-in link, no password needed.
- Upload the same
.zipyou sideload (the same bundle rules apply), with a short summary, a description and up to six screenshots. - The Kamoji team reviews every submission before it appears in the Mini Apps store. You get an email when it is approved, or when the team asks for changes.
From the portal you can also send a new version, change your app's store listing (name, summary, description, screenshots, icon: each change is reviewed again), remove your app from the store at any time, and see how many people viewed and installed it.
Coming later
The platform is new, and some of what it is designed to do is not built yet. None of the following works today; do not rely on it:
- Your own images and GIFs from an
assets/folder (only Kamoji's built-in images work), your own fonts, and free drawing (ui.draw,ui.canvas). - Saving data between visits (
store, a writabledata/folder). - Building widgets from Lua (
ui.*). - Data from the phone and HTTP polling as data sources; only MQTT works today.
- Built-in filters (
derived: moving averages, peak hold and so on). Write them in Lua for now. - More sensor values and events: microphone, tilt angles, light in lux, idle, bumpy road, Wi-Fi and phone events.
- Enforcement of every permission (today only
net.mqttis checked), themin_firmwarecheck, and enabling, disabling and ordering mini apps.