A modern, privacy-focused Nostr client built with React 19, TailwindCSS, shadcn/ui, and Nostrify.
| Feature | Description | Protocol |
|---|---|---|
| Global Feed | Real-time public feed with infinite scroll, media rendering, and compose | NIP-01 |
| Custom Feeds | Follow specific pubkeys and view their notes | NIP-01 |
| Private DMs | End-to-end encrypted direct messages with maximum privacy | NIP-17, NIP-44, NIP-59 |
| Profile | View and edit your profile, browse your own posts | NIP-01, NIP-02 |
| Directory | Search profiles by npub, hex pubkey, or name | NIP-01 |
| Keys | Generate, encrypt (AES-256-GCM), backup, and restore keys | NIP-19 |
| Relays | Manage your NIP-65 relay list with live status indicators | NIP-65 |
| Media Hosts | Configure Blossom / NIP-96 upload servers with auto-probing | NIP-96, NIP-98 |
| Lightning Zaps | Send zaps via WebLN or Nostr Wallet Connect (NWC) | NIP-57, NWC |
| Themes | 15 built-in themes (Dark, Solarized, Terminal, Neon, Dracula, etc.) | — |
This client implements NIP-17 Private Direct Messages, the most privacy-preserving messaging protocol on Nostr. Unlike the legacy NIP-04 scheme, NIP-17 hides all metadata.
You compose a message
│
▼
kind:14 rumor (unsigned, no sig)
│ NIP-44 encrypt to recipient
▼
kind:13 seal (signed by you, random timestamp)
│ NIP-44 encrypt with ephemeral key
▼
kind:1059 gift wrap (signed by ephemeral key, p-tag → recipient)
│
▼ Published to recipient's NIP-10050 preferred DM relays
A separate gift wrap is also created for yourself so you can read your sent messages.
- No metadata leak — relay sees only a gift wrap with a
ptag; not who sent it, not when, not what kind - Deniable — the inner rumor is unsigned; if leaked it cannot be cryptographically attributed
- NIP-44 encryption — XChaCha20-Poly1305, the latest Nostr encryption standard
- Randomised timestamps — up to 2 days in the past on both seal and gift wrap to prevent timing correlation
- Ephemeral keys — each gift wrap uses a fresh one-time signing key
Because NIP-17 requires your private key for decryption (to derive the NIP-44 conversation key), browser extension signers that do not expose the private key cannot decrypt received messages without entering the key manually. This is a known limitation of the NIP-17 specification — decryption must happen client-side with the raw key.
- Open the Lightning Wallet panel in the sidebar
- Click Add and paste a
nostr+walletconnect://URI from your wallet - Zap any note directly — NWC handles payment automatically
If you have a WebLN-compatible browser extension (e.g. Alby), it is detected automatically and used for zap payments.
Click ⚡ Zap on a note
│
▼
Fetch recipient's LNURL endpoint (NIP-57)
│
▼
Build & sign zap request (kind:9734)
│
▼
Fetch Lightning invoice from LNURL server
│
▼ Try NWC → Try WebLN → Show QR code
Pay invoice
Attach images, videos, and audio to notes using your configured media host:
- Go to Media Hosts and add a Blossom or NIP-96 server URL
- Click Probe to auto-discover API endpoint and file size limits
- When composing a note, select the file and your host → upload uses NIP-98 auth
Every upload is authenticated with a signed kind:27235 event containing:
- The upload URL
- The HTTP method (
POST) - A SHA-256 hash of the file payload
This prevents unauthorized use of your storage quota.
| Action | Description |
|---|---|
| Generate | Creates a new secp256k1 keypair locally |
| Encrypt & Save | AES-256-GCM with PBKDF2 (100k iterations) stored in localStorage |
| Decrypt Saved | Restore an encrypted key to memory with your password |
| Export Backup | Downloads an encrypted JSON backup file |
| Nostr Login | Extension (NIP-07), nsec paste, or NIP-46 bunker |
Security note: Never share your
nsecor hex private key. The encrypt/save feature uses strong AES-256-GCM encryption so your key at rest is protected.
- Add, remove, and mark relays as read / write
- Your relay list is published as a
kind:10002NIP-65 event when logged in - Live status checks via WebSocket ping
- Suggested popular relays listed for quick setup
| Theme | Style |
|---|---|
| Default Light | Clean white |
| Dark | Deep navy |
| Solarized Light | Warm yellow |
| Solarized Dark | Dark teal |
| Terminal | Green on black |
| Ocean | Deep ocean blue |
| Forest | Dark green |
| Desert | Warm sand |
| Vintage | Aged parchment |
| Neon | Magenta on black |
| Monokai | Code editor |
| Dracula | Purple/dark |
| Gruvbox Light | Warm retro |
| Gruvbox Dark | Dark retro |
| Midnight | Deep blue |
- React 19 — concurrent rendering, hooks
- TailwindCSS 3 — utility-first styling
- shadcn/ui — accessible Radix UI components
- Nostrify — Nostr protocol framework
- TanStack Query — data fetching & caching
- nostr-tools — NIP-44, NIP-59, gift wrap helpers
- React Router 6 — client-side routing
- @getalby/sdk — Nostr Wallet Connect
# Install dependencies
npm install
# Start dev server
npm run dev
# Build for production
npm run buildsrc/
├── components/
│ ├── AppLayout.tsx # Sidebar + header shell
│ ├── NoteCard.tsx # Feed note with actions
│ ├── NoteContent.tsx # Rich text / link rendering
│ ├── WalletModal.tsx # NWC + WebLN management
│ ├── ZapButton.tsx # Per-note zap trigger
│ ├── ZapDialog.tsx # Zap amount dialog
│ ├── EditProfileForm.tsx # Kind-0 profile editor
│ ├── RelayListManager.tsx # NIP-65 relay editor
│ └── auth/ # Login, signup, account switcher
├── pages/
│ ├── FeedPage.tsx # Global feed + compose
│ ├── CustomFeedPage.tsx # Per-pubkey feeds
│ ├── ProfilePage.tsx # Own profile + posts
│ ├── DirectoryPage.tsx # Profile search
│ ├── ShieldedPage.tsx # NIP-17 Private DMs ← NIP-04 replaced
│ ├── KeysPage.tsx # Key generation / encryption
│ ├── RelaysPage.tsx # Relay management
│ ├── MediaHostsPage.tsx # NIP-96/98 hosts
│ └── NIP19Page.tsx # npub/note/nevent viewer
├── hooks/
│ ├── useFeed.ts # Infinite-scroll feed query
│ ├── useNostrPublish.ts # Signed event publishing
│ ├── useAuthor.ts # Kind-0 profile fetch
│ ├── useUploadFile.ts # Blossom file upload
│ ├── useZaps.ts # Zap fetch + send
│ ├── useWallet.ts # WebLN + NWC detection
│ └── useNWC.ts # NWC connection management
└── contexts/
├── AppContext.ts # Theme + relay config
└── NWCContext.tsx # NWC provider
| NIP | Description |
|---|---|
| NIP-01 | Basic protocol — events, filters, subscriptions |
| NIP-02 | Contact lists |
| NIP-07 | Browser extension signing |
| NIP-10 | Text note threading / replies |
| NIP-17 | Private Direct Messages (NIP-44 + NIP-59) |
| NIP-19 | Bech32 identifiers (npub, nsec, note, nevent, naddr) |
| NIP-25 | Reactions (kind 7) |
| NIP-44 | Versioned encryption (XChaCha20-Poly1305) |
| NIP-46 | Nostr Connect / remote signing |
| NIP-57 | Lightning Zaps |
| NIP-59 | Gift Wrap (seal + wrap) |
| NIP-65 | Relay list metadata |
| NIP-96 | HTTP file storage |
| NIP-98 | HTTP Auth |
| NWC | Nostr Wallet Connect |
MIT
Vibed with Shakespeare