Nostr Chat is a Quasar/Vue web and Electron client for Nostr private messaging. The current app supports direct chats, group chats, contact and profile management, relay controls, browser notifications, developer diagnostics, and local packaging for desktop builds.
- Account creation in the app, with generated
npubandnsecexport - Login with a NIP-07 browser extension
- Local private-key login for
nsecor raw hex keys - Direct-message threads with search, reactions, deletions, unread tracking, and relay delivery status
- First-contact request inbox with accept, block, delete, and review flows
- Group chats with invite handling and epoch rotation support
- Contact list management, profile refresh, profile publishing, and contact lookup by identifier or pubkey
- Relay management for:
- app relays
- published NIP-65 relays
- discovered contact relays
- relay metadata and connection-state inspection
- Settings for profile, relays, theme, notifications, status, and developer diagnostics
- Startup and sync history view
- Browser-notification opt-in flow
- Developer tools for relay diagnostics, trace export, reconnects, and subscription restart
- Web, Electron, and Android build targets
The app currently uses the Nostr flows documented in NIPS_USED.md, including:
- NIP-05 identifier lookup
- NIP-07 extension login
- NIP-11 relay metadata
- NIP-17 private messaging
- NIP-19 key and profile encoding
- NIP-24 profile metadata fields
- NIP-44 encryption
- NIP-51 private follow-set style group membership data
- NIP-59 gift wrapping
- NIP-65 relay lists
- NIP-78 private app storage
- repo-local NIP-171 draft notes for group messaging in nip171.md and nip171b.md
- Quasar 2
- Vue 3.5
- Pinia 2
- TypeScript 5
@nostr-dev-kit/ndk- Vitest for unit tests
- Playwright for end-to-end tests
- Electron Builder for desktop packaging
- Biome for formatting and linting
Node.js 24 and npm 11 are required for local development and CI. The repo now declares support for Node.js 24.x.
If you use nvm, run:
nvm install
nvm useInstall dependencies:
npm installStart the web app in development mode:
npm run devStart the Electron app in development mode:
npm run dev:electronTypecheck:
npm run typecheckFormat check:
npm run format:checkLint:
npm run lintFull local quality sweep:
npm run quality:allRun unit tests:
npm run test:unitRun unit tests with coverage:
npm run test:unit:coverageRun the full local Playwright suite:
npm run test:e2e:localTargeted local e2e smoke suites are also available:
npm run test:e2e:local:auth-smokenpm run test:e2e:local:contacts-smokenpm run test:e2e:local:dm-smokenpm run test:e2e:local:groups-smokenpm run test:e2e:local:relays-smokenpm run test:e2e:local:session-smoke
The local e2e runner uses Playwright plus the Docker stack in docker-compose.e2e.yml. scripts/run-e2e-local.cjs starts the relays, waits for ports 7000 and 7001, runs Playwright, and tears the stack down again. Each run resets the relay volume so local runs start clean.
Playwright traces, screenshots, and videos are retained by default. After a run, inspect test-results/ and playwright-report/ for artifacts.
Build the web app:
npm run buildBuild Electron output without packaging into an installer:
npm run build:electron:dirBuild Electron packages:
npm run build:electron:mac
npm run build:electron:win
npm run build:electron:linuxBuild Android outputs:
npm run build:android:apk:debug
npm run build:android:release
npm run build:android:aab:releaseAndroid prerequisites:
- Docker with Compose support.
- Node/npm on the host so you can run the repo scripts.
Android notes:
- The native project lives in
src-capacitor/android. build:android:*now builds inside Docker, so the host machine does not need a local JDK or Android SDK.- The Docker image uses the official Node Docker image plus OpenJDK 17 and Android command-line tools.
- Docker builds default to
linux/amd64for better Android SDK compatibility. Override withANDROID_DOCKER_PLATFORMif you need a different target. - The helper scripts keep Gradle caches inside the repo via
.gradle-android/, so builds do not depend on~/.gradle. - Linux container dependencies are isolated in Docker volumes instead of using your host
node_modules. - If
ANDROID_KEYSTORE_PATHis absolute, the Docker wrapper mounts that keystore file into the container automatically. - Release signing is picked up from these environment variables when present:
ANDROID_KEYSTORE_PATHrelative tosrc-capacitor/androidor absoluteANDROID_KEYSTORE_PASSWORDANDROID_KEY_ALIASANDROID_KEY_PASSWORD- optional
ANDROID_VERSION_CODE - optional
ANDROID_VERSION_NAME
- Generated Android artifacts are copied into
dist/capacitor/android/. - If you ever want the old host-native path, use:
npm run build:android:local:apk:debugnpm run build:android:local:releasenpm run build:android:local:aab:release
src/
components/ Shared chat, profile, dialog, relay, and settings UI
composables/ Reusable UI and layout behavior
constants/ Default relay and app constants
pages/ Auth, chats, contacts, and settings routes
router/ Route definitions and lazy page loaders
services/ IndexedDB and runtime-facing services
stores/ Pinia stores and the modular Nostr runtime
testing/ Browser e2e bridge helpers
types/ App-level TypeScript types
utils/ Small logic helpers used across stores and UI
src-electron/ Electron main/preload entrypoints and assets
e2e/ Playwright specs
tests/unit/ Vitest specs
scripts/ Dev and test helper scripts
src/stores/nostrStore.tsis the main composition root for auth, relay, startup, message-ingest, and group runtimes.src/stores/nostr/*.tscontains the focused runtime modules used by the root store.src/stores/chatStore.tsandsrc/stores/messageStore.tsare the main UI-facing state layers.src/services/chatDataService.tsis the IndexedDB boundary for chats and messages.src/testing/e2eBridge.tsexposes deterministic browser helpers used by the Playwright suite.
This repo now includes project-specific guidance for coding agents: