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

write-nostr

v0.2.3

Published

Browser-based long-form writing app for the Nostr protocol — NIP-23 editor, feed reader, and publishing tool

Readme

write_nostr

write_nostr is a browser-based long-form writing app for the Nostr protocol. It provides a distraction-free Markdown editor for composing, publishing, and managing NIP-23 long-form content (kind:30023) directly to Nostr relays, along with feeds for discovering articles from the network.

Built with Svelte 5 and SvelteKit, write_nostr runs as a fully static single-page app — no backend required. Authentication works via NIP-07 browser extensions, nsec keys, or passkeys (WebAuthn/PRF). Articles are rendered with live preview, support metadata (title, summary, featured image, tags), and auto-save to localStorage drafts. The app is installable as a PWA with offline support.

Whether you're a writer looking for a censorship-resistant publishing platform or a Nostr user who wants to read and engage with long-form content on the decentralized web, write_nostr offers a clean, focused experience.

Features

  • Write & Publish — Full-featured Markdown editor with live preview, formatting toolbar, metadata (title, summary, featured image, tags), and direct publishing to Nostr relays.
  • Browse Articles — Three feed modes: All (global firehose), My Circle (articles from people you follow), and Top Articles (sorted by interaction score). Tag filtering, pagination, and manual refresh.
  • Related Articles — Vector-similarity search across articles powered by PolyGraph, surfacing related content for any article.
  • Drafts — Auto-saving drafts to localStorage with a dedicated drafts manager.
  • Authentication — Sign in via NIP-07 browser extension, paste an nsec key, or use a passkey (WebAuthn/PRF).
  • Social — Follow/unfollow and block/unblock authors directly from the feed.
  • Profiles — Kind:0 profile metadata fetched from relays, cached for performance.
  • Translation — On-device article translation via Chrome's Built-in AI Translation API.
  • PWA — Installable as a progressive web app with offline support.

Tech Stack

| Layer | Technology | |---|---| | Framework | Svelte 5 + SvelteKit 2 (runes mode) | | Build | Vite 8 + TypeScript 6 | | Nostr | nostr-tools — SimplePool, event signing, NIP-19 encoding/decoding | | Passkeys | nostr-passkey — WebAuthn/PRF-based key management | | Markdown | marked — rendering | | Graph / Vector Search | PolyGraph — persistent graph with IndexedDB adapter, vector similarity search | | Caching | idb — IndexedDB cache layer | | Adapter | @sveltejs/adapter-static — static SPA output |

Nostr Protocols (NIPs)

  • NIP-01 — Basic protocol & relay communication
  • NIP-02 — Contact lists (kind:3)
  • NIP-07 — Browser extension signer
  • NIP-19 — bech32-encoded entities (nsec, npub, naddr, nprofile, nevent)
  • NIP-23 — Long-form content (kind:30023)
  • NIP-51 — Lists (kind:10000 mute/block lists)
  • NIP-65 — Relay list metadata (kind:10002)

Getting Started

npm install
npm run dev        # Development server with hot reload

Open the URL printed by Vite (usually http://localhost:5173).

Build & Preview

npm run build      # Production build to ./build
npm run preview    # Preview the production build locally

Deploy

npm run deploy -- --host user@host --domain example.com

The deploy script:

  1. Builds the project
  2. Syncs to a remote server via rsync over SSH
  3. Installs a systemd service running the built files via the included Python SPA HTTP server
  4. Optionally configures Caddy or nginx as a reverse proxy with TLS

Prerequisites

  • Local: npm, rsync
  • Remote: python3, systemctl, ss, curl, rsync, sudo

PolyGraph Cache

write_nostr uses PolyGraph (@0xx0lostcause0xx0/polypack), a persistent graph database built on IndexedDB, to cache Nostr events and profiles in the browser. The cache is TTL-based with automatic pruning of stale entries, and supports:

  • Vector search — Articles are indexed by embedding vector, enabling similarity-based related-article recommendations and centroid-based ranking.
  • Event & profile caching — Kind:30023 articles, follow lists, relay lists, and kind:0 profiles are cached locally to reduce relay round-trips.

Configuration

Environment variables: WRITE_NOSTR_SSH_TARGET, WRITE_NOSTR_DOMAIN, WRITE_NOSTR_PORT, etc.

Type Checking

npm run check

Project Structure

src/
├── app.html                 # HTML shell
├── app.css                  # Global styles (light/dark mode)
├── lib/
│   ├── components/          # Svelte components (Editor, ArticleCard, etc.)
│   ├── stores/              # Svelte stores (auth, relays, drafts, social, profiles)
│   ├── nostr/               # Nostr logic (fetch, publish, resolve, profiles)
│   └── utils/               # Utilities (markdown, NIP-19, translation)
├── routes/
│   ├── +page.svelte         # Main feed page
│   ├── +layout.svelte       # Root layout
│   ├── new/                 # Editor (/new)
│   ├── drafts/              # Drafts manager (/drafts)
│   ├── settings/            # Settings (/settings)
│   └── article/[naddr]/     # Article view (/article/[naddr])
static/
├── brand/                   # Logo assets
├── pwa/                     # PWA icons
├── manifest.webmanifest     # PWA manifest
└── sw.js                    # Service worker

Default Relays

  • wss://relay.damus.io
  • wss://relay.nostr.band
  • wss://nos.lol
  • wss://relay.primal.net

Relays can be managed in Settings after login.

License

MIT