manifest.json reference

Every widget has a manifest.json at the root of its .nepget bundle. It tells NepTunes how to load and present the widget.

Required fields

Field Type Description
manifestVersion Int Manifest format version. Always 1.
id String Unique identifier in reverse-domain notation, e.g. com.example.my-widget.
name String Display name shown in the widget picker.
version String Semantic version, e.g. 1.0.0.
entry String Entry HTML file, typically index.html.
defaultSize Object Default window size: { "width": Int, "height": Int } in pixels.

Optional fields

Field Type Description
author String Author name.
description String Short description of the widget.
license String License identifier, e.g. MIT.
homepage String Homepage URL.
minSize Object Minimum window size { width, height }. Applies to user resizing and to NepTunes.setSize() alike, whatever resizable says.
maxSize Object Maximum window size { width, height }. Applies to the same paths. Omitting it is not “unbounded” — a widget window is never larger than the display it is on.
resizable Bool Whether the user can resize the widget — by dragging its edges, or a resize handle the widget draws itself. Defaults to true; set it to false for a fixed-size widget.
preview String Preview image filename inside the bundle.
icon String Icon filename inside the bundle.
permissions Array The permissions the widget needs.
settings Object A { "schema": [ … ] } object describing user settings.
minNepTunesVersion String Minimum NepTunes version, e.g. 4.2.0. If it’s newer than the running app, the update is shown as blocked instead of installed.
authorPublicKey String Base64 of your Ed25519 signing key’s public half — 32 raw bytes, no ed25519: prefix. Required when the bundle ships a bundle.sig, and it must equal that file’s authorPublicKey; declaring it without a signature makes the bundle refuse to install. Pinned on first install; a change forces users to re-consent. See Updates & signing.
releaseNotes String What changed in this version. Shown in the update confirmation sheet.

bundle.sig — the manifest’s signature sidecar

A signed bundle carries a second file next to manifest.json: bundle.sig, holding the author’s Ed25519 signature over the SHA-256 hash of every file in the bundle — manifest.json included. You never hand-write it; embed-sign generates it (widget-tools.mjsUpdates & signing explains how to get it and where keygen puts your keys):

node widget-tools.mjs embed-sign MyWidget.nepget \
  --key .keys/my-widget-author.pem
node widget-tools.mjs embed-verify MyWidget.nepget

Two rules tie the two files together, and NepTunes enforces both at install time:

  • manifest.authorPublicKey must equal bundle.sig’s authorPublicKey.
  • A manifest that declares authorPublicKey with no bundle.sig is rejected — claiming an identity without proving it is worse than claiming none.

Because the manifest is itself covered by the signature, any manifest edit (a version bump, a new permission) means re-running embed-sign. The full format, the exact bytes the signature covers, and the verification order are in Updates & signing.

Complete example

This is the manifest from the “Now Playing” widget in the gallery:

{
  "manifestVersion": 1,
  "id": "pl.micropixels.neptunes.widget.now-playing",
  "name": "Now Playing",
  "version": "1.9.0",
  "author": "NepTunes",
  "description": "Displays the currently playing track with playback controls",
  "license": "MIT",
  "homepage": "https://neptunesmac.app",
  "entry": "index.html",
  "defaultSize": { "width": 368, "height": 220 },
  "minSize": { "width": 328, "height": 200 },
  "resizable": false,
  "preview": "preview.jpg",
  "permissions": ["artwork", "playbackControl"],
  "settings": {
    "schema": [
      {
        "id": "showArtwork",
        "type": "checkbox",
        "label": "Show Album Artwork",
        "default": true
      },
      {
        "id": "theme",
        "type": "radio",
        "label": "Theme",
        "options": [
          { "value": "dark", "label": "Dark" },
          { "value": "light", "label": "Light" }
        ],
        "default": "dark"
      }
    ]
  }
}

← Quick startJavaScript API →