Secure time-locked messaging powered by Nostr and drand timelock encryption
A decentralized application that lets you create encrypted time capsules that automatically unlock at specified future times. Built with cutting-edge cryptographic primitives and the Nostr protocol for a truly censorship-resistant experience.
- β° Time-locked Encryption - Messages unlock automatically at predetermined times using drand timelock encryption
- π End-to-End Security - NIP-44 encryption for private messages with perfect forward secrecy
- π‘ Decentralized - Built on Nostr protocol for censorship resistance and decentralization
- π― Multi-mode Support - Public and private time capsules with different encryption schemes
- β‘ Real-time Updates - Live event streaming and automatic unlock notifications
- π± Responsive Design - Optimized for desktop, laptop, tablet, and mobile devices
- π Auto-retry Logic - Robust error handling with exponential backoff
- π Performance Monitoring - Real-time metrics and connection status
- π¨ Modern UI - Clean, intuitive interface with loading states and notifications
- π‘οΈ Security First - CSP headers, input validation, and secure key management
- Frontend: SvelteKit 2.x with TypeScript
- Cryptography: tlock-js, @noble/secp256k1, @noble/hashes
- Protocol: Nostr (NIPs 01, 04, 44, 59)
- Timelock: drand Quicknet network
- Deployment: Netlify with edge functions
- Time Capsule Service - Core business logic for capsule creation/management
- Relay Manager - Dynamic relay selection and failover
- Event Handler - Real-time Nostr event processing
- Unlock Scheduler - Automated timelock monitoring and unlocking
- Security Layer - Input validation, CSP, and audit logging
- Node.js >= 22.12.0 (see
.nvmrc) - npm or yarn
- Modern browser with WebSocket support
-
Clone the repository
git clone https://github.com/Shugur-Network/time-capsules.git cd time-capsules -
Install dependencies
npm install
-
Configure environment
cp .env.example .env.local
Edit
.env.localwith your configuration:# Nostr Relays (comma-separated list) VITE_NOSTR_RELAYS=wss://shu01.shugur.net,wss://shu02.shugur.net,wss://shu03.shugur.net # Drand API URL for timelock encryption VITE_DRAND_URL=https://api.drand.sh # Application limits and timeouts VITE_MAX_CAPSULE_SIZE=1048576 VITE_DEFAULT_UNLOCK_DELAY=86400 VITE_WS_RECONNECT_DELAY=1000 VITE_MAX_RECONNECT_ATTEMPTS=5 VITE_NOTIFICATION_TIMEOUT=5000
-
Start development server
npm run dev
Open http://localhost:5173 in your browser.
npm run build
npm run preview- Login with your Nostr private key (nsec or hex format)
- Choose mode:
- Public: Viewable by anyone when unlocked
- Private: Encrypted for specific recipients
- Set content: Write your message (supports text, max 1MB)
- Set unlock time: Choose when the capsule should unlock
- Add recipients (private mode only): Enter npub addresses
- Create: Your capsule will be encrypted and published
- Home: View all your created capsules
- View: Browse all accessible capsules
- Real-time: Automatic updates when capsules unlock
- Notifications: Get notified of unlock events
- NIP-44 Encryption: Industry-standard encryption for private messages
- Timelock Encryption: Mathematical guarantee of time-based unlocking
- Key Management: Secure local storage with browser APIs
- Input Validation: Comprehensive validation and sanitization
- Event Streaming: Real-time updates via WebSocket
- Smart Caching: Efficient drand beacon caching
- Connection Management: Automatic reconnection and failover
- Responsive Design: Optimized for all screen sizes
| Variable | Description | Default |
|---|---|---|
VITE_NOSTR_RELAYS |
Comma-separated relay URLs | Shugur network relays |
VITE_DRAND_URL |
drand API endpoint | https://api.drand.sh |
VITE_MAX_CAPSULE_SIZE |
Max capsule size in bytes | 1048576 (1MB) |
VITE_DEFAULT_UNLOCK_DELAY |
Default delay in seconds | 86400 (24h) |
VITE_WS_RECONNECT_DELAY |
WebSocket reconnect delay (ms) | 1000 |
VITE_MAX_RECONNECT_ATTEMPTS |
Max reconnection attempts | 5 |
VITE_NOTIFICATION_TIMEOUT |
Notification timeout (ms) | 5000 |
The app uses the Shugur relay network by default but supports any Nostr-compatible relays:
// Add custom relays
const customRelays = [
'wss://relay.damus.io',
'wss://nos.lol',
'wss://relay.snort.social'
];Built-in security features include:
- Content Security Policy (CSP)
- Input validation and sanitization
- XSS protection
- CSRF protection
- Secure headers
- Connect repository to Netlify
- Set build settings:
- Build command:
npm run build - Publish directory:
.svelte-kit/output/client - Node version:
22.12.0
- Build command:
- Configure environment variables in Netlify dashboard
- Deploy: Automatic deployments on git push
# Build for production
npm run build
# Deploy the .svelte-kit/output/client directory
# to your static hosting providerFROM node:22.12-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "run", "preview"]- Uses drand Quicknet network for time-based unlocking
- Chain:
52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971 - Period: 3 seconds per beacon
- Provides mathematical guarantee of unlock timing
- Authenticated encryption with ChaCha20-Poly1305
- HKDF key derivation with conversation keys
- Perfect forward secrecy for private messages
- NIP-01: Basic protocol flow
- NIP-04: Encrypted direct messages (legacy)
- NIP-44: Modern encryption standard
- NIP-59: Gift wrap for enhanced privacy
- Kind 1041: Time capsule events
- Kind 1059: Gift-wrapped private capsules
- Custom tags for timelock metadata
- Tree Shaking: Optimal bundle size with Vite
- Code Splitting: Lazy loading of components
- Caching Strategy: Smart drand beacon caching
- Connection Pooling: Efficient WebSocket management
src/
βββ lib/
β βββ components/ # Svelte components
β βββ services/ # Business logic services
β βββ stores/ # Svelte stores (state management)
β βββ utils/ # Utility functions
β βββ config/ # Configuration files
β βββ types/ # TypeScript type definitions
β βββ styles/ # Global styles
βββ routes/ # SvelteKit routes
βββ app.html # HTML template
- TimeCapsuleService: Core capsule operations
- NostrWebSocketService: WebSocket connection management
- RelayManager: Dynamic relay selection
- CapsuleEventHandler: Event processing pipeline
- TimeUnlockScheduler: Automated unlock monitoring
# Development server
npm run dev
# Type checking
npm run check
npm run check:watch
# Production build
npm run build
# Preview production build
npm run preview
# Run tests
npm run test# Run all tests
npm run test
# Manual testing with provided keys
# See .env.example for test relay configurationWe welcome contributions! Please see our contributing guidelines:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
- Follow TypeScript best practices
- Use conventional commit messages
- Add tests for new features
- Update documentation as needed
- Ensure responsive design compatibility
This project is licensed under the MIT License - see the LICENSE file for details.
- Nostr Protocol - Decentralized social protocol
- drand - League of Entropy randomness beacon
- SvelteKit - Web application framework
- Shugur Network - Relay infrastructure
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: Project Wiki
Built with β€οΈ by the Shugur Network team
Empowering the future of decentralized, time-locked communication