Nuvaka › Developer docs › Manifest (nuvaka.json)

Manifest: nuvaka.json

nuvaka.json at the package root describes the extension. The server, the app and nuvaka-ext lint apply the same rules. Unknown fields are rejected.

Example

{
  "id": "tarikgkhsn.github-watcher",
  "name": "GitHub takipçisi",
  "version": "0.1.0",
  "apiVersion": 1,
  "description": {
    "tr": "Seçtiğin GitHub depolarının yeni sürümlerini saatte bir denetler ve yeni sürüm çıkınca tüm cihazlarına ya da yalnız bu cihaza bildirim gönderir.",
    "en": "Checks the GitHub repositories you choose for new releases every hour and notifies all your devices, or only this one, when a new release appears."
  },
  "storeCategory": "developer",
  "icon": "icon.svg",
  "entry": { "ui": "index.html", "background": "background.js" },
  "pages": [
    { "id": "releases", "title": { "tr": "Sürümler", "en": "Releases" } }
  ],
  "permissions": [
    { "net": ["api.github.com"], "reason": { "tr": "Depoların son sürümünü GitHub API'den okumak için", "en": "To read the latest release of each repository from the GitHub API" } },
    { "nuvaka.push": true, "reason": { "tr": "Yeni sürümü tüm cihazlarına bildirmek için", "en": "To announce a new release on all your devices" } },
    { "notifications": true, "reason": { "tr": "Yeni sürümü yalnız bu cihazda bildirmek için", "en": "To announce a new release on this device only" } },
    { "background": true, "reason": { "tr": "Sürümleri saatte bir, sayfa kapalıyken de denetlemek için", "en": "To check releases every hour, even when the page is closed" } }
  ],
  "storage": { "quotaMB": 1 },
  "triggers": [{ "schedule": "hourly" }, { "event": "network.online" }],
  "settings": [
    { "key": "repos", "type": "string", "label": { "tr": "Depolar (sahip/ad, virgülle ayır)", "en": "Repositories (owner/name, comma separated)" }, "default": "tauri-apps/tauri, nodejs/node" },
    { "key": "channel", "type": "select", "label": { "tr": "Bildirim", "en": "Notification" }, "default": "push", "options": ["push", "local", "none"] }
  ]
}

Source: examples/apps/github-watcher/nuvaka.json

Fields

FieldTypeRequiredRule
idstring✓<publisher>.<name>; publisher [a-z0-9][a-z0-9_-]{1,31}, name [a-z0-9][a-z0-9-]{1,39}
namestring✓2–40 characters
versionstring✓semver x.y.z, no prefix; every upload greater than the previous one
apiVersioninteger✓1
minAppVersionstringsemver; the lowest Nuvaka app version the extension needs
description{ tr, en? }✓tr required; each 1–300 characters
storeCategorystring✓productivity, developer, files, communication, finance, media, games, system, education, other
iconstring✓path of an .svg or .png in the package
homepagestringhttps:// URL, 8–300 characters
entry{ ui?, background? }✓at least one; file paths in the package (ui: .html/.htm, background: .js/.mjs)
pagesarray✓ if entry.ui1–10 pages: { id, title: { tr, en? }, icon? }
permissionsarrayat most 30; each item is one permission + reason
storage{ quotaMB }1–100 MB; default 10
shared{ exports?, imports? }sharing between extensions
triggersarrayat most 10; needs entry.background
settingsarrayat most 30 settings
$schemastringfor editors; ignored

Localized texts use the { "tr": "…", "en": "…" } form; tr (Turkish) is always required.

id

The publisher prefix is the uploading account's username (lower case) and is enforced by the server: nobody else can publish with your prefix. The ID never changes once published, even if the name does.

version and minAppVersion

Only x.y.z (e.g. 1.4.0); no v prefix, no -beta suffix. You cannot upload the same or a lower version. minAppVersion is the lowest Nuvaka app version the extension requires.

entry and pages

entry.ui is the UI's HTML file and entry.background the background script. Both must be in the package.

  • pages is required when entry.ui is present. Every page is an item in the Apps menu under the publisher heading; all of them open the same HTML file. The open page comes in the nuvaka.ready context (ctx.page) and nuvaka.ui.onPage(fn) fires when it changes.
  • Page id: [a-z0-9][a-z0-9-]{0,29}, unique. title: { tr, en? }, at most 40 characters each. icon: optional icon name, up to 40 characters.
  • entry.background requires the background permission.

