Skip to content

Popup Spec

Roy Padina edited this page Oct 23, 2026 · 2 revisions

Popup Spec

With the ui permission, an action can return {popup: spec}. NtfyBar draws it with its own native popup, labelled with the topic and the plugin's name. Plugins never get a web view. Canonical text: docs/popup-spec.md.

return {
  popup: {
    title: "Deploy finished",          // required, up to 200 characters
    icon: "checkmark.seal",            // optional SF Symbol name
    accent: "success",                 // info (default) | success | warning | critical
    timeoutSec: 30,                    // optional, 0 to 600; 0 or missing = stays
    position: "topRight",              // optional (1.1+): topCenter | topRight; missing = the topic's setting
    level: "overFullScreen",           // optional (1.1+): floating | overFullScreen
    blocks: [
      { text: "Build **#482** is live." },                     // markdown, up to 4096 characters
      { kv: [["Branch", "main"], ["Took", "3 m 12 s"]] },       // table, up to 50 rows
      { progress: 0.75, label: "Rollout 75 %" },                // 0 to 1
      { badge: "Production" }                                   // up to 40 characters
    ],
    buttons: [                         // up to 3
      { id: "ok", label: "Got it", style: "prominent" },        // default | prominent | destructive
      { id: "rollback", label: "Roll back", style: "destructive" }
    ],
    state: { build: 482 }              // any JSON up to 64 KB, handed back to onPopupAction
  }
};

Rules

  • Unknown keys are ignored, so newer specs load in older NtfyBar versions.
  • Wrong types, out-of-range values or too many blocks or buttons make the whole popup an error (logged, nothing shown).
  • At most 20 blocks. A block with no known key is skipped.
  • Button id: letters, digits, _ and -, up to 40 characters, unique in the popup. Labels up to 40.
  • NtfyBar always adds a Dismiss button. If no button is prominent, the first one is.
  • Markdown links in text blocks open only if they are http/https.

Buttons

function onPopupAction(ctx, buttonId, state) {
  // ctx: the message that triggered the popup; state: what you returned in the spec
  if (buttonId === "ok") return { close: true };
  return { popup: { title: "Are you sure?", buttons: [{ id: "yes", label: "Yes" }], state: state } };
}

Return undefined or {close: true} to close, or {popup: spec} to replace the content in place. Without an onPopupAction function every button just closes the popup.

Example

com.ntfybar.ack-button shows a popup with an ACK button and publishes a reply when pressed.

Clone this wiki locally