Nuvaka › Developer docs
Nuvaka Apps developer documentation
Add your own app to Nuvaka General App: a UI built with HTML, CSS and JavaScript, an optional background script, and Nuvaka data (notes, cloud files, clipboard pool, mail…) to the extent the user allows. Users install your extension in the app from Apps › Store.
What Nuvaka Apps is
- Package: an extension is a
.nvxfile (ZIP) with thenuvaka.jsonmanifest at its root. Its ID has the form<your-username>.<name>, e.g.tarikgkhsn.faturaci, and never changes once published. - UI: an HTML page opened in a sandboxed frame (iframe). Every entry in the manifest's
pagesshows up in the Apps menu under the publisher heading. The app always shows an info bar above the frame (name, version, trust badge, publisher, Permissions, Stop). - Background: an optional single-file JavaScript module. It runs in the QuickJS engine, separately for each extension, and wakes up on schedules (
every 15m,daily 09:00…) and events (app.started,notes.changed…). - The
nuvakaobject: the app injects a globalnuvakaobject into every frame and background script; no library needed. The@nuvaka/extension-sdkpackage only adds TypeScript types, typed error classes and a mocknuvakafor tests. - Permissions: an extension can only use what it asks for in its manifest and the user grants. Critical permissions such as mail, connection passwords and writing to Nuvaka files are confirmed again on every use. See Concepts.
- Data: every extension gets its own key-value storage on the server (no permission needed, quota up to 100 MB). It syncs across devices and every write carries the version it read (MVCC).
- Platforms: extensions currently run in the desktop app (Windows, Linux, macOS).
Your first extension in 10 minutes
You need Node.js 20 or newer, a Nuvaka account with a verified email and the desktop app.
- Scaffold
npm create @nuvaka/extension hello -- --username your-username --ui --background cd hello npm install--usernameis your Nuvaka username; the ID becomesyour-username.hello. Created files:nuvaka.json,icon.svg,index.html,app.js,style.css,background.js,test/extension.test.js,package.json. Without--uior--backgroundyou get both. - Check
npx nuvaka-ext lintThe same rules the server applies on upload: manifest schema, file types, forbidden code patterns, and whether the
nuvaka.*namespaces used in code match the permissions. Details: Security rules. - Try it in the app
In the app, open Profile and, on the Profile tab under Developer, tick Developer mode. Then use Apps › Manage apps › Load from folder and pick your extension folder. The folder runs unsigned and only on this device; its version shows as
devand every permission in the manifest counts as granted. After a change, use the Reload button in the list.npx nuvaka-ext devdevwatches the folder and runs lint on every change. If you run the app from source (debug build), it also prints theNUVAKA_EXT_DEV_DIRcommand that loads the folder at startup.Server endpoints need an installIn an extension loaded from a folder, local capabilities work (UI,
net,files, local clipboard,ui.notify). Server endpoints such as storage, notes, clipboard pool and push only work if the extension is installed on your account: publish a version and install it to try them. - Get a developer token and sign in
Create a token under Profile › Developer › Developer tokens (starts with
nvd_, shown once, valid for 1 year).npx nuvaka-ext login --token nvd_xxxxxxxx npx nuvaka-ext whoami - (Recommended) Publisher signing key
npx nuvaka-ext keys createAdd the printed public key under Profile › Developer › Publisher signing keys. From then on every upload must be signed; even a stolen token cannot publish a version without the key.
- Publish
npx nuvaka-ext publish --changelog "First version"The result is
published,revieworrejected. A publisher's first extension goes to review; once approved it appears in the Store. See Publishing and review. - Install
Find your extension in Apps › Store and install it. The install syncs to all devices on your account.
First code
In the UI, nuvaka.ready resolves once the shell connects and gives you the context (page, locale, theme). Frames have no localStorage; use nuvaka.storage for persistent data.
// app.js (UI)
const out = document.getElementById('count')
nuvaka.ready.then(async () => {
const r = await nuvaka.storage.get('count') // { value, version } | null
out.textContent = r ? r.value : 0
})
document.getElementById('inc').onclick = async () => {
// Read → modify → write with the version read; retries with the current value if another device got in between
const r = await nuvaka.storage.update('count', (n) => (n || 0) + 1)
out.textContent = r.value
}
// Another device or the background wrote (only newer versions arrive)
nuvaka.storage.onChanged((key, c) => { if (key === 'count' && !c.deleted) out.textContent = c.value })
// background.js (QuickJS; single file, no imports)
nuvaka.on('schedule', async ({ schedule, at }) => {
await nuvaka.ui.notify('Hello', `Scheduled task ran (${schedule})`)
})
Documentation
nuvaka.json field and its rules.
PermissionsEach permission, its value, risk class and the text users see.
API referencenuvaka.* calls, response shapes, events and errors.
CLInuvaka-ext commands, options and environment variables.
Publishing and reviewTokens, signing keys, scan, review, verified badge, yanking.
Security rulesPackage limits and the patterns lint rejects.
ExamplesFive example extensions with code excerpts.
Versions
These docs cover API v1; the manifest says "apiVersion": 1. A breaking change comes with a new API version. The major version of the @nuvaka/extension-cli and @nuvaka/extension-sdk packages is the API version they support (1.x = API v1).
Nuvaka Apps API v1 · last updated 2026-09-27