diff --git a/CLAUDE.md b/CLAUDE.md index 0970d74..6f21eb4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## What This Is -Wrystr is a cross-platform Nostr desktop client built with Tauri 2.0 (Rust) + React + TypeScript. It connects to Nostr relays via NDK (Nostr Dev Kit) and aims for Telegram Desktop-quality UX. +Wrystr is a cross-platform Nostr desktop client built with Tauri 2.0 (Rust) + React + TypeScript. It connects to Nostr relays via NDK (Nostr Dev Kit) and aims for Telegram Desktop-quality UX. Long-form content (NIP-23) is a first-class, distinguishing feature — not an afterthought. ## Commands @@ -21,28 +21,36 @@ Prerequisites: Node.js 20+, Rust stable, `@tauri-apps/cli` **Frontend** (`src/`): React 19 + TypeScript + Vite + Tailwind CSS 4 -- `src/App.tsx` — root component, view routing via UI store -- `src/stores/` — Zustand stores per domain: `feed.ts`, `user.ts`, `ui.ts` -- `src/lib/nostr/` — NDK wrapper; all Nostr calls go through here, never direct NDK in components -- `src/types/nostr.ts` — shared TypeScript interfaces (NostrProfile, NostrNote, RelayInfo) -- `src/components/feed/` — Feed, NoteCard, NoteContent -- `src/components/shared/` — LoginModal, RelaysView, SettingsView +- `src/App.tsx` — root component; shows `OnboardingFlow` for new users, then view routing via UI store +- `src/stores/` — Zustand stores per domain: `feed.ts`, `user.ts`, `ui.ts`, `lightning.ts` +- `src/lib/nostr/` — NDK wrapper (`client.ts` + `index.ts`); all Nostr calls go through here +- `src/lib/lightning/` — NWC client (`nwc.ts`); Lightning payment logic +- `src/hooks/` — `useProfile.ts`, `useReactionCount.ts` +- `src/components/feed/` — Feed, NoteCard, NoteContent, ComposeBox +- `src/components/profile/` — ProfileView (own + others, edit form) +- `src/components/thread/` — ThreadView +- `src/components/search/` — SearchView (NIP-50, hashtag, people) +- `src/components/article/` — ArticleEditor (NIP-23) +- `src/components/zap/` — ZapModal +- `src/components/onboarding/` — OnboardingFlow (welcome, create key, backup, login) +- `src/components/shared/` — RelaysView, SettingsView (relay mgmt + NWC + identity) - `src/components/sidebar/` — Sidebar navigation **Backend** (`src-tauri/`): Rust + Tauri 2.0 - `src-tauri/src/lib.rs` — Tauri app init and command registration - Rust commands must return `Result` -- Future: OS keychain for key storage, SQLite, lightning integration +- Future: OS keychain for key storage, SQLite, lightning node integration ## Key Conventions (from AGENTS.md) - Functional React components only — no class components - Never use `any` — define types in `src/types/` -- Tailwind classes only — no inline styles -- Private keys must never be exposed to JS; use OS keychain via Rust +- Tailwind classes only — no inline styles, except unavoidable WebkitUserSelect +- Private keys must never be exposed to JS; use OS keychain via Rust (not yet implemented — nsec currently lives in NDK signer memory only) - New Zustand stores per domain when adding features - NDK interactions only through `src/lib/nostr/` wrapper +- Lightning/NWC only through `src/lib/lightning/` wrapper ## NIP Priority Reference @@ -52,6 +60,23 @@ Prerequisites: Node.js 20+, Rust stable, `@tauri-apps/cli` ## Current State -Implemented: relay connection, global feed, note rendering, login (nsec/npub), sidebar navigation, Zustand stores. +**Implemented:** +- Onboarding: key generation, nsec backup flow, login with nsec/npub +- Global + following feed, compose, reply, thread view +- Reactions (NIP-25) with live network counts +- Follow/unfollow (NIP-02), contact list publishing +- Profile view + edit (kind 0) +- Long-form article editor (NIP-23) with draft auto-save +- Zaps: NWC wallet connect (NIP-47) + NIP-57 via NDKZapper +- Search: NIP-50 full-text, hashtag (#t filter), people +- Settings: relay add/remove (persisted to localStorage), NWC URI, npub copy +- Relay connection status view -Not yet implemented: compose/post, reactions, zaps, DMs, profile editing, SQLite storage, OS keychain integration. +**Not yet implemented:** +- OS keychain integration (Rust) — nsec lives in NDK memory only +- SQLite local note cache +- Direct messages (NIP-44/17) +- Reading long-form articles (NIP-23 reader view) +- Zap counts on notes +- NIP-65 outbox model +- GitHub Releases + auto-updater diff --git a/README.md b/README.md index e350dda..95b0336 100644 --- a/README.md +++ b/README.md @@ -10,15 +10,19 @@ Early development. Core features working. Not yet ready for general release. ## Features -- **Global & following feed** — live notes from relays, filtered to your network -- **Compose & post** — write and publish notes (kind 1) -- **Replies** — inline reply composer on every note, opens in thread view -- **Reactions** — like notes (NIP-25), persisted locally -- **Thread view** — click any note to see it with its replies -- **Profile view** — click any name or avatar to view their profile and notes -- **Editable own profile** — update your display name, bio, picture, NIP-05, Lightning address and more (kind 0) +- **Onboarding** — key generation built-in, plain-language explanation, nsec backup flow; no browser extension required +- **Global & following feed** — live notes from relays, tab-switched to your network +- **Compose & post** — write and publish notes (kind 1), Ctrl+Enter to send +- **Replies** — inline reply composer on every note, full thread view +- **Reactions** — like notes (NIP-25) with live network counts +- **Follow / Unfollow** — follow and unfollow from any profile (NIP-02), updates contact list on-chain +- **Thread view** — click any note to see it with all its replies +- **Profile view** — click any name or avatar; edit your own profile (kind 0) - **Long-form article editor** — write and publish markdown articles (NIP-23) with title, summary, tags, cover image, live preview, and auto-save drafts -- **Login** — nsec (private key) or npub (read-only), with browser password manager support +- **Zaps** — send Lightning payments via NWC (NIP-47 + NIP-57); amount presets, custom amounts, optional comment +- **Search** — NIP-50 full-text search, `#hashtag` topic search, people search with inline follow +- **Settings** — relay add/remove (live, persisted), NWC wallet connection, npub copy +- **Login** — nsec (full access) or npub (read-only) ## Stack @@ -26,7 +30,7 @@ Early development. Core features working. Not yet ready for general release. |---|---| | Desktop shell | Tauri 2.0 (Rust) | | Frontend | React 19 + TypeScript + Vite | -| Nostr protocol | NDK (Nostr Dev Kit) | +| Nostr protocol | NDK 3.x (Nostr Dev Kit) | | Styling | Tailwind CSS 4 | | State | Zustand | @@ -42,16 +46,14 @@ npm run tauri build # production binary ## Roadmap -- [ ] Key generation + onboarding flow -- [ ] OS keychain for secure key storage -- [ ] SQLite local cache -- [ ] Zaps (NIP-57) + Lightning Wallet Connect (NIP-47) -- [ ] Follow/unfollow -- [ ] Search (NIP-50) +See [ROADMAP.md](./ROADMAP.md) for the full prioritised next steps. + +Near-term: +- [ ] OS keychain for secure key storage (Rust backend) +- [ ] SQLite local note cache - [ ] Direct messages (NIP-17/44) - [ ] Read long-form articles in-app -- [ ] Relay management UI -- [ ] GitHub Releases distribution + Tauri auto-updater +- [ ] GitHub Releases + Tauri auto-updater ## License diff --git a/ROADMAP.md b/ROADMAP.md index 042645f..3e2a7fb 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -20,61 +20,19 @@ platform that happens to live on Nostr, not a social feed that happens to suppor --- -## Quick wins (high impact, low effort) +## Up next -### 1. Settings View -- Currently 100% stubbed with placeholder text -- Add relay management: add/remove relay URLs -- Appearance toggles (theme, etc.) -- Key export/management UI - -### 2. Follow/Unfollow from UI (NIP-02 — P1) -- Follow list is already fetched in the user store and used for the following feed -- Just needs a Follow/Unfollow button on ProfileView -- Data layer is already there — this is mostly UI work - -### 3. Reaction counts from network -- Likes are currently tracked in localStorage only -- Reaction counts from the network are never fetched or displayed -- Would make notes feel much more alive socially - ---- - -## Medium effort, high value - -### 4. Zaps (NIP-57 + NIP-47 — P2) -- lud16 (Lightning address) is already shown on profile pages -- Needs: zap modal, amount picker, NWC wallet connection (NIP-47) -- Big UX differentiator vs other clients - -### 5. Search (NIP-50 — P1) -- Not started at all -- Easiest entry point: hashtag search (hashtags are already highlighted in NoteContent) -- Then: full-text note search, user search - -### 6. OS Keychain via Rust (Tauri backend) -- Security-critical: private keys currently only live in memory +### 1. OS Keychain via Rust (Tauri backend) +- Security-critical: private keys currently live in NDK signer memory only - Rust backend (`src-tauri/src/lib.rs`) only has a placeholder `greet()` command -- Tauri has keychain plugins ready to use +- Tauri has keychain plugins ready to use (`tauri-plugin-keychain`) ---- - -## Longer term - -### 7. Onboarding flow -- Nostr onboarding is notoriously bad across most clients; Wrystr should be the exception -- Key generation built-in (no "go get a browser extension first") -- Human-readable explanation of what a key is, without crypto jargon -- One-click backup flow (show nsec, prompt to save) -- New users should see interesting content immediately, not a blank feed -- Optional: custodial key service path for non-technical users, with a clear path to self-custody later - -### 8. SQLite note caching +### 2. SQLite note caching - Notes disappear on every refresh — no persistence - Would make the app feel dramatically more solid and fast - Rust backend is the right place for this -### 9. Direct Messages (NIP-44 — P3) +### 3. Direct Messages (NIP-44 — P3) - Significant complexity (encryption, key handling) - Major feature gap but non-trivial to implement well @@ -100,16 +58,15 @@ platform that happens to live on Nostr, not a social feed that happens to suppor ## What's already done (for reference) -- Global + following feed +- **Onboarding**: key generation, nsec backup flow, plain-language UX, no extension required +- **Global + following feed**, compose, reply, thread view +- **Reactions** (NIP-25) with live network counts +- **Follow / Unfollow** (NIP-02), contact list publishing +- **Profile view + edit** (kind 0) +- **Long-form article editor** (NIP-23) with draft auto-save +- **Zaps**: NWC wallet connect (NIP-47) + NIP-57 via NDKZapper, amount presets, comment +- **Search**: NIP-50 full-text, hashtag (#t filter), people with inline follow +- **Settings**: relay add/remove (live + persisted), NWC wallet setup, npub copy - Note rendering (images, video, mentions, hashtags) -- Compose + reply -- Reactions (like button + network counts) -- Follow / unfollow (NIP-02) -- Profile view + edit -- Thread view -- Article editor (NIP-23, with draft auto-save) -- Search: NIP-50 full-text, hashtag (#t filter), people -- Settings: relay add/remove (persisted), npub copy -- Login (nsec + read-only pubkey) - Relay connection status view -- NDK wrapper for all Nostr interactions +- NDK 3.x wrapper for all Nostr interactions