This content originally appeared on DEV Community and was authored by Abdul-Qawi Laniyan
Decentralized messaging is the future of censorship-resistant, privacy-first communication.
Whisper Board is a lightweight, anonymous chat app powered by Waku protocol, designed to showcase how easy it is to integrate Waku into a modern web stack.
Why Decentralized Messaging?
Most recently, we’ve seen how fragile centralized systems can be. A single AWS outage in the US-East region, knocked out major apps, even Signal, a privacy-first messenger, across Central and Eastern Europe. Billions of messages delayed, communities cut off, and trust shaken.
Here is a full report on what happened.
When all communication routes depend on a few corporate data centers, resilience becomes an illusion.
Decentralized messaging changes that: it doesn’t rely on one server, company, or geography. Messages flow peer-to-peer, so even if one node fails, the network stays alive. It’s more than just privacy, it’s about robustness, autonomy, and continuity.
In this article, you’ll learn:
- The architecture behind a simple Whisper Board built with waku
- How to connect to and use Waku in your own app
- How messages flow through the network
- How to onboard and contribute as a new developer
- Visual diagrams to aid understanding
Architecture Overview
Diagram: System Components
File structure :
src
├── components
│ ├── MessageCard.tsx
│ └── MessageForm.tsx
├── hooks
├── lib
├── pages
│ ├── Index.tsx
│ └── NotFound.tsx
├── services
│ ├── MessageService.ts
│ └── WakuService.ts
├── types
├── App.css
├── App.tsx
├── index.css
├── main.tsx
├── vite-env.d.ts
.gitignore
bun.lockb
components.json
eslint.config.js
index.html
package-lock.json
package.json
postcss.config.js
README.md
tailwind.config.ts
tsconfig.app.json
tsconfig.json
tsconfig.node.json
vite.config.ts
</pre>
- Frontend: Built in React, styled with Tailwind and shadcn-ui.
-
Hooks:
useWakuhandles node connection,useMessagesmanages sending/receiving. -
Services:
WakuServicemanages the Waku node,MessageServicehandles message flow. - Waku Node: Lightweight node connects to the decentralized network.
Technologies Used
- Vite
- TypeScript
- React
- shadcn-ui
- Tailwind CSS
- Waku JS SDK
How the App Works
Connecting to Waku
The custom hook useWaku.ts initializes and manages the Waku node:
const { isConnecting, isConnected, error } = useWaku();
- On mount, calls
wakuService.initialize()to connect to Waku peers. - Cleans up on unmount via
wakuService.stop().
Code Reference
//src/hooks/useWaku.ts
/* https://github.com/Oladotunlaniyan/whisper-waku-chat/blob/main/src/hooks/useWaku.ts*/
import { useState, useEffect } from "react";
import { wakuService } from "../services/WakuService";
export const useWaku = () => {
const [isConnecting, setIsConnecting] = useState(false);
const [isConnected, setIsConnected] = useState(false);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const initWaku = async () => {
if (wakuService.isReady()) {
setIsConnected(true);
return;
}
setIsConnecting(true);
setError(null);
try {
await wakuService.initialize();
setIsConnected(true);
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to connect to Waku");
} finally {
setIsConnecting(false);
}
};
initWaku();
return () => {
wakuService.stop();
};
}, []);
return { isConnecting, isConnected, error };
};
Messaging Flow
Sequence Diagram: Sending and Receiving a Message
Core Flow
- User submits a message via the UI (
MessageForm). - Hook
useMessagescallsmessageService.publishMessage. -
MessageServiceencodes and pushes the message to the Waku network. - Node listens for incoming messages and updates UI in real time.
Key Code References
//name=src/services/MessageService.ts
export class MessageService {
private getEncoder() {
const node = wakuService.getNode();
return node.createEncoder({ contentTopic: CONTENT_TOPIC });
}
async publishMessage(content: string): Promise<void> {
const node = wakuService.getNode();
const encoder = this.getEncoder();
const message = { content, timestamp: Date.now() };
const payload = this.encodeMessage(message);
await node.lightPush.send(encoder, { payload });
}
async subscribeToMessages(onMessage: (message: WhisperMessage) => void): Promise<() => void> {
const node = wakuService.getNode();
const decoder = this.getDecoder();
await node.filter.subscribe([decoder], (wakuMessage) => {
if (!wakuMessage.payload) return;
const decoded = this.decodeMessage(wakuMessage.payload);
onMessage({ id: `${decoded.timestamp}-${Math.random()}`, content: decoded.content, timestamp: decoded.timestamp });
});
return () => { /* unsubscribe logic */ };
}
}
Onboarding: Steps for Beginner Contributors
Getting Started
- Clone the Repository
git clone https://github.com/Oladotunlaniyan/whisper-waku-chat.git
cd whisper-waku-chat
- Install Dependencies
npm install
- Run the App
npm run dev
- Open http://localhost:8080 in your browser.
-
Edit Code Locally
- Most logic lives in
src/ - Message logic:
src/services/MessageService.ts - Waku node logic:
src/services/WakuService.ts - UI:
src/components/,src/pages/
- Most logic lives in
Contribution Guide
- Follow the onboarding steps above for local development.
- Make sure you have Node.js and npm installed (guide).
- Follow the onboarding steps above for local development.
- Submit issues or pull requests for improvements, bug fixes, or new features.
- For UI tweaks, edit files in
src/components/. - For protocol logic, edit
src/services/WakuService.tsandsrc/services/MessageService.ts.
First-Time Contributor Tips
- Start by reading the README.
- Use the hooks and services as your entry points for understanding message flow.
- To add a feature, create a new component in
src/components/and integrate with hooks/services. - For debugging, use console logs in services and hooks.
- Ask for help or suggestions via GitHub Issues.
Visuals
- System Architecture Diagram (see above)
- Sequence Diagram for Messaging (see above)
- UI Screenshot: (Add your own screenshot or generate one from running the app.)
Conclusion
Whisper Waku Chat is a simple but powerful demo of decentralized, anonymous messaging using Waku.
With a modern React frontend and the Waku JS SDK, it’s easy for new developers to get started and contribute.
Next Steps:
- Fork the repo, run locally, and start hacking!
- Check out the Waku docs for protocol details.
- Join the Waku dev community for support and collaboration.
Further Resources
This is a very simple implementation of the Waku protocol, in subsequent articles I will be increasing functionality and complexity of the whisper board. This includes using new methods, explaining more core concepts etc.
This content originally appeared on DEV Community and was authored by Abdul-Qawi Laniyan

