Emberdocs
humans.md

Build applets

Build an Ember applet

An Ember applet is a small web app that runs inside Ember. You write HTML, CSS, and JavaScript, describe the app in applet.json, then sign and package it as a .ember-applet file.

You need Node.js 22 or newer and a local checkout of the Ember repository. The complete author kit lives in docs/applets. Read the applet specification before building. It is the source of truth for manifests, package limits, security rules, and every window.ember API. The folder also includes v1 and v2 JSON schemas, TypeScript types, a key tool, a package tool, and a WASI backend template.

Make the applet#

Create a folder with these files:

my-applet/
  applet.json
  index.html
  app.js
  styles.css

Put this in applet.json:

{
  "manifestVersion": 1,
  "id": "com.example.hello",
  "name": "Hello Ember",
  "description": "My first Ember applet.",
  "version": "1.0.0",
  "entry": "index.html",
  "icon": "applet"
}

The ID must use reverse-domain form, such as com.example.hello. Keep it stable once people install your applet. Ember uses it to identify updates and to separate each applet's data.

Add a page in index.html. Load Ember's SDK before your application script. The SDK supplies window.ember; remote and inline scripts are blocked.

<!doctype html>
<html lang="en">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Hello Ember</title>
  <body>
    <h1>Hello from my applet</h1>
    <script src="/_ember/sdk.js"></script>
    <script src="app.js"></script>
  </body>
</html>

Then add any browser-side behavior in app.js. Bundle every script, stylesheet, font, and image with your applet. Ember does not allow inline or remote scripts.

Use Ember APIs#

Applets cannot call Tauri or native system APIs. Ember adds a small window.ember API when an applet declares a supported permission or capability.

For example, add storage to the manifest:

"permissions": ["storage"]

Then use it from app.js:

await window.ember.storage.set("greeting", "Hello Ember");
const greeting = await window.ember.storage.get("greeting");
console.log(greeting);

Each applet has its own 5 MB JSON store. Declare only what the applet needs. Version 2 manifests add native HTTP, browser networking, credentials, OAuth, external links, fullscreen, workers, a guest terminal, trusted extension calls, and optional WASI backends. Use manifest version 2 when you need any of those features. It requires a capabilities object and does not use version 1's permissions array.

Copy docs/applets/ember.d.ts into a TypeScript project for SDK types. The applet specification gives an example and limits for every capability, including network origins, request headers, credential placement, and backend execution.

Sign and package it#

Keep your private key outside the applet folder. From the Ember repository root, create a development key once:

npm run applet:key -- ../ember-dev-key.pem

Package the applet:

npm run applet:pack -- path/to/my-applet ../ember-dev-key.pem

This writes com.example.hello-1.0.0.ember-applet. The packager hashes the applet's files and signs those hashes. Do not edit the package after it is created.

Test it in Ember#

Open Ember, choose Library, and select the .ember-applet file. Ember verifies its contents and signature, then shows its identity and requested capabilities before installing it. Launch it from the Library.

For a fuller working example, inspect applets/notes in the Ember repository. It includes a manifest, local UI files, storage, and applet settings. If you use an AI coding agent, give it the whole docs/applets directory and the instructions in the AI agent guide.

This page is rendered from humans.md. Agents should read that file directly.