Skip to content

The app manifest

hub-app.json in the app folder tells the hub how to run the app and what it offers. The hub reads it at startup, before the app runs.

{
"manifest": 1,
"id": "board",
"name": "Board",
"icon": "layout-grid",
"run": { "entry": "server.js", "defaultPort": 4560 },
"loading": { "verbs": ["Laying out the board…"] },
"publishes": ["board.selected"],
"actions": {
"handles": {
"board.open": { "params": { "session": "string" }, "url": "?session={session}", "mode": "message" }
}
},
"provides": {}
}
Field Required Meaning
manifest Yes The format version. Now 1
id Yes The app id, ^[a-z][a-z0-9-]{0,31}$. Must be the id of the apps entry. hub is reserved
name No The tab name. Default: the id
icon No A Lucide icon name
run.entry Yes The server script, relative to the app folder. Must be inside the folder. A path into node_modules is allowed
run.defaultPort No The first choice for the proxy port. See Ports
loading.verbs No Lines for the hub’s loading screen while the app loads
publishes No The topics the app publishes. See Topics
actions.handles No The actions the app handles. See Actions
provides No The capabilities the app provides. See Capabilities

Each key of actions.handles is an action name, <noun>.<verb or view> in lowercase, for example session.cost. Use your app id as the prefix for an action that only your app has.

Field Meaning
params Param names and types. string is required, string? is optional
url A path and query on the app’s origin, with {name} for each param, for example ?session={session}. No #
mode url (default): the hub loads the URL. message: the hub sends the action to the live page, and loads the URL only when the page is not live

With mode: "message", the app must call hub.handle(name, fn) for the action. See Handle an action.

A capability is a job that one app does for the hub. For each capability, the first enabled app in tab order that declares it is the provider.

Capability Field The provider’s route answers The hub uses it for
projects path [{path, modifiedAt}] The project list in the project palette (Ctrl+Alt+P)
terminal liveWork {sessions: [...]} Keeping a set of apps alive while it has open terminals. The provider also gets the terminal env and token

Each field is a path on the provider’s own origin that starts with /. With no provider, the capability is off: no terminal, and the palette has no project list.

The hub skips the app, with a log line, when:

Log reason Cause
not found No hub-app.json in the folder
unknown manifest version ... manifest is not 1
id ... does not match ... id breaks the id rule
id "<a>" is not "<b>" id is not the id of the apps entry
run.entry is missing No run.entry
run.entry is outside the app directory run.entry points outside the folder, or at the folder itself
provides.<cap>.<key> is not a path A capability path does not start with /
publishes topic ... does not match ... A topic breaks the topic rule
publishes topic "<t>" is the hub's project.changed, theme.changed or a hub.* topic

The hub skips one action, and keeps the app, when the name starts with hub., url has a # or is not a string, mode is not url or message, or a param type is not string or string?.

For the ids, ports, topics, actions and capabilities of the four built-in tools, see The built-in tools.