Skip to main content

Manifest and Settings

manifest.json tells Kamoji what a Kamoji Mini App is, what it uses, which settings it has and where its data comes from. It is the only required file.

{
"id": "mqtt-value",
"name": "MQTT Value",
"version": "1.0.0",
"author": "Your Name",
"api_version": 1,
"min_firmware": "0.1.80",
"permissions": ["net.mqtt", "touch"],
"params": [
{ "key": "broker", "type": "string", "label": "Broker",
"default": "mqtt://broker.hivemq.com:1883" },
{ "key": "topic", "type": "string", "label": "Topic", "default": "kamoji/demo/value" }
],
"sources": [
{ "id": "v", "type": "mqtt", "broker": "{{param.broker}}", "topic": "{{param.topic}}" }
]
}

Fields​

FieldRequiredMeaning
idYesThe mini app's id: lowercase letters, digits and -, starting with a letter or digit, 2 to 40 characters. It must equal the folder name, and is unique on a Kamoji. Mini apps appear in alphabetical order of their ids
api_versionYesMust be 1. A mini app with another value is not run
nameNoShown in the Kamoji app and on the error card. Defaults to the id
versionNoYour version, e.g. 1.0.0 (use semver). Reported by APPS_LIST and after an install
authorNoYour name
min_firmwareNoThe oldest firmware the mini app needs, e.g. "0.1.80". Kamoji does not check it yet
permissionsNoWhat the app uses (below)
paramsNoThe app's settings (below)
sourcesNoData sources: MQTT topics. See MQTT and Data
side_tapsNo"app" to use single left/right taps in the mini app instead of switching modes. See Side taps
platformsNoPhones the mini app works with: ["android"], ["ios"] or both (the default). The Kamoji app only lists it, and only installs it from a file, on those phones. Navigation is ["android"] (it reads Android notifications)

If manifest.json is missing, over 16 KB, not valid JSON, has an id that is not the folder name, or an api_version other than 1, the mini app is listed as unavailable and does not appear as a mode.

Side taps​

Normally a single tap on Kamoji's left or right side switches to the previous or next mode, and a mini app never sees it. A game or anything else that needs two buttons can take these taps over:

"side_taps": "app"

While such a mini app is on screen:

  • a single left / right tap calls on_left_tap() / on_right_tap() in your Lua (needs the touch permission);
  • tapping and holding left or right (about 0.6 s) switches to the previous / next mode instead;
  • when the mini app opens, Kamoji shows "Hold left / right to switch" for 3 seconds, so users know how to leave.

Settings, sleep and the left + right squeeze work as usual. The Snake example uses this.

Permissions​

List everything your mini app uses. The Kamoji app shows the permissions in plain words before an install.

PermissionAllows
sensors.imuThe motion sensor: the imu and drive groups
sensors.lightThe light sensor: the light group
sensors.micThe microphone (coming later)
sensors.envThe temperature: the env group
sensors.obdOBD-II car data: the obd group (firmware 0.2.2+). Kamoji also keeps the paired adapter polled while the mini app is on screen
events.driveDriving events: bump, hard_brake, hard_accel, lean
events.deviceDevice events (coming later)
touchTop tap, top hold and pinch
net.mqttMQTT sources and the mqtt.* Lua functions
net.httpHTTP sources (coming later)
net.phoneData from the phone (coming later)
phone.navigationTurn-by-turn navigation from the phone: the nav group and builtin:nav_icon / builtin:nav_icon_large. On Android the Kamoji app forwards Google Maps; it asks the user for notification access only once a mini app with this permission is installed
note

Today Kamoji enforces net.mqtt (without it, MQTT sources are skipped and mqtt.publish / mqtt.subscribe raise an error), phone.navigation (without it, the nav group stays empty) and sensors.obd (without it, the obd group stays empty). The other permissions will be enforced later, so declare them now; a mini app that relies on a missing one will stop working.

Settings (params)​

params lists the mini app's settings. The Kamoji app draws a Settings form for every installed mini app from this list, so users can change them without touching any file. On Kamoji, the current values live in the app's config.json, and your expressions and Lua read them as param.<key>.

The clock's time zone (utc_offset), the Excite-O-Meter's sounds switch and the MQTT mini app's broker and topic in the examples are settings users change this way.

"params": [
{ "key": "utc_offset", "type": "number", "label": "UTC offset (hours)",
"help": "8 for Singapore, -5 for New York", "default": 8, "min": -12, "max": 14, "step": 0.25 },
{ "key": "show_seconds", "type": "bool", "label": "Show seconds", "default": true },
{ "key": "label", "type": "string", "label": "City", "default": "Singapore" },
{ "key": "units", "type": "enum", "label": "Units", "options": ["kmh", "mph"], "default": "kmh" },
{ "key": "accent", "type": "color", "label": "Accent colour", "default": "#64D2FF" },
{ "key": "token", "type": "secret", "label": "API token", "optional": true }
]
FieldMeaning
keyRequired. The name in param.<key> and in config.json. Use letters, digits and _ so it works as a Lua name
typeRequired. One of the types below
labelThe name shown in the form. Defaults to the key
helpA hint line shown under the field
defaultThe value until the user changes it
min, max, stepnumber only: the allowed range and step of the stepper or slider
optionsenum only: the allowed values, as strings
optionaltrue when the setting may be left empty (cleared back to its default)
TypeForm fieldValue in LuaAccepted values
numberStepper or slidernumberWithin min / max
boolSwitchtrue / falsetrue, false
stringText fieldstringAny text
enumPickerstringOne of options
colorSwatches and hexstring, e.g. "#64D2FF"#RGB or #RRGGBB
secretPassword fieldstringAny text; can be cleared

Hiding the Wi-Fi icon (hide_wifi)​

A bool setting with the key hide_wifi is reserved: when it is true, Kamoji hides its Wi-Fi icon and network name at the top of the screen while your mini app is showing, and brings them back when it leaves. Add it to params so users can choose (every Originally US mini app has it):

{ "key": "hide_wifi", "type": "bool", "label": "Hide Wi-Fi icon", "default": false,
"help": "Hide the Wi-Fi icon and network name at the top of the screen while this app is showing" }

Set "default": true if your layout needs the top of the screen to itself. Kamoji's own WiFi Display setting still applies: if it is set to None, the icon is hidden anyway.

How values reach your app:

  • When the mini app comes on screen, Kamoji fills the param table: the value from config.json if there is one, else default. A setting with neither is nil, so write param.token or "" for optional ones.
  • color values work directly in colour properties: "color": "{{ param.accent }}".
  • When the user changes a setting, Kamoji validates it against the setting's type (min / max, options, a #RGB or #RRGGBB colour), saves it to config.json in one step and, if the mini app is on screen, restarts it so the change shows at once. Settings never change under a running mini app. Clearing a secret or an optional setting removes it from config.json, so the default applies again.
  • An update of the mini app keeps the user's config.json (and its data/ folder), unless the new bundle ships its own.
  • A secret is stored on Kamoji and never sent back out: the Kamoji app only learns whether it is set. Your mini app reads it as a normal string, for example as an MQTT password.
  • Settings are also usable in manifest strings, such as a source's broker, topic, username and password: "{{param.broker}}".

config.json is a flat JSON object of key to value:

{ "utc_offset": 1, "label": "London", "accent": "#FF9F0A" }

Kamoji writes it; you normally do not ship one. Put your starting values in default instead: a config.json in your bundle replaces the user's settings on every update. Tool builders can read and change settings over Bluetooth with APP_PARAMS and APP_SET.