permissions

Each item holds exactly one permission key and a reason. The reason is shown on the install screen: { tr, en? }, 1–200 characters each.

"permissions": [
  { "files": "read", "reason": { "tr": "Seçtiğin klasördeki dosyaları okumak için", "en": "To read files in the folder you pick" } },
  { "files": "write", "reason": { "tr": "Düzenlenen dosyayı kaydetmek için", "en": "To save the edited file" } },
  { "net": ["api.github.com"], "reason": { "tr": "Sürümleri GitHub'dan okumak için", "en": "To read releases from GitHub" } },
  { "notifications": true, "reason": { "tr": "Yeni sürümü bildirmek için", "en": "To announce a new release" } }
]
  • The same scope cannot appear twice. files: read and files: write are separate scopes and may both be requested.
  • net: 1–20 full host names, lower case. *, IP addresses, localhost and names ending in .local/.localhost/.internal are not accepted.
  • The shared permission is not written in the manifest; it is added automatically when shared.imports is present.
  • Storage needs no permission; every extension has its own space.

All permissions, their values and risk classes: Permissions reference.

storage

"storage": { "quotaMB": 25 }

An integer from 1 to 100; default 10 MB. The quota is per user and per extension. See Quota.

shared

Extensions can expose named values to each other. Names are [a-z0-9][a-z0-9-]{0,29}.

"shared": {
  "exports": [{ "name": "rates", "description": { "tr": "Günlük döviz kurları", "en": "Daily exchange rates" } }],
  "imports": [{ "from": "tarikgkhsn.faturaci", "name": "customers" }]
}
  • exports: the names this extension may write with nuvaka.shared.set(name, …), with a description shown to the user ({ tr, en? }, ≤ 200).
  • imports: values to read with nuvaka.shared.get(from, name). Reading requires the user to grant the shared permission and the source extension to be installed.

triggers

Events that wake the background script. Requires entry.background. Each item is either { "schedule": … } or { "event": … }.

Schedules

FormMeaning
every Nmevery N minutes; 15 ≤ N ≤ 1440 (e.g. every 15m, every 360m)
hourlyevery hour
daily HH:MMevery day, local time (e.g. daily 09:00)
weekly mon HH:MMonce a week; day mon tue wed thu fri sat sun

When it fires, nuvaka.on('schedule', ({ schedule, at }) => …) runs in the background; schedule is the manifest text and at the firing time (unix seconds). A schedule missed while the app was closed fires once at the next start.

Events

EventWhenPermission needed
app.startedwhen the background starts (app start)—
app.focusedwhen the app window gets focus—
network.onlinewhen the network comes back—
notes.changedwhen notes changenuvaka.notes: read
cloud.fileAddedwhen a file is added to Nuvaka cloudnuvaka.cloud: read
mail.receivedwhen mail arrivesnuvaka.mail: read
clipboard.addedwhen an item is added to the clipboard poolnuvaka.clipboard: read

Server-originated events are not delivered unless the matching read permission is granted. The payload does not contain the change itself; read the data again through the API.

settings

Settings the user can change. The app draws the settings screen; values are the same across devices and are read with nuvaka.settings.get() (default when the user has not set a value).

FieldRule
key1–40 characters
typestring, number, bool, select
label{ tr, en? }, ≤ 80 each
defaultdefault value
optionsarray of choices; required for select
"settings": [
  { "key": "greeting", "type": "string", "label": { "tr": "Selamlama", "en": "Greeting" }, "default": "Hello" },
  { "key": "channel", "type": "select", "label": { "tr": "Bildirim", "en": "Notification" }, "default": "push", "options": ["push", "local", "none"] }
]

Extra rules

Rules the JSON schema cannot express but the server and lint enforce:

  • entry and icon paths must exist in the package.
  • entry.ui requires pages; entry.background requires the background permission; triggers require entry.background.
  • every Nm requires 15 ≤ N ≤ 1440.
  • The same permission scope cannot appear twice.
  • The id prefix must be the uploading account's username.
  • net hosts cannot be .local, .localhost or .internal.

Nuvaka Apps API v1 · last updated 2026-09-27