npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@napplet/core

v0.2.1

Published

Shared protocol types, constants, and message definitions for the napplet protocol

Readme

@napplet/core

JSON envelope types and NUB dispatch infrastructure for the napplet ecosystem.

Getting Started

Package Overview

This package is the single source of truth for all protocol-level definitions in the napplet ecosystem. All other @napplet/* packages import their envelope types, dispatch infrastructure, and protocol constants from here.

Zero dependencies. No DOM or browser APIs. Works in any JavaScript runtime.

Installation

npm install @napplet/core

Quick Start

import {
  type NappletMessage, type NubDomain, type ShellSupports,
  type NubHandler, type NubDispatch,
  NUB_DOMAINS, SHELL_BRIDGE_URI, PROTOCOL_VERSION,
  createDispatch, registerNub, dispatch, getRegisteredDomains,
  ALL_CAPABILITIES, TOPICS,
} from '@napplet/core';

API Reference

Envelope Types

The JSON envelope wire format is the primary API introduced in NIP-5D v4. All messages between napplet and shell use a type field as a discriminant in domain.action format.

NappletMessage

Base interface for all messages exchanged between napplet and shell.

interface NappletMessage {
  /** Message type discriminant in "domain.action" format */
  type: string;
}

Concrete message types extend this interface with domain-specific payload fields:

// Example concrete message type:
interface RelaySubscribe extends NappletMessage {
  type: 'relay.subscribe';
  id: string;
  subId: string;
  filters: NostrFilter[];
}

The type field domain prefix (relay, identity, storage, ifc, theme, keys, media, notify, config) routes messages to the correct NUB handler via dispatch().

NubDomain

String literal union of the nine NUB capability domains.

type NubDomain = 'relay' | 'identity' | 'storage' | 'ifc' | 'theme' | 'keys' | 'media' | 'notify' | 'config';

| Domain | Scope | |-----------|------------------------------------------| | relay | Relay proxy (subscribe, publish, query) | | identity | Read-only user identity queries | | storage | Scoped key-value storage proxy | | ifc | Inter-frame communication (dispatch + channel) | | theme | Theme tokens and appearance settings | | keys | Keyboard forwarding and action keybindings| | media | Media session control and playback | | notify | Shell-rendered notifications | | config | Per-napplet declarative configuration (JSON Schema-driven) |

NUB_DOMAINS

Runtime constant array of all NUB domain strings. Useful for iteration and validation.

const NUB_DOMAINS: readonly NubDomain[] = ['relay', 'identity', 'storage', 'ifc', 'theme', 'keys', 'media', 'notify', 'config'];

for (const domain of NUB_DOMAINS) {
  console.log(`Checking support for: ${domain}`);
}

ShellSupports

Interface for the shell capability query API.

interface ShellSupports {
  supports(capability: NubDomain | string): boolean;
}

Napplets call window.napplet.shell.supports(domain) to check whether the shell declared support for a NUB domain before using that domain's API.

NappletGlobalShell

Type for the window.napplet.shell namespace. Extends ShellSupports.

interface NappletGlobalShell extends ShellSupports {}

NUB Dispatch Infrastructure

The dispatch system allows NUB modules to self-register at import time. Inbound messages are routed to the correct NUB handler based on the domain prefix extracted from message.type (the part before the first .).

createDispatch()

Factory that returns an isolated { registerNub, dispatch, getRegisteredDomains } backed by its own Map<string, NubHandler>. Use for testing or multi-instance scenarios.

function createDispatch(): NubDispatch;
import { createDispatch } from '@napplet/core';

const { registerNub, dispatch } = createDispatch();
registerNub('relay', handleRelayMessage);
dispatch({ type: 'relay.subscribe' }); // true

registerNub(domain, handler)

Register a handler for a NUB domain on the module-level singleton registry. NUB modules call this at import time.

const registerNub: (domain: string, handler: NubHandler) => void;
import { registerNub } from '@napplet/core';

registerNub('relay', (msg) => {
  // handles all relay.* messages
  console.log('relay message:', msg.type);
});

Throws if the domain is already registered.

dispatch(message)

Dispatch a message to the handler matching its domain prefix. Returns true if a handler was found and called.

const dispatch: (message: NappletMessage) => boolean;
import { dispatch } from '@napplet/core';

dispatch({ type: 'relay.subscribe' });  // true (if relay handler registered)
dispatch({ type: 'unknown.action' });   // false
dispatch({ type: 'malformed' });         // false (no dot)

The domain is extracted by splitting message.type on the first .. A type with no . or an empty domain prefix returns false without throwing.

getRegisteredDomains()

Return all currently registered domain strings from the singleton registry.

const getRegisteredDomains: () => string[];
import { getRegisteredDomains } from '@napplet/core';

getRegisteredDomains(); // ['relay', 'identity', 'storage']

NubHandler

Callback type for NUB message handlers.

type NubHandler = (message: NappletMessage) => void;

NubDispatch

Interface returned by createDispatch().

interface NubDispatch {
  registerNub: (domain: string, handler: NubHandler) => void;
  dispatch: (message: NappletMessage) => boolean;
  getRegisteredDomains: () => string[];
}

Protocol Types

Types shared by all napplet packages for Nostr event structures and the capability system.

NostrEvent

Standard Nostr event structure (used by relay NUB and identity NUB).

interface NostrEvent {
  id: string;
  pubkey: string;
  created_at: number;
  kind: number;
  tags: string[][];
  content: string;
  sig: string;
}

NostrFilter

Subscription filter (used by relay NUB for relay.subscribe and relay.query).

interface NostrFilter {
  ids?: string[];
  authors?: string[];
  kinds?: number[];
  since?: number;
  until?: number;
  limit?: number;
  [key: `#${string}`]: string[] | undefined; // tag filters, e.g. '#t', '#e'
}

Capability

String union type listing all 10 protocol capability strings.

type Capability =
  | 'relay:read' | 'relay:write'
  | 'cache:read' | 'cache:write'
  | 'hotkey:forward'
  | 'sign:event' | 'sign:nip04' | 'sign:nip44'
  | 'state:read' | 'state:write';

Shell implementations use bitfield constants (CAP_*) for fast runtime checks. Capability strings are the human-readable protocol-level representation.

ALL_CAPABILITIES

readonly Capability[] containing all 10 capability strings.

for (const cap of ALL_CAPABILITIES) {
  console.log(cap); // 'relay:read', 'relay:write', ...
}

Subscription

Handle returned by relay.subscribe() and ipc.on().

interface Subscription {
  close(): void;
}

EventTemplate

Unsigned event template passed to relay.publish().

interface EventTemplate {
  kind: number;
  content: string;
  tags: string[][];
  created_at: number;
}

Protocol Constants

| Constant | Value | Description | |----------|-------|-------------| | PROTOCOL_VERSION | '4.0.0' | Current napplet-shell protocol version (JSON envelope era, NIP-5D v4) | | SHELL_BRIDGE_URI | 'napplet://shell' | URI identifying the shell bridge in relay tags | | REPLAY_WINDOW_SECONDS | 30 | Maximum event age (seconds) for replay protection |


Topic Constants

The TOPICS object contains string constants for IFC topic-based routing. These are legacy constants from the pre-envelope era — with JSON envelope messages, topic strings are passed directly in ifc.emit and ifc.subscribe payloads.

import { TOPICS } from '@napplet/core';

TOPICS.STATE_GET                // 'shell:state-get'
TOPICS.SHELL_CONFIG_GET         // 'shell:config-get'
TOPICS.WM_FOCUSED_WINDOW_CHANGED // 'wm:focused-window-changed'
// ... see source for full list

Note: With JSON envelope wire format (v0.16.0+), state operations use storage.* messages directly rather than IFC topic routing. These constants are retained for backward compatibility with shell runtime implementations.


Types

import type {
  NappletMessage, NubDomain, NamespacedCapability, ShellSupports, NappletGlobalShell,
  NubHandler, NubDispatch,
  NostrEvent, NostrFilter, Capability,
  Subscription, EventTemplate, NappletGlobal,
} from '@napplet/core';

| Type | Description | |------|-------------| | NappletMessage | Base interface for all JSON envelope messages | | NubDomain | Union of the nine NUB domain strings | | NamespacedCapability | Union of NubDomain \| nub:* \| perm:* for supports() | | ShellSupports | Interface with supports() capability query method | | NappletGlobalShell | Type for window.napplet.shell (extends ShellSupports) | | NubHandler | Callback type for NUB domain handlers | | NubDispatch | Interface returned by createDispatch() | | NostrEvent | Nostr event structure | | NostrFilter | Subscription filter for relay NUB | | Capability | Human-readable capability string union | | Subscription | Handle with close() returned by subscribe/on | | EventTemplate | Unsigned event template for publishing |

Integration Note

@napplet/core is consumed by all packages in the napplet ecosystem for envelope types and NUB dispatch.

  • In this repo: @napplet/shim, @napplet/sdk, and @napplet/vite-plugin import NappletMessage, NubDomain, ShellSupports, and all shared protocol types from @napplet/core.
  • NUB packages (@napplet/nub-relay, @napplet/nub-identity, @napplet/nub-storage, @napplet/nub-ifc, @napplet/nub-keys, @napplet/nub-media, @napplet/nub-notify, @napplet/nub-config): extend NappletMessage for their domain-specific message types and call registerNub at import time.

Protocol Reference

  • NIP-5D -- Napplet-shell protocol specification

License

MIT