Back to Cherry Studio

Mini App Reference

docs/references/mini-app/README.md

2.0.104.0 KB
Original Source

Mini App Reference

A mini app is a static web app shipped as a .miniapp package (a zip with a manifest.json at its root). Cherry Studio installs it locally, serves it from cherry-miniapp://<appId>/ inside a sandboxed <webview>, and exposes host capabilities through one global: window.cherry.

This is the author-facing contract. It describes what you can call, what is enforced, and what will not work — not how the host implements it.

Documents

DocumentRead it when
SandboxFirst. Your code works in a browser and fails here — localStorage, fetch, iframes, popups, navigation
ManifestWriting manifest.json: every field, id rules, permission declarations, network hosts
CapabilitiesCalling cherry.*: signatures, return shapes, errors, quotas and rate limits per method
LifecycleSaving state: the app can be killed at any moment; visibility and locale events; quiesce
ThemingLooking like Cherry: /__cherry/theme.css, the CSS variable contract, dark mode, Tailwind
PackagingShipping: building the archive, install consent, updates, rollback, uninstall
Activity logKnowing what the user sees: which of your calls are recorded, with what metadata, and for how long
cherry.d.tsTypeScript declarations for window.cherry — copy into your project
Runtime probesMaintaining the host: the measurements behind the sandbox layers and how to rebuild each probe when Electron moves
examples/capability-tests/A runnable app that checks every cherry.* method against this reference, permission by permission — zip the directory to install it

Minimal app

mygame.miniapp (zip)
├── manifest.json
├── index.html
└── icon.png
json
{
  "id": "com.example.mygame",
  "name": { "en": "My Game", "zh": "我的游戏" },
  "description": "A tiny sample game.",
  "version": "1.0.0",
  "entry": "index.html",
  "permissions": ["storage.*"]
}
html
<!doctype html>
<link rel="stylesheet" href="/__cherry/theme.css" />
<body>
  <script>
    cherry.storage.get('save').then(({ value }) => {
      const state = value ? JSON.parse(value) : { score: 0 }
      state.score += 1
      return cherry.storage.set('save', JSON.stringify(state))
    })
  </script>
</body>

Three things to know before writing code

RuleConsequence
The page is sandboxed with an opaque origin and no networkWeb Storage, IndexedDB, cookies and every outbound request are blocked. Persist through cherry.storage / cherry.file; reach the network through cherry.network.fetch
Every capability that reaches your data, the network or the user is gated by a manifest declarationUndeclared methods reject with PermissionDenied, and optional permissions can be revoked at any time. Environment reads (app.*) and ai.cancel are ungated and cannot be declared; *.usage and ai.getCapabilities ride on their namespace's grant. See capabilities.md
The host never warns before destroying the appWrite state as soon as it changes. cherry.storage.set and cherry.file.save are committed when they resolve

Where the truth lives

FactSource
Method names and how each is gatedMINI_APP_METHODS in src/shared/types/miniAppManifest.ts — the manifest schema, the consent card and the runtime gate all read this table
The seven error namesCherryErrorName in src/shared/ipc/schemas/miniAppBridge.ts
cherry.d.ts does not drift from the bridgesrc/main/features/miniApp/runtime/__tests__/apiSurface.test.ts asserts the .d.ts, MINI_APP_METHODS and the preload expose the same method set and the same error names

Parameter and return shapes are hand-written in cherry.d.ts and capabilities.md; only the method set and error set are machine-checked.