Thank you for your interest in contributing! This extension is a NIP-07 signer, encrypted key vault, Lightning/WebLN wallet, and profile/mute/relay manager for Nostr web clients.
- Node.js 18+ (for running tests)
- Chrome or Firefox browser
- Basic familiarity with browser extension development (MV3)
git clone https://github.com/user/nostr-wot-extension.git
cd nostr-wot-extensionNo build step required — the extension uses plain ES modules with no bundler.
Chrome:
- Open
chrome://extensions - Enable "Developer mode"
- Click "Load unpacked" and select the project directory
Firefox:
- Open
about:debugging#/runtime/this-firefox - Click "Load Temporary Add-on"
- Select any file in the project directory (e.g.,
manifest.json)
node --test tests/Tests use Node.js native node:test module with browser API mocks in tests/helpers/.
├── background.ts # Service worker — thin dispatcher over lib/bg/
├── content.ts # Content script (ISOLATED world) — message bridge
├── inject.ts # Page script (MAIN world) — window.nostr + window.webln
├── lib/
│ ├── bg/ # Background handler modules (nip07, vault, wallet, relay, profile, publish, …)
│ ├── crypto/ # Pure TS crypto (secp256k1, schnorr, NIPs, bip32/39)
│ ├── wallet/ # Lightning wallet providers (NWC, LNbits, provisioning)
│ ├── storage.ts # IndexedDB relay-list cache + pubkey ID mapping
│ ├── vault.ts # AES-256-GCM encrypted key vault
│ ├── signer.ts # NIP-07 signing coordinator
│ ├── permissions.ts # Per-domain / per-account permission storage
│ ├── accounts.ts # Account creation/import
│ ├── relayUtils.ts # Relay URL normalization
│ └── browser.ts # Cross-browser compatibility shim
├── src/popup/ # Extension popup (tab-based UI)
├── src/onboarding/ # First-run setup wizard
├── src/prompt/ # Signing request approval popup
├── docs/ # Technical documentation (see docs/README.md)
└── tests/ # Node.js test suite
- Check existing issues first
- Create a failing test case if possible
- Fix the bug
- Verify existing tests still pass:
node --test tests/
- Open an issue to discuss the feature first
- Reference the relevant NIP if applicable
- Follow existing patterns in the codebase
- Add tests for new backend logic
git checkout -b feature/my-changeUse these branch name prefixes:
feature/— new functionalityfix/— bug fixesdocs/— documentation
- Follow existing code style (no linter configured — match surrounding code)
- Use plain ES modules, no build tools
- Use optional chaining (
?.) for DOM access - Zero private keys after use (
privkey.fill(0)intry/finally) - Gate privileged message handlers via
PRIVILEGED_METHODSSet - No external dependencies — the extension is self-contained
node --test tests/For UI changes, manually test in Chrome and Firefox:
- Open the popup and verify all tabs work
- Test dark mode (system preference)
- Test with 0 accounts, 1 account, and multiple accounts
- Test with both signing accounts and read-only accounts
- Write a clear PR title (e.g., "wallet: fix LNbits balance parsing")
- Describe what changed and why
- Include screenshots for UI changes
- Reference any related issues
Read docs/architecture.md for the full technical reference. Key points:
- No build system — files are loaded directly by the browser
- Message passing — inject.js → content.js → background.js via
postMessageandruntime.sendMessage - Privileged methods — vault, permission, and management operations are gated to internal extension pages via sender ID verification
- Per-account databases — each account gets its own IndexedDB named
nostr-wot-{accountId} - Precomputed graph — distances are cached in typed arrays for O(1) lookup after first query
- Never log or expose private keys
- Always zero
Uint8Arrayprivate keys after use - Validate all inputs from web pages (content script allowlists)
- Use
sender.idchecks for privileged operations - Rate-limit external-facing API methods
- Verify event signatures before trusting relay data
Be respectful, constructive, and focused on building great software. Technical disagreements are welcome; personal attacks are not.