Nuvaka › Developer docs › In-app store (addons)
In-app store: addons
An extension can open its own addon store: language and theme packs for a code editor, level packs for a game, commands for a tool. Other developers publish the addons; users install them from inside the host app. The Nuvaka store's safeguards (signing, scanning, review, yanking) apply to addons exactly the same way.
Note: The SDK side (nuvaka.addons) arrives with Nuvaka 0.3.1. Store and publishing rules already apply.
Terms
- Host: an extension that accepts addons. Its manifest has an
addonsfield. - Addon: a Nuvaka package whose manifest has
addonOf. There are two kinds:- Data addon (
"addonKind": "data"): runs no code. It is made of JSON, text and images that the host reads and interprets. - Code addon (
"addonKind": "code"): a normal extension with its own page or background script. The host calls the functions itexposes.
- Data addon (
Host manifest
"addons": {
"kinds": ["data", "code"],
"open": true,
"schema": "codeeditor.addon/1",
"maxSizeMB": 5
}
| Field | Rule |
|---|---|
kinds | required; accepted kinds: "data", "code" or both |
open | required; true lets anyone publish addons, false only the host's publisher |
schema | optional; name of the format data addons follow (e.g. codeeditor.addon/1). Documenting it is up to the host. |
maxSizeMB | optional; 1–20. Maximum addon package size (default 20). |
If the addons field is removed or open is turned off, published addons stay; new ones are refused (addons_not_accepted / addons_closed).
Addon manifest
{
"id": "rust-lang-pack",
"name": { "tr": "Rust dil paketi", "en": "Rust language pack" },
"version": "1.0.0",
"addonOf": "code-editor",
"addonKind": "data",
"minAppVersion": "0.3.1"
}
addonOf: the host's id. It cannot change after the first publish. A published normal extension cannot later become an addon.addonKind:dataorcode; must be in the host'skinds(otherwiseaddon_kind_not_accepted).
Data addon rules
- These fields are forbidden:
entry,pages,permissions,storage,shared,triggers,settings,contributes,workers,addons,dependencies. - Only these file types:
json,txt,md,png,jpg,jpeg,webp,svg. SVGs may not contain<script>,on*=attributes,foreignObject,javascript:, oriframe/embed/object. - At most 20 MB (or the host's
maxSizeMB; beyond itaddon_too_large) and 500 files.
Code addon rules
- Must have a required
extendsdependency on the host (Dependencies):{ "id": "<host>", "version": "^x.y.z", "kind": "extends" }. - Permissions are not inherited: a code addon requests its own permissions and the user approves them separately.
- All normal extension rules (lint, scan, review) apply.
Platforms
An addon's platforms set must be within the host's (Platform compatibility); otherwise platform_exceeds_dependency.
Getting started with the CLI
nuvaka-ext init rust-lang-pack --addon-of code-editor --kind data
nuvaka-ext init my-formatter --addon-of code-editor --kind code
Publish as usual with nuvaka-ext publish.
Addons in the store
- Addons don't appear in the Nuvaka store's main lists. They appear in the host's own store tab and on publisher pages.
GET /api/ext/v1/store?addonOf=<host>: a host's addons. Search, sorting and paging work the same.- The host's detail returns
addons: { kinds, open, schema, maxSizeMB, count }.
Install and uninstall
- An addon installs only if the host is installed; otherwise the server returns
409 host_requiredwith{ host }. - The user always confirms installs: even when the host calls
nuvaka.addons.install, Nuvaka shows its own confirmation window. - When the host is uninstalled, Nuvaka offers to remove its addons too. Addon data is kept for 30 days.
Host API: nuvaka.addons
Only a host (an extension with an addons field) can make these calls. store always lists the caller's own addon store; an app can't see another app's store. call doesn't give the host's permissions to the addon.
| Call | Description |
|---|---|
list() | Installed addons: [{ id, version, kind, name, files }] |
read(id, path) | A file from a data addon; Uint8Array |
readText(id, path) / readJson(id, path) | Same, as text or parsed JSON |
call(id, method, arg) | Calls a function a code addon exposes |
store(query) | Returns this host's addon store list |
install(id) | Starts an install; Nuvaka shows the confirmation. cancelled if the user declines. |
uninstall(id) | Starts an uninstall (confirmed) |
onChanged(cb) | Called when an addon is installed, updated or removed |
for (const a of await nuvaka.addons.list()) {
if (a.kind !== 'data') continue
const meta = await nuvaka.addons.readJson(a.id, 'addon.json')
registerLanguages(meta.languages)
}
nuvaka.addons.onChanged(() => location.reload())
Example schema: codeeditor.addon/1
Nuvaka's code editor accepts language, theme and snippet addons. A data addon has addon.json at its root:
{
"schema": "codeeditor.addon/1",
"languages": [
{ "id": "rust", "extensions": [".rs"], "aliases": ["Rust"],
"monarch": "rust.monarch.json", "configuration": "rust.config.json" }
],
"themes": [
{ "id": "ember", "label": { "tr": "Kor", "en": "Ember" }, "base": "vs-dark", "file": "ember.theme.json" }
],
"snippets": [{ "language": "rust", "file": "rust.snippets.json" }]
}
- Theme file:
{ "inherit": true, "rules": [...], "colors": { ... } }. - Snippets use the VS Code format (
prefix,body,description). - A code addon adds commands:
nuvaka.expose('codeeditor.commands', () => [{ id: 'sort-lines', title: 'Sort lines' }])
nuvaka.expose('codeeditor.run', ({ command, text, selection, language, fileName }) => {
const sorted = text.split('\n').sort().join('\n')
return { text: sorted, replace: 'selection', message: 'Sorted' }
})
replace: 'selection' or 'document'. message is optional and shows in the status bar.
Error codes
| Code | Meaning |
|---|---|
addons_not_accepted | The target extension doesn't accept addons |
addon_kind_not_accepted | This kind (data/code) is not accepted |
addons_closed | open: false; only the host's publisher can publish |
addon_too_large | Package exceeds maxSizeMB |
platform_exceeds_dependency | The addon's platforms exceed the host's |
host_required | (409) Install the host first |
| "addonOf değiştirilemez" | A published addon's host can't change |
| "yayındaki uzantı eklentiye dönüştürülemez" | A published normal extension can't become an addon; publish under a new id |
Nuvaka Apps API v1 · last updated 2026-09-28