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.4.11

Published

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

Downloads

1,289

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.
  • Semantic Embeddings — Starts with an offline deterministic baseline, then optionally upgrades to local Transformers.js embeddings in a Web Worker using WebGPU/WASM with automatic fallback.
  • 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.
  • AI Writing Assistant — Optional Habla-inspired side-panel tools for drafting, rewriting, concision, expansion, and summaries. Configure an OpenAI or Groq API key locally in Settings.
  • 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 OPFS adapter, vector similarity search, and adaptive memory | | Local Embeddings | Transformers.js — optional browser sentence embeddings with FeatureHashEmbedding fallback | | 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

Android build

Android APKs and app bundles are built by GitHub Actions when a v* release tag is pushed. The workflow installs the Android SDK and NDK on the GitHub-hosted runner, initializes Tauri's generated Android project there, signs the ARM64 APK and AAB with the Android release key, and uploads both to the workflow run and GitHub release. No Android development tools are needed on your local machine.

Configure these repository secrets for Android release signing:

  • ANDROID_KEYSTORE_BASE64 — base64-encoded PKCS#12 keystore
  • ANDROID_KEYSTORE_PASSWORD
  • The signing key alias is read from the keystore during the build.

Tagged Android releases are also published to Zapstore using zapstore.yaml. Configure the repository secret ZAPSTORE_NSEC with the Zapstore publisher Nostr private key used by Scrollstr. The workflow validates the metadata, then publishes the signed APK after uploading it to the GitHub release.

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.
  • Embedding upgrade path — FeatureHashEmbedding is available immediately and offline. On capable browsers, a local all-MiniLM-L6-v2 Transformers.js model is loaded in a Worker, preferring WebGPU and falling back to WASM. Existing persisted vectors are rebuilt in background batches and tagged with provider/version and input-hash metadata.
  • Event & profile caching — Kind:30023 articles, follow lists, relay lists, and kind:0 profiles are cached locally to reduce relay round-trips.
  • Adaptive memory (activation) — Reading, liking, boosting, zapping, and searching durably reinforce article nodes; edges link articles to their topics (tagged), author (authors), and mentioned pubkeys (mentions). A personalized For You feed ranks by activation, semantic search "absorbs" the query region, and similar articles are re-ranked by spreading activation.

Configuration

Environment variables: WRITE_NOSTR_SSH_TARGET, WRITE_NOSTR_DOMAIN, WRITE_NOSTR_PORT, etc.

AI Writing Assistant

The editor includes an optional AI assistant modeled after the writing workflows in Habla. It supports OpenAI and Groq OpenAI-compatible chat endpoints. API keys are stored locally in the browser, scoped to the logged-in Nostr account, and are sent directly to the selected provider; they are never published to Nostr. Generated text is shown for review and is never applied or published automatically.

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