A decentralized forum that runs entirely over Meshtastic LoRa mesh radio — no internet, no servers, no cloud. Nodes talk directly to each other via USB-connected LoRa devices.
Each instance of Blackbox Board is an independent node. Nodes discover each other through the mesh network and synchronize their forum state peer-to-peer.
Communication stack:
Browser (Vanilla JS)
↕ REST API (polling every 5s)
Node.js HTTP server (server.js)
↕ JSON lines over stdin/stdout
Python serial bridge (bridge.py)
↕ USB serial
Meshtastic LoRa device
↕ 915 / 868 MHz radio
Remote Meshtastic device → Remote node
Protocol highlights:
- Forum messages are encoded in a compact format (
mf1) to fit within LoRa's ~220-byte MTU - Messages larger than the safe payload size are chunked and reassembled automatically
- A two-phase sync handshake (
sync_offer → sync_turn → sync_done) avoids sending data the peer already has - Each node tracks peer knowledge to minimize redundant transmissions
- Forum state is persisted to JSON files and survives restarts
| Component | Version |
|---|---|
| Node.js | 14 or later |
| Python | 3.11 or later |
| Meshtastic Python lib | pip install meshtastic |
| Hardware | 1–2 USB Meshtastic LoRa modules |
npm install
npm run start-singleOpens at http://127.0.0.1:7861
npm run start- Node A →
http://127.0.0.1:7861 - Node B →
http://127.0.0.1:7862
You can test the UI and forum logic without physical LoRa hardware by running two nodes locally. The bridge will report that no device is detected, but the forum, topics, posts, and sync UI all work normally — you just won't have radio transmission.
To simulate a full sync between two local nodes:
npm run start— starts both nodes- Open
http://127.0.0.1:7861andhttp://127.0.0.1:7862in separate tabs - Create topics and posts on one node
- Trigger a sync from the other node's sidebar
For performance testing:
node test-sync-performance.js| Variable | Default | Description |
|---|---|---|
PORT |
7861 |
HTTP server port |
DATA_DIR |
./data |
Directory for persistent JSON state |
INSTANCE_LABEL |
— | Display name shown in the UI |
MESHTASTIC_PORT |
auto-detect | Explicit serial port path |
MESH_PORT_INDEX |
0 |
Index for auto-detected port (0 or 1) |
FORUM_CHUNK_SIZE |
150 |
Chunking hint in bytes |
MESH_TEXT_PAYLOAD_MAX_BYTES |
220 |
LoRa packet size cap |
NO_OPEN_BROWSER |
— | Set to any value to suppress auto-open |
| Key | Action |
|---|---|
| F1 | New Topic |
| F2 | Forum view |
| F3 | Sync peers |
| F4 | Logs |
| F5 | Settings |
T |
Toggle dark/light theme |
data/
forum.json # Topics, posts, seen envelope IDs
bootstrap.json # Selected peer, hello state, peer knowledge
local-identity.json # Ed25519 key pair + author ID
logs.jsonl # Append-only event log
