NIP-5D · Nostr Web Applets

Composable Nostr apps,
not monoliths.

A Nostr Applet — a napplet — is a small, sandboxed app that does one thing well. It runs inside a host shell and delegates signing, storage and relay access over a simple, typed message protocol — so apps stop rebuilding the same client, and every sensitive request is brokered by the shell.

sandboxed & isolated by the host · every request via the shell · any shell, any napplet
Web first — not web only web napplets prove the protocol on the web by choice
  • A real, browser-enforced sandbox
  • The biggest developer ecosystem
  • Ships as a NIP-5A nsite — no servers

The napplet & NAP model is transport-agnostic by design — room to grow beyond the browser.

Projections one capability seam, many hosts — see the registry
ProjectionBindingStatus
Webiframes + postMessage · window.napplet.*In use
NativeOS process + IPC / FFIPossible
WASMhost importsPossible
wtf is an applet?

applet

/ˈæp.lɪt/ noun

a small application built to do one narrow task — run inside a larger host program rather than launched on its own.

Blend application with the diminutive -let and you get a tiny program made to live inside a bigger one. The word turns up in print around 1990, then gets burned into a generation’s memory by Java applets running sandboxed in the browser — though the instinct of shipping a little program to extend a remote machine goes all the way back to RFC 5 in 1969. A napplet is that same idea, reborn Nostr-native.

The problem

Nostr clients are monoliths

The protocol is composable. The clients are not. Each one is a giant app that owns your keys and reinvents the same building blocks — so good ideas stay trapped inside whichever client shipped them.

Everyone rebuilds everything

Feeds, DMs, profiles, relay management, search — every client re-implements the same surface from scratch.

Your key is everywhere

Each app you install asks for direct signing access. The more apps that hold that power, the larger your exposure.

No real composition

You can’t drop one team’s great feed into another team’s great messenger. Features are welded to clients.

All-or-nothing trust

Installing a client means trusting the whole thing — its code, its relays, its handling of your data.

The shift

Invert the client

NIP-5D splits the monolith in two. A trusted shell brokers every sensitive request — signing, relays, storage. Focused web napplets render the UI and ask the shell to do that work. Same protocol — completely different shape.

How it works

A message bus with a trust boundary

Every sensitive request goes through the shell, which brokers it to a signer, extension or relay. Web napplets just send envelopes and get answers back. On the web — the first target — that boundary is an iframe and postMessage.

shell mediates
01

One envelope, every message

Napplet and shell speak a single JSON wire format: { type: "domain.action", ...payload } over postMessage. No SDK lock-in — it’s just messages.

02

Identity bound to the document

The verified app hands the shell a private channel before any of its code runs. If the frame loads anything else, the shell cuts the channel and drops the app.

03

Sandboxed by construction

Iframes use allow-scripts only — no allow-same-origin. Napplets can’t read shell storage, cookies or keys. Everything sensitive is proxied.

04

Capabilities, negotiated

A runtime injects window.napplet.relay when relay access is available. NAP domains carve the protocol into modular capabilities.

Benefits

Why the pattern wins

Splitting trust from UI isn’t just tidy — it changes what’s safe, what’s reusable, and who’s in control.

Every request goes through the shell

Napplets never call a signer, relay or store directly. They ask the shell, which brokers each request — to a remote signer, an extension, or its own services — and can say no.

Real sandbox isolation

allow-scripts without allow-same-origin: no service workers, no shell storage, no cross-origin reach. Each napplet does one thing, so its surface and permissions stay small.

Compose, don’t rebuild

Drop a great feed next to a great messenger. Napplets are interchangeable parts, not features welded into one app.

A bigger pool of builders

The hard Nostr protocol lives behind the shell. Developers can ship a useful napplet without deep protocol knowledge — and without putting users at risk.

The user stays in control

The shell brokers every relay, storage and signing request, and scopes storage per napplet. Consent lives with the host, not the app.

Portable across shells

Write to NIP-5D, run in any compatible shell. No vendor SDK lock-in — the protocol is the contract.

The paradigm shift

An app store, not an app

Treat the shell like an operating system for Nostr. Napplets become installable, swappable programs — and the ecosystem stops being a handful of monoliths.

Clients compete on features Shells compete on trust & UX

When any napplet can run anywhere, a shell wins by being safer and nicer to use — not by hoarding features.

Pick one app, get its whole worldview Assemble your own client

Mix a feed from one team, a wallet from another, a niche tool from a solo dev. Your client becomes a composition.

Deep Nostr expertise to ship anything One dev ships one great napplet

The hard protocol lives behind the shell. Render UI, send envelopes — no relay pools, NIP-46 signers or event-signing to get right. A far broader pool of builders can contribute.

Trust the whole client with your signer Trust the shell, sandbox the rest

A single audited host brokers every sensitive request. Everything else runs contained, asking the shell for what it needs.

Runtimes & shells

Any shell can be a runtime

A runtime is the host that actually runs your web napplet — it brokers your requests to a signer, extension or relay and talks to the network. On the web, a runtime is any app that honors NIP-5D — the security posture and transport for web napplets — and there can be many. That’s the point.

For client developers

Already built a Nostr client?

You’ve solved the hard parts — relay pools, signer flows, storage, key handling. Expose them through NAP interfaces and your client becomes a shell. Host third-party web napplets without rewriting your app, and turn your client into a platform.

  • Reuse your existing relay & signer plumbing
  • Host an ecosystem instead of shipping every feature
  • Compete on trust & UX, not feature count
For protocol developers

Want to shape the protocol?

NIP-5D is small and the surface is well-defined. Stand up a runtime, implement the NAP capability domains, and help decide what the protocol becomes. Conformance work and new NAPs are where the design is still being written.

  • Implement NIP-5D — transport, identity, dispatch
  • Define & extend NAP capability domains
  • Drive conformance against the reference runtime
Browse the NAPs track ↗
Reference runtime

Kehto implements NIP-5D end-to-end

The reference shell where the protocol runs for real — host a napplet, watch the envelopes flow, and use it as the conformance target while you build a runtime of your own.

Packages

The napplet SDK

Small, ESM-only, zero-framework packages. Import the shim for a window global, the SDK for named exports, or pull a single NAP domain.

@napplet/core

JSON envelope types and NAP dispatch infrastructure shared by the SDK packages. Protocol requirements live in NIP-5D and the NAP specs.

@napplet/shim

Runtime-side domain installers for the window.napplet namespace. Shells inject the available domains before napplet scripts run.

@napplet/sdk

Named TypeScript exports wrapping window.napplet for bundler consumers — relay, inc, services, storage objects plus NAP message types.

@napplet/nap

All NAP domains as layered subpath exports — barrel, types-only, shim-only, or sdk-only. Tree-shakable. Import from a domain subpath.

@napplet/vite-plugin

Build-time napplet manifest generation. Hashes each file and signs a kind 35129 manifest event (NIP-5A tag schema).

@napplet/cli

Standalone CLI for creating projects, owning deploy metadata, previewing in Paja, and publishing NIP-5A manifests to Blossom and Nostr relays.

@napplet/conformance

Framework-agnostic protocol conformance engine — reference mock shell, per-NAP envelope validators, a manifest validator, and reporters. A dev/test tool, not loaded in the sandbox.

@napplet/conformance-cli

The headless napplet-conformance runner. Drives the conformance engine against your napplet in real Chromium via Playwright — wire it up as test:conformance.

@napplet/conformance-web

Browser conformance runtime. Loads a napplet URL, runs the conformance engine live in the page, and powers the deployed /conformance app.

@napplet/boilerplate

Project scaffold behind napplet create. Clones the maintained Vite + TypeScript starter without owning deployment metadata.