A peer-to-peer personal knowledge base that syncs bidirectionally across your devices in real-time without a central server. Built with BEAM (Elixir) for distributed systems and React for the frontend.
- π Peer-to-Peer Mesh Network: No central server, devices connect directly
- π Real-Time Sync: Changes propagate instantly when devices are connected
- π΄ Offline-First: All data available locally, no internet required
- β‘ CRDT-Based: Conflict-free replicated data types ensure eventual consistency
- π Privacy-Focused: Your data stays on your devices
- π BEAM-Powered: Leverages Erlang's distributed computing capabilities
- Phoenix Framework: REST API and WebSocket server
- Distributed Erlang: Automatic node discovery and mesh networking
- Mnesia: Distributed replicated database
- CRDTs: Last-Write-Wins Register and Observed-Remove Set for conflict resolution
- libcluster: Gossip-based automatic node discovery
- Horde: Distributed process registry
- Vite: Fast development and optimized builds
- Zustand: Lightweight state management
- TypeScript: Type-safe development
- Heroicons: Beautiful UI icons
- Elixir 1.15+ and Erlang/OTP 26+
- Node.js 18+ and npm
- Make (for convenience)
# Install all dependencies
make install# Start both backend and frontend
make dev
# Or start them separately:
make backend # Backend on http://localhost:4000
make frontend # Frontend on http://localhost:5173The backend API will be available at http://localhost:4000/api and the frontend at http://localhost:5173.
# Build both backend and frontend
make build- Click the + button in the sidebar
- Start typing in the title and content fields
- Changes are saved automatically
- Add tags using the tag input at the bottom
To test distributed sync, run multiple backend instances:
# Terminal 1 - Node 1
cd backend
NODE_NAME=whisp1@127.0.0.1 PORT=4000 make dev
# Terminal 2 - Node 2
cd backend
NODE_NAME=whisp2@127.0.0.1 PORT=4001 make devThe nodes will automatically discover each other via gossip protocol and start syncing notes.
GET /api/notes- List all notesPOST /api/notes- Create a noteGET /api/notes/:id- Get a specific notePUT /api/notes/:id- Update a noteDELETE /api/notes/:id- Delete a noteGET /api/mesh/status- Get mesh network statusGET /api/mesh/nodes- List connected nodesGET /health- Health check
Whisps/
βββ backend/ # Elixir/Phoenix backend
β βββ lib/
β β βββ whisp/ # Core business logic
β β β βββ crdt/ # CRDT implementations
β β β βββ mesh/ # Mesh networking
β β β βββ storage/ # Mnesia storage
β β β βββ sync/ # Sync engine
β β β βββ notes/ # Notes management
β β βββ whisp_web/ # Web layer
β β βββ controllers/
β β βββ channels/
β βββ config/
β βββ test/
β βββ Makefile
βββ frontend/ # React frontend
β βββ src/
β β βββ components/ # React components
β β βββ store/ # Zustand stores
β β βββ lib/ # Utilities
β β βββ types.ts # TypeScript types
β βββ public/
β βββ Makefile
βββ ARCHITECTURE.md # Detailed architecture docs
βββ Makefile # Root makefile
make help # Show available commands
make install # Install dependencies
make dev # Start dev servers
make build # Build for production
make test # Run tests
make clean # Clean build artifactscd backend
make dev # Start Phoenix server
make test # Run tests
make format # Format code
make compile # Compile project
make shell # Start IEx shellcd frontend
make dev # Start Vite dev server
make build # Build for production
make preview # Preview production build
make format # Format codeEdit backend/config/runtime.exs:
# Node name and cookie
config :whisp,
node_name: :whisp@127.0.0.1,
cookie: :secret_cookie
# Cluster topology
config :libcluster,
topologies: [
whisp_gossip: [
strategy: Cluster.Strategy.Gossip,
config: [port: 45892, ...]
]
]Create frontend/.env:
VITE_API_URL=http://localhost:4000/api
# Backend tests
cd backend && make test
# Frontend tests (when configured)
cd frontend && make testBuild as an Elixir release:
cd backend
mix release
./_build/prod/rel/whisp/bin/whisp startDocker support coming soon for containerized deployment.
- CRDTs: Notes use Last-Write-Wins Registers for title/content and Observed-Remove Sets for tags
- Vector Clocks: Track causality to detect concurrent updates
- Mnesia Replication: Distributed database automatically replicates across nodes
- Gossip Protocol: Nodes discover each other via UDP multicast
- Phoenix PubSub: Real-time change propagation to connected clients
- Offline Queue: Changes queued locally when offline, synced on reconnection
Contributions welcome! Please read the architecture documentation first.
MIT
- Built with Phoenix Framework
- Inspired by Conflict-Free Replicated Data Types research
- Powered by the BEAM ecosystem