| name | zepp-os-fundamentals |
| description | Use for Zepp OS project setup and structure decisions - editing app.json (manifest, permissions list, module entries, API_LEVEL, targets, designWidth, assets), deciding where code belongs (device app vs side service vs settings app vs app-service vs watchface module), supporting round + square device targets, scaffolding or laying out a new Mini Program or Watchface project, or explaining the four runtime contexts. Use whenever the question is "where does this code go", "what goes in app.json", "what permission do I declare in app.json", "how do I target this device", "how is a watchface project laid out vs a regular app", or "what's the difference between the device app and the side service". Do not use for runtime permission requests at execution time (zepp-os-app-control), for the implementation inside a specific module (use the topic skill), or for zeus CLI commands (zeus-cli). |
Zepp OS Fundamentals
Context: all four runtimes (this skill defines them)
API_LEVEL: 2.0+ (the API_LEVEL system itself is a 2.0 concept)
Overview
A Zepp OS project is one package containing up to four separate programs, wired together in app.json. Each runs in a different place with a different API surface — mixing them up is the #1 source of errors. The API is versioned by API_LEVEL (not OS version): you target a minimum API_LEVEL and the system guarantees newer firmware stays backward-compatible.
The four runtime contexts
| Context | Runs on | app.json module key | Entry | API surface |
|---|
| Device App (Mini Program) | the watch | page | page/**/index.page.js | @zos/* |
| Watchface | the watch | watchface | watchface entry | @zos/* (+ legacy hmUI/hmSensor) |
| Side Service (companion) | the phone (Zepp app, background JS) | app-side | app-side/index.js | messaging / fetch / transfer (no @zos/ui) |
| Settings App | the phone (Zepp app, settings UI) | setting | setting/index.js | Settings UI components + settings-storage |
Plus optional modules: app-service (Background Service, configVersion v3), app-widget/secondary-widget (shortcut cards and secondary widgets), app-event (System Event Listening, configVersion v3).
Rule of thumb: UI on the watch → device app. Network/HTTP → side service (the watch has no direct internet; it goes through the phone). A configuration screen the user sees in the Zepp phone app → settings app.
API_LEVEL
- A string
"major.minor" compared left-to-right: 3.1 > 3.0 > 2.98 > 2.1 > 2.0. Introduced in Zepp OS 2.0.
- You declare the minimum you need in
app.json → runtime.apiVersion.minVersion. The app runs on any firmware whose API_LEVEL ≥ minVersion.
- Forward-compatible: higher-
API_LEVEL (newer) devices run apps built for a lower level. Pick the lowest level that has the APIs you need to reach the most devices.
- Every API in the docs is tagged with its
API_LEVEL; tags can apply to a single parameter/field, not just the whole method.
- 1.0 caveat: Zepp OS 1.0 devices do not support
API_LEVEL at all — apps built on the 2.0+ JS API will not run on them (and aren't distributed to them).
In this library, features are tagged inline like [≥4.0] = needs API_LEVEL 4.0 or higher. Example: direct widget property access via . getter/setter is [≥4.0]; before that use getProperty/setProperty.
Project structure
.
├── app.json # global config (see below)
├── app.js # Mini Program global logic (app lifecycle)
├── page/ # DEVICE APP pages — one dir per page recommended
│ └── home/
│ ├── index.page.js # page logic
│ └── index.layout.js # style (separated for screen adaptation)
├── app-side/index.js # SIDE SERVICE (companion) entry
├── setting/index.js # SETTINGS APP entry
├── app-widget/index.js # shortcut card (optional)
├── secondary-widget/index.js# watchface complication (optional)
├── assets/<target>/ # per-device resources; subdir name = targets key in app.json
│ └── image/ fonts/ icon.png
├── i18n/ # app-level ${key}.po files (en-US.po, …)
│ # Per-module i18n is also supported: page/i18n/, app-side/i18n/, setting/i18n/
└── utils/
Separate style into *.layout.js from page behavior in *.page.js — this is where screen adaptation lives.
app.json essentials
{
"configVersion": "v3",
"app": { "appId": 1000089, "appName": "...", "appType": "app",
"version": { "code": 5, "name": "0.0.5" }, "vender": "...", "description": "..." },
"runtime": { "apiVersion": { "minVersion": "3.0", "compatible": "3.0", "target": "3.0" } },
"permissions": ["device:os.bg_service"],
"targets": {
"gtr-3-pro": {
"module": { "page": { "pages": ["page/home/index"] }, "app-side": { "path": "app-side/index" } },
"platforms": [{ "name": "gtr-3-pro" }],
"designWidth": 480
}
},
"i18n": { },
"defaultLanguage": "en-US"
}
targets distinguishes per-device builds; each key must match an assets/<key>/ subdir.
designWidth + the px() helper (see zepp-os-ui) is the core of multi-screen adaptation.
- Permissions are declared in
permissions[] and can be requested at runtime via @zos/app requestPermission/queryPermission; see references/permissions.md for confirmed codes used in this library.
Common Mistakes
- Calling
@zos/ui from the side service or settings app → those run on the phone and have no device UI. UI lives only in the device app/watchface.
- Trying to
fetch() from the device app → the watch has no direct internet. Do HTTP in the side service and pass results to the device via messaging (see zepp-os-communication).
- Setting
minVersion too high → excludes older devices. Use the lowest API_LEVEL that has the APIs you actually use.
assets/ subfolder name ≠ targets key → resources won't resolve.
- Expecting a 2.0+ app to run on Zepp OS 1.0 → it won't; 1.0 has no
API_LEVEL.
- Using configVersion v3 modules (
app-service, app-event) with configVersion other than v3 → they won't load.
Reference