Skip to content

What are napplets? ​

A napplet is a small, single-purpose Nostr web application that runs inside a sandboxed iframe and delegates everything sensitive — signing, storage, relay access — to a host shell. The shell and the napplet communicate over postMessage using a JSON envelope wire format defined by NIP-5D.

ALPHA

napplet is alpha. The specification is experimental and a moving target. There will most certainly be drift between the packages and the specification. Things will most certainly change. For adventurers only.

The monolith problem ​

Today, every Nostr client re-implements the same machinery from scratch: a feed viewer, a DM inbox, a profile editor, relay management, key handling, signing. The result is a handful of large monolithic clients that each duplicate the same hard, security-sensitive plumbing — and each one is a fresh place for that plumbing to go wrong.

NIP-5D proposes a different shape:

Napplets SHOULD be single-purpose rather than monolithic. The shell composes multiple napplets; napplets don't compose themselves.

Shell + napplets ​

Instead of one client that does everything, you get:

  • A shell — the trusted host application. It brokers signing — to a remote signer (NIP-46), a browser extension (NIP-07), or its own key management — plus relay access and persistent storage. It hosts napplets in sandboxed iframes and brokers their requests.
  • Many napplets — untrusted, single-purpose mini-apps. A chat widget, a feed viewer, a profile editor, a relay manager — each one its own napplet.

The napplet never calls a signer, relay connection, or localStorage directly. It asks the shell, which brokers each request through NAP interfaces — keys live wherever the shell delegates them, not inside the napplet. The browser's iframe sandbox (allow-scripts only, no allow-same-origin) enforces the boundary, so a compromised napplet cannot reach the shell's DOM, cookies, or key material.

NIP-5D in one paragraph ​

NIP-5D defines the napplet-shell protocol. All messages are JSON objects with a type field in domain.action format - { type: "outbox.query", ...payload } - sent over a MessagePort that the runtime hands to the shell in a single napplet.hello before any napplet script runs. The shell binds that port to the (dTag, artifactHash) it verified from the napplet's NIP-5D manifest and artifact bytes, and revokes the binding if the frame's document is replaced. Capability domains (NAPs — modular Nostr Applet Protocol contracts) are negotiated declaratively via manifest R tags and queried at runtime with window.napplet?.domain. Read the full NIP-5D explanation.

Archetype roles use stable identities such as napplet:note/open. Manifest discovery, subscriptions, normalized wire identities, and handler routing keep that complete queryless string and match it exactly. INC emit may transpose URI query pairs into a text payload before sending the queryless identity.

Intent invocation uses invoke(uri, options?) or open(uri, options?); its structured result reports both dispatch success and whether a handler accepted it. Payload remains untrusted at the receiving boundary. This project follows NAP-INC PR #89 (4593ce9), the governance/web projection PR #90 (896c32c), and NAP-INTENT.

A bigger pool of builders ​

Because the hard, security-sensitive Nostr machinery — relay pools, NIP-46 signers, event signing and encryption — lives behind the shell, a napplet author doesn't need deep protocol expertise to ship something useful. They render UI and send envelopes; the shell handles the dangerous parts. That lowers the barrier to entry and widens the ecosystem without putting users at risk.

Web first, not web only ​

The napplet model is being proven on the web first, and for good reasons: the iframe is a real, browser-enforced sandbox you can demonstrate today; the web has the largest developer ecosystem to draw from; and a napplet is just static files, so it distributes as a NIP-5A static site (an nsite) over Nostr + Blossom with no servers.

NIP-5D is specifically that web realization — it defines the security posture and transport (postMessage across an iframe boundary) for napplets in the NIP-5A context. It is a web-context spec, not a cross-platform one.

The broader napplet and NAP capability model, however, is deliberately transport-agnostic — capability domains and intent, not browser plumbing. The web is the starting point, not the ceiling: the same model leaves room to be carried on other platforms later, each of which would define its own transport and security posture (its own analogue to NIP-5D) rather than reusing the web one.

Who it's for ​

  • Nostr developers who want to ship a focused app without re-building relay management, signing, and storage — and without ever holding the user's keys.
  • Developers new to Nostr who want to build for the ecosystem without mastering every protocol detail first — the shell carries that weight.
  • Shell / client authors who want to host third-party apps safely, competing on trust and UX rather than feature count.
  • Protocol tinkerers exploring what a composable, capability-based Nostr client ecosystem looks like.

Ready to build? Head to Getting Started, or join the community group chat.

Released under the MIT License.