Browser extension for did:nostr and Solid authentication
Podkey is a beautiful, secure browser extension for did:nostr and Solid authentication. It provides a NIP-07-compatible Nostr wallet that enables seamless authentication to Solid pods using did:nostr identities, while remaining fully compatible with the broader Nostr ecosystem.
- 🎨 Beautiful, modern UI with soft gradients and smooth animations
- 🔐 Enhanced security with proper key validation and storage
- ⚡ Built-in Solid authentication (NIP-98) for seamless pod access
- 📊 Trust management with per-origin permissions
- 🌈 Delightful user experience with intuitive design
- did:nostr identity - Full support for did:nostr decentralized identifiers
- Solid authentication - Zero-redirect authentication to Solid servers using did:nostr
- Automatic signing - Automatic signing for trusted Solid pods
- WebID linking - Link did:nostr identities to Solid WebIDs (coming soon)
-
Clone the repository:
git clone https://github.com/JavaScriptSolidServer/podkey.git cd podkey -
Install dependencies:
npm install
-
Build the extension:
npm run build
-
Load in Chrome:
- Open
chrome://extensions/ - Enable "Developer mode" (top-right toggle)
- Click "Load unpacked"
- Select the
podkeydirectory
- Open
-
Test it:
- Visit the test page to verify everything works
- Click the Podkey icon to generate or import a key
- ✅ NIP-07 Provider - Full
window.nostrAPI implementation - ✅ Key Generation - Secure cryptographic key generation using
@noble/secp256k1 - ✅ Key Import - Import existing 64-char hex private keys
- ✅ Event Signing - Sign Nostr events with Schnorr signatures
- ✅ Trust Management - Per-origin permissions with auto-approval
- ✅ Beautiful UI - Soft gradients, smooth animations
- ✅ 64-char Hex Keys - Proper did:nostr format compatibility
- 🔜 NIP-04 encryption/decryption
- 🔜 Multiple identity support
- 🔜 Relay management
- 🔜 Activity history
- 🔜 nsec/npub Bech32 encoding
- 🔜 WebID linking
- 🔜 Backup & recovery
- 🔜 Automatic NIP-98 authentication for Solid servers
// Check if Podkey is available
if (window.nostr) {
// Get your public key
const pubkey = await window.nostr.getPublicKey()
console.log('Your public key:', pubkey)
// Sign an event
const event = {
kind: 1,
created_at: Math.floor(Date.now() / 1000),
tags: [],
content: 'Hello from Podkey! 🔑'
}
const signed = await window.nostr.signEvent(event)
console.log('Signed event:', signed)
}Visit the interactive test page to:
- Verify extension installation
- Test key generation and import
- Test event signing with various event types
- View real-time diagnostics and logs
┌─────────────────────────────────────────┐
│ Browser Extension (Podkey) │
│ │
│ ┌───────────────────────────────────┐ │
│ │ Popup UI (popup/) │ │
│ │ - Key generation/import │ │
│ │ - Trust management │ │
│ │ - Settings & identity display │ │
│ └───────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────┐ │
│ │ Background Worker (src/) │ │
│ │ - Key storage (storage.js) │ │
│ │ - Event signing (crypto.js) │ │
│ │ - Permission management │ │
│ └───────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────┐ │
│ │ Content Script (src/injected.js)│ │
│ │ - Injects window.nostr │ │
│ │ - Bridges page ↔ extension │ │
│ └───────────────────────────────────┘ │
└─────────────────────────────────────────┘
- 🔒 Private keys never leave the extension - Stored in Chrome's secure local storage
- 🔒 User permission required - Every signing operation requires approval (auto-approved for now)
- 🔒 Per-origin trust - Granular permissions for each website
- 🔒 64-char hex validation - All keys validated for proper did:nostr format
- 🔒 Secure event signing - Uses
@noble/secp256k1v3.0.0 with Schnorr signatures
podkey/
├── manifest.json # Extension manifest (MV3)
├── package.json # npm package configuration
├── src/
│ ├── background.js # Service worker (message handling)
│ ├── crypto.js # Key generation & signing
│ ├── storage.js # Secure key storage
│ ├── injected.js # Content script (page bridge)
│ └── nostr-provider.js # window.nostr implementation
├── popup/
│ ├── popup.html # Popup UI structure
│ ├── popup.css # Beautiful styling
│ └── popup.js # Popup logic
├── test-page/
│ └── index.html # Interactive test page
├── scripts/
│ └── bundle.js # Build script for dependencies
└── icons/ # Extension icons
- Cryptography: @noble/secp256k1 v3.0.0
- Hashing: @noble/hashes v1.8.0
- Bundling: esbuild
- Storage: Chrome Storage API
- UI: Vanilla JavaScript + CSS Gradients
- Manifest: V3 (latest)
# Install dependencies
npm install
# Build the extension (bundles dependencies)
npm run build
# Lint code
npm run lint
# Run tests
npm test-
Build the extension:
npm run build
-
Load in Chrome (see Installation above)
-
Visit the test page:
- Local: Open
test-page/index.htmlin your browser - Online: https://javascriptsolidserver.github.io/podkey/test-page/
- Local: Open
-
Check the console for any errors
Podkey is built for did:nostr and Solid authentication. All public keys are proper 64-character hexadecimal strings, making them fully compatible with the did:nostr specification:
const pubkey = await window.nostr.getPublicKey()
const did = `did:nostr:${pubkey}`
// did:nostr:3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459dThis enables:
- ✅ did:nostr decentralized identifiers per W3C specification
- ✅ Solid pod authentication using did:nostr identities
- ✅ Cross-platform identity portability
- ✅ Verifiable credentials and authentication
Returns the user's public key (64-char hex).
const pubkey = await window.nostr.getPublicKey()Signs a Nostr event. Shows permission prompt if origin is not trusted.
const signed = await window.nostr.signEvent({
kind: 1,
created_at: Math.floor(Date.now() / 1000),
tags: [],
content: 'Hello!'
})Returns relay configuration (coming soon).
const relays = await window.nostr.getRelays()We love contributions! Here's how to get started:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests if applicable
- Ensure tests pass (
npm test) - Commit (
git commit -m 'Add amazing feature') - Push (
git push origin feature/amazing-feature) - Open a Pull Request
- 🎨 Icon design (16px, 48px, 128px)
- 📝 Documentation improvements
- 🧪 Additional test coverage
- 🌐 i18n/localization
- ✨ NIP-04 encryption
- 🔧 Bug fixes
- 🚀 Performance improvements
- Make sure Developer Mode is enabled in
chrome://extensions/ - Check that you selected the correct directory
- Look for errors in the Chrome console
- Reload the page after installing Podkey
- Check that the extension is enabled
- Look for conflicts with other Nostr extensions
- Check the browser console for errors
- Make sure you've generated or imported a key
- Check the extension console (click "service worker" in chrome://extensions)
- Look for permission prompts that may be blocked
- Make sure all dependencies are installed:
npm install - Check Node.js version (needs >= 18.0.0)
- Try deleting
node_modulesandpackage-lock.json, thennpm installagain
AGPL-3.0 License - see LICENSE for details
- Built with 💜 for the Nostr and Solid communities
- Inspired by nos2x and the NIP-07 specification
- Part of the JavaScriptSolidServer ecosystem
- Cryptography powered by @noble
- GitHub: https://github.com/JavaScriptSolidServer/podkey
- Issues: https://github.com/JavaScriptSolidServer/podkey/issues
- Test Page: https://javascriptsolidserver.github.io/podkey/test-page/
- did:nostr Specification: https://nostrcg.github.io/did-nostr/
- NIP-07 Spec: https://github.com/nostr-protocol/nips/blob/master/07.md
- NIP-98 Spec: https://github.com/nostr-protocol/nips/blob/master/98.md
- Solid Project: https://solidproject.org/
Made with 🔑 by the JavaScriptSolidServer team
Podkey v0.0.7 - Your keys, your identity, your data