Run & Use
How to run Shortwave locally, run the de-risk script, use the chat UI, and install it on your phone.
Run & Use
Prerequisites
- Node.js 20+
- npm 10+
- An internet connection (for Nostr relay access in dev)
Local development
# Clone
git clone git@github.com:mechaforge/shortwave.git
cd shortwave
# Install dependencies
npm install
# Start dev server
npm run devOpen http://localhost:3000 — home / landing page.
Open http://localhost:3000/chat — the encrypted DM channel UI.
Open http://localhost:3000/docs — this docs site.
M0 de-risk script
Run this first. Proves the NIP-17/NIP-44/NIP-59 JS crypto end-to-end.
npx tsx scripts/derisk-nip17.tsExpected output:
── NIP-17 DE-RISK ──────────────────────────────────────────
Alice pubkey : bc171ef70cce34a3…
Bob pubkey : 4a9f2c81de053b7e…
Wrapped event id : 7c3f1a92b0de45f1…
Wrapped event kind : 1059
Connected to 2/2 relay(s)
Published to 2/2 relay(s)
Bob received : "shortwave-derisk-1749456000000"
Content match : YES
NIP-17 DERISK PASSUsing the chat UI (manual two-browser test)
The /chat route is the full Shortwave instrument UI (forged-2 design).
First visit — identity
On first load, the app generates a fresh Nostr keypair and persists it in localStorage.
Your pubkey appears in the bottom identity panel as npub1… and OP-XXXX.
Add a contact
- Click + Add in the operator rail (left sidebar)
- Paste the contact's npub1… or 64-char hex pubkey
- Enter an optional handle (e.g. DETHKLAW)
- Press Enter or click Add
The contact appears in the rail. Click them to open the channel.
Send a message
Type in the compose bar at the bottom right and press ↵ Enter or click Send.
The message is NIP-17 gift-wrapped and published to all connected relays. It appears immediately in your ledger thread with a sent state marker.
Receive a message
Have the other person add your npub as a contact and send you a message.
The /chat page subscribes to all incoming kind:1059 events for your pubkey on startup.
Incoming messages appear in the thread with a recv state marker.
Two-browser test
- Open Tab A at
http://localhost:3000/chat. Copy your npub from the identity panel. - Open Tab B at
http://localhost:3000/chat(incognito/different browser to get a fresh keypair). Copy Tab B's npub. - In Tab A: Add Tab B's npub as a contact → open channel → send a message.
- In Tab B: Add Tab A's npub as a contact → open channel.
- Tab B receives the message within a few seconds (relay round-trip ~2–10s).
- Reply from Tab B → Tab A receives.
Caveats:
- Same-browser tabs share localStorage and therefore the same identity. Use a different browser or incognito for the second identity.
- Relay connectivity varies; if one relay is down, the other handles delivery.
- Messages are ephemeral — they exist in-memory only. Refreshing the page clears the thread (by design — no plaintext persistence).
Build
npm run buildShould exit with 0 errors and produce the route table showing /chat at ~40 kB.
Type-check
npm run typecheckSelf-hosting the relay (optional, recommended)
docker run -d \
--name strfry \
-p 7777:7777 \
-v $(pwd)/strfry-data:/app/strfry-db \
ghcr.io/hoytech/strfry:latest
# .env.local
NEXT_PUBLIC_LOCAL_RELAY=ws://127.0.0.1:7777Shortwave connects to this relay in addition to the public relays, publishing to all simultaneously.
Install on your phone (PWA)
Shortwave is installable as a Progressive Web App on iOS and Android. Once installed it launches full-screen (no browser chrome) and works as a native-feeling app.
iOS (Safari)
- Open the deployed Shortwave URL in Safari on iPhone or iPad.
- Tap the Share button (rectangle with an arrow pointing up).
- Scroll down in the share sheet and tap Add to Home Screen.
- Edit the name if you wish, then tap Add.
- The Shortwave icon appears on your home screen. Tap it to launch standalone.
Note: Safari is required for PWA installation on iOS — Chrome/Firefox on iOS cannot install PWAs.
Android (Chrome)
- Open the deployed Shortwave URL in Chrome.
- Chrome will show an Install app banner at the bottom, or tap the three-dot menu → Add to home screen.
- Tap Install in the prompt.
- Shortwave appears in your app drawer and home screen.
Mobile UX (< 600px)
On mobile the app uses the mobile-1 layout:
- Screen A — Operators list: lists all your added operators with a preview of the last message. Your identity strip is docked at the bottom. Tap + Add to add an operator by pubkey.
- Screen B — Conversation: tap any operator to open the encrypted channel. Messages appear as stacked transmission cards. Outbound cards align right with a green right-rule; inbound left. The compose bar is pinned above the home indicator safe area.
- Back affordance: tap ‹ in the top bar to return to the operators list.
All controls are ≥ 44px touch targets. The thread and operators list use momentum scroll.
Security notes
- Rotate keys before sharing with your circle. The keys generated by
scripts/derisk-nip17.tsare throwaway test keys. - localStorage is MVP-only. No passphrase protection yet (M5). Don't use on a device you don't trust.
- Client-side crypto only. Keys and plaintext never leave the browser; no server involved.
- For hardened use, run the
rc-cliRust core directly — no browser attack surface.