Roadmap
M0–M8 milestones and the north-star Shortwave hardware device.
Roadmap
Milestones
M0 — De-risk (done)
Goal: Prove the JS crypto before any UI work.
scripts/derisk-nip17.ts — generates two keypairs, sends a NIP-17 gift-wrapped DM, Bob receives and decrypts it over public Nostr relays, prints NIP-17 DERISK PASS.
No hand-rolled crypto. Pure nostr-tools.
M1 — Scaffold (done)
Goal: npm run build clean, npm run dev runs, structure in place.
- Next.js 15 + TypeScript + Tailwind v4 App Router
lib/nostr/,lib/identity/,components/ui/skeleton- Chat and connect route stubs
- Fumadocs
/docssite
M2 — Design foundation (done)
Goal: Locked design language from forged-2 extracted into Forge + wired into Shortwave.
- Forge v0 tokens seeded (
mechaforge/forge—tokens/tokens.css,tokens/tokens.json,tailwind-preset.js) - Shortwave consumes Forge tokens from
lib/forge/tokens.css(source of truth: mechaforge/forge#1) - Space Mono primary instrument font (matches forged-2 exactly)
- Full dark mono palette
--forge-bg … --forge-ink-4+ signal-green--forge-signalaccent rules - 8px grid:
--forge-ctl40px ·--forge-head64px ·--forge-bar96px ·--forge-rail-w296px - Zero radii — sharp/angular everywhere
- Design language documented:
/docs/design-language
M3 — Identity (done)
Goal: Nostr identity generated, persisted, and displayed in the instrument UI.
-
lib/identity/keypair.ts—loadOrCreateIdentity()generates secp256k1 keypair, persists to localStorage (MVP — see docs/threat-model for upgrade path) -
npub bech32 encoding via
nostr-tools/nip19 -
Operator ID derived from pubkey (
OP-XXXXfrom last 4 hex bytes) -
Contacts: add by hex pubkey or npub1… bech32; persisted to localStorage
-
Identity panel in rail (96px, bottom-aligned with compose bar)
-
Geometric avatar marks: YOU / DETHKLAW / VOXEL / NULLKEY / GHOST
-
Relay status displayed in header (tick marks, connected / total count)
TODO mechaforge/shortwave#13: source operator_id + avatar from Mini Mecha profiles; gate access.
M4 — Core chat — columnar ledger (done)
Goal: Real E2E NIP-17 send + receive, forged-2 columnar ledger UI.
lib/nostr/client.ts— realsendDM(NIP-17 gift-wrap vianip17.wrapEvent) +subscribeDMs(kind:1059 subscription withunwrapEvent)- Multi-relay: wss://relay.damus.io + wss://nos.lol (+ optional ws://127.0.0.1:7777 via
NEXT_PUBLIC_LOCAL_RELAY) - Relay connection pool (shared across page session); dedup by event ID across relays
- Ephemeral — no plaintext written to disk; in-memory session only
- Columnar ledger thread (subgrid 5-column: time · avatar · operator · transmission · state)
- Green left-rule + wash on outbound rows; no bubbles
- Continuation rows (same sender within 2 min → blank avatar/operator cols)
- Optimistic local echo on send
- Channel header: operator name + operator ID + encryption/retention HUD metrics
- Session note (key verified · E2E · no transcript)
M5 — Key lifecycle
Goal: Passphrase-locked key export/import; key rotation.
- Export sk encrypted with user passphrase (WebCrypto AES-GCM)
- Import from passphrase-locked file
- Key rotation warning when key is old
M6 — Mobile layout + PWA (done)
Goal: Mobile-native responsive layout + installable PWA on iOS/Android.
- Responsive contract: Desktop (≥ 600px) keeps forged-2 columnar ledger unchanged. Mobile (< 600px) uses approved
mobile-1stacked transmission cards layout. - Mobile layout: App bar (wordmark or back+peer) → Screen A (operators list with identity strip) → tap → Screen B (transmission card thread + pinned compose bar). Same
lib/nostrsend/receive engine — different layout only. - PWA manifest (
app/manifest.ts): name "Shortwave",display: standalone, dark theme/background, maskable 192/512 icons. - Service worker (Serwist 9.x, MIT): app-shell cache only. Message data is never cached — ephemeral by design.
- iOS niceties:
apple-mobile-web-app-capable,black-translucentstatus bar,viewport-fit=coverfor safe-area insets,apple-touch-icon. - Production placeholder icon: geometric signal mark + SW monogram in Forge techwear language (
#0c0d0ebg,#4ea88baccent). Rod designs the hero brand mark in-house — this is a clearly-labelled placeholder. - Safe-area handling: compose bar and identity strip both use
env(safe-area-inset-bottom)for home-indicator clearance. Top usesenv(safe-area-inset-top)for notch/Dynamic Island. - Touch targets: all controls ≥ 44px.
- Momentum scroll on thread and operators list (
-webkit-overflow-scrolling: touch).
M7 — Relay configuration UI
Goal: Users can add/remove relays, test connectivity.
M8 — Groups (MLS)
Goal: Small-group encrypted channels (3–10 people).
- OpenMLS (RFC 9420) for full PCS + forward secrecy
- Group key management UI
North-star: the Shortwave hardware device
The long-term vision is a dedicated Shortwave device — a small, purpose-built appliance that removes the hosted-web-app delivery attack surface.
Phase 1: Pi appliance (earnable now)
A Raspberry Pi running the resilient-comms Rust core headless — pre-provisioned with identity, relay list, and contact keys.
- Software exists today (
rc-cliinresilient-comms) - Hardware: Pi Zero 2W + USB keyboard + small OLED or e-ink display
- Cost: ~A$50–80/unit
Phase 2: Curated kit
Curated BOM (Pi + LoRa HAT + enclosure + pre-flashed SD card).
Phase 3: Custom device (earned by usage)
Custom device with integrated LoRa radio and secure element. North-star only — earned by proven usage.
Current state (2026-06-09)
- Rust core: dogfoodable — encrypted 2-person messenger works, relay-redundant
- Radio software tier: 7/7 impairment tests passing
- Web app: M0 + M1 + M2 + M3 + M4 + M6 done — forged-2 columnar ledger + mobile-1 stacked cards + installable PWA
- Radio hardware: 2 Meshtastic nodes ordered