Pager is an open-source printed circuit board by justinlindh, from the justinlindh/bramble repository on GitHub, published under the MIT licence. It is a 2-layer board of 96 × 50 mm with 97 parts on 101 nets, routed with 898 tracks and 129 vias.
It is built around the ATGM336H-5N31, ESP32-S3-WROOM-1-N8R2 and LORA1262-915TCXO, with the DW01A, FS8205A and USBLC6-2SC6 among its other parts. Its parts include 26 capacitors, 21 resistors, 10 diodes, 8 ICs and 5 transistors. It belongs with the radio and wireless boards and the ESP32 boards of this library.
Privacy-first LoRa mesh networking for ESP32-S3, built with ESP-IDF.
Bramble is an encrypted, multi-hop mesh protocol and firmware stack for long-range, infrastructure-free communication. It is designed for resilient field use while reducing metadata exposure; docs/SECURITY-MODEL.md documents exactly what is and is not protected.
Bramble is a secure LoRa mesh protocol and firmware implementation for ESP32-S3 devices with SX1262 radios. It focuses on practical private communications in constrained, lossy RF environments, with explicit handling for routing, retransmission, airtime limits, and node identity.
The firmware runs on real hardware (including T-Deck Plus and Heltec V3/V4 targets), with host-side testing used to validate protocol behavior continuously during development.
What Makes Bramble Different
Compared to Meshtastic and MeshCore-style systems, Bramble leans on privacy and on authenticated, confirmable delivery at the protocol level. It is an early project: functional and hardware-verified on a small bench mesh, but not yet field-tested at scale. The claims below are what the code on main does, with the honest limits stated alongside.
Dual-substrate routing. Two forwarding substrates ship, and a runtime toggle (s_flood_transport, default off) selects between them. Reactive AODV is the default: RREQ/RREP discovery, a cached route table, reverse-route breadcrumbs learned from DATA, intermediate-node RREP, and route-forwarded ACKs. DM airtime is O(path_length), not O(N). Flooding is the opt-in alternative: hop-limited (configurable, default 8, range 1..32), deduplicated, airtime-budget-gated unicast/channel floods with a flooded ACK for route-free sender confirmation. Both substrates are first-class; the toggle picks one.
Authenticated traffic (wire v4), no insecure bootstrap. DATA frames and the control plane (RREP, RERR, ACK, delivery receipt, beacon) carry a network-key HMAC that relays verify before acting; a captured frame cannot be forged or replayed by an outsider on a provisioned network. There is no public default key: an unprovisioned node is inert (fail-closed) and refuses to emit or accept any authenticated frame until a real per-fleet key is provisioned (minted on-device or pasted in). Residual: any network-key holder is an insider and can still forge these MACs, narrowed by per-node identity rather than by provisioning (docs/SECURITY-MODEL.md).
Confirmed delivery. Acknowledged tiers report DELIVERED vs FAILED to the sender rather than fire-and-forget. Honest envelope: reactive holds confirmed delivery at small, dense scale; the flooded confirmation holds at low-to-moderate message load and degrades at high load because flood airtime scales as O(messages x nodes). It is explicitly not a high-load guarantee.
End-to-end direct messages. DMs use per-peer AES-256-GCM sessions keyed by a role-symmetric quad-DH X25519 exchange (components/dm_session), and are not readable by other channel members. Each message has forward secrecy from a symmetric HKDF ratchet, with a coarse per-epoch DH ratchet for post-compromise recovery. An identity-bound 7-digit safety number (SAS) lets two people verify a contact out of band; the verification UX ships in the web client, the T-Deck graphical build, and on the e-paper pager itself (a per-peer view under the Nodes screen with a two-step confirm), and verified state is remembered per contact and cleared automatically if a contact's identity key changes. See docs/SECURITY-MODEL.md for the threat model and residuals.
Channel encryption + multi-hop channels. Channel messages use AES-256-GCM (AEAD) with the channel ID hidden inside the ciphertext, and they relay multi-hop via the flood relay.
Privacy-first routing. Route-request sources are pseudonymized per query, so forwarded route requests do not carry the originator's address.
Airtime budgeting: every transmission goes through one budget-gated TX path (components/radio/tx_gate.c) with real time-on-air costing, per-tier token buckets, and regional duty-cycle caps enforced where the frequency plan requires them (for example EU 868 at 1%).
3-tier reliability model: Broadcast (fire-and-forget), Normal (acknowledged, 3 retries with backoff), and Critical (8 retries plus delivery receipts carrying the relay path).
Cryptographic node identity + optional fleet trust anchor. Each node has an Ed25519 identity whose 4-byte address is the hash of its own public key (SHA-256(ed25519_pub)[0:4]), so an address cannot be claimed without the matching key: address impersonation is a preimage search, not a TOFU race. Nodes flood self-signed identity attestations that peers verify and TOFU-pin, refusing and counting any later conflicting key for a pinned address. An optional per-fleet trust anchor (an operator-held Ed25519 key that endorses each member's identity with a cert) closes Sybil identity minting on an anchored mesh, because an anchored node only pins peers carrying a cert its anchor signed. Residuals stated in the same breath: a compromised endorsed insider stays a valid member (endorsement is admission control, not behavioral trust), the anchor seed is the fleet's trust root and its custody is the whole scheme, and an un-anchored mesh keeps unforgeable but free-to-mint identities (docs/trust-anchor.md, docs/SECURITY-MODEL.md).
Attested roll-call. An initiator broadcasts a roll-call and every member answers with an Ed25519 identity-signed unicast, building a per-member ledger with relay paths (bramble.startRollCall / bramble.getRollCall, with a panel in the web client). An anchored mesh audits against the endorsed member set; an un-anchored mesh reports observed responders only. A signature proves an answer and absence proves nothing; both initiation and answering are rate-limited because a roll-call costs N unicast answers. Verified by host tests and the collision-modeled simulator; no field deployment (docs/rollcall.md).
Deployment digital twin. Each node exports its observed topology over RPC (bramble.exportTopology), and the simulator's twin subcommand replays that deployment against the collision model: capacity (delivery rate vs offered load) and which single node's loss partitions the mesh. The twin replays observed links at a moment in time; it predicts nothing about unplaced nodes, and its results are simulation (docs/digital-twin.md).
Browser playground.make playground boots the actual firmware binary as a small virtual fleet on a simulated ether, with a guided tour through provisioning (including the fail-closed inert state), multi-hop relay, SAS verification, and a delivery receipt. First contact needs no hardware and no toolchain; a browser fleet is not a field deployment (docs/playground.md).
Store-and-forward mailbox: offline nodes receive queued messages when they rejoin the mesh.
Location sharing with privacy tiers: presence, zone (a 0.003° by 0.006° cell, about 334 m north-south and 668 m east-west at the equator), or exact; per-peer control over what you share and with whom. Location payloads are AES-256-GCM encrypted end to end and padded to a fixed size so the ciphertext does not leak which tier was chosen; timing and the fact that a node shares location remain observable (docs/SECURITY-MODEL.md).
Browser-based flashing: flash firmware to new devices directly from the web, no toolchain required.
Bramble includes a web client for live network operation and monitoring. It provides real-time chat (including delivery badges), map-based peer location views, neighbor and route visualization, traffic monitoring, channel management, and radio configuration.
See docs/webapp/chat.md for current web client behavior and usage notes. To run it from source, cd webapp && npm ci && npm run dev; webapp/README.md covers the dev workflow, the WiFi-transport backend, and the Electron builds.
A desktop app (Linux, Windows, macOS) is also available, built from the same webapp. It connects directly to nodes on your local network instead of going through a hosted proxy, and can discover nodes on the LAN automatically. See docs/webapp/desktop.md.
Hardware Targets
Board
MCU
Display
Input
Radio
Audio
Status
Heltec WiFi LoRa 32 V3
ESP32-S3
0.96" SSD1306 OLED (128x64)
Buttons
SX1262
N/A
Running target
Heltec WiFi LoRa 32 V4
ESP32-S3
OLED + optional L76K GNSS
Buttons
SX1262
N/A
Running target
LilyGo T-Deck Plus
ESP32-S3
ST7789 320x240 LCD with LVGL v9 UI
GT911 capacitive touch + I2C keyboard
SX1262 with TCXO (DIO3 1.8V, DC-DC)
I2S with NVS-persisted volume
Running target with full GUI
Bramble Pager v1 (custom PCB)
ESP32-S3-WROOM-1
2.13" GDEY0213B74 e-paper (SSD1680, 250x122)
Buttons
SX1262 with TCXO and DIO2 RF switch (DC-DC)
Buzzer + vibra alerts
Design complete, boards not yet ordered
Seeed Wio-WM1110 Dev Kit
nRF52840
None (BLE-only interface)
None
LR1110
N/A
Experimental: joins the bench mesh, BLE RPC + provisioning over an encrypted link, identity/key/bonds persist in flash; GNSS and power management not yet implemented (nrf/)
Seeed SenseCAP T1000-E (card tracker)
nRF52840
None (BLE-only interface)
Button
LR1110
Buzzer
Experimental: boots, BLE RPC, joins the mesh; GNSS driver implemented for the onboard AG3335 module and bench-verified (2026-07-31); power management not yet implemented (nrf/)
The Bramble Pager v1 is a custom in-house board, not an off-the-shelf dev kit: its own 96x50mm 2-layer PCB (ESP32-S3-WROOM-1 + SX1262 with a DIO2 RF switch, GDEY0213B74 2.13" e-paper, ATGM336H GPS, buzzer, vibration motor, and status LED), JLCPCB-fabbable, in a 3D-printed case. The authoritative design tree (spec, schematic, PCB, BOM, case, and bring-up gates) is hardware/pager/v1/; build it with the bramble-pager board profile.
This is what the firmware paints on each display class, as real framebuffers (T-Deck captured on hardware, the others rendered by the real firmware in the emulator):
T-Deck Plus: LVGL color UI
Heltec OLED: text UI
Pager v1 (alpha): e-paper text UI
Each image links to its device's section in the device screen gallery, which shows every screen and documents how each capture was made.
Simulator
Bramble ships with a mesh simulator that runs real protocol code against a virtual radio layer and renders topology/traffic in a browser. The radio layer models the shared LoRa medium (real time-on-air, collisions, capture, half-duplex, listen-before-talk), making it the primary proving ground for scale and routing behavior before field deployment.
See simulator/README.md for setup and scenarios. For measured scale results under the collision model, docs/results/simulation-2026-07-honest-baseline.md is the source of truth (it supersedes the June numbers for planning; the earlier collision-free "100% at 200 nodes" figures were retracted as sim artifacts). In short, re-measured on 2026-07-24 at the PHY firmware actually transmits on (the frequency plan's SF9/125 kHz, not the radio profile's SF10): 30% message delivery at 10 nodes, 10% at 50, 0-5% at 100 and 0% at 200, as a single channel saturates under control-plane load (0.91 erlang offered by control traffic alone at 50 nodes, 1.94 at 200). Scale is bounded by radio profile, node density, and hop budget; there is no field-tested-at-scale result.
Emulator
The simulator drives real protocol code through a test harness; the emulator goes one step further and runs the actual firmware binary. Each virtual node is app_main compiled for ESP-IDF's linux target, booted with a virtual board profile, with the radio, e-paper display, buttons, GPS, and battery replaced by virtual drivers at the existing hardware seams. N virtual Bramble Pagers attach to the gosim ether and are rendered in a browser as the physical device: a faithful SSD1680 e-paper panel, clickable buttons, per-node consoles, and true per-node identities that survive restart. It is the packaging/UX proving ground the simulator is not: what a user actually sees and does on the device.
Quick start: cd emulator && make run (local toolchain) or docker compose up --build (zero prerequisites), then open the printed URL and load the emu-channel-delivery scenario. A gated PHY-passthrough bridge lets a serial-attached real node inject the physical RF channel into the virtual ether. See emulator/README.md for setup, scenarios, and the headless CI/E2E suites. A QEMU true-VM backend (running the exact flashable image) is a documented phase-2 follow-on, not yet built.
Getting Started
Full build/flash instructions (including board-specific profiles and USB-port notes) are in docs/BUILDING.md.
Quick start (building from source needs ESP-IDF v5.4.1; see
docs/BUILDING.md to install and activate it):
bash
git clone https://github.com/justinlindh/bramble.git
cd bramble
# activate ESP-IDF in this shell first
source "$IDF_PATH/export.sh"
bash scripts/flash.sh local heltec-v3 build
bash scripts/flash.sh local heltec-v3 flash /dev/ttyUSB0
Use tdeck-plus instead of heltec-v3 for T-Deck Plus builds.
No toolchain, no problem: the web flasher
flashes a device over USB straight from the browser. If a build or flash
stalls (serial permissions, a missing toolchain, a port collision), see
docs/troubleshooting.md.
Keeping it up to date. Once a node is on your WiFi it installs new firmware over the air from the web client, no cable and no toolchain: docs/updating-your-node.md.
First-time setup. A freshly flashed node boots unprovisioned and inert: it has no network key, so it will not mesh (it neither emits nor accepts authenticated control-plane traffic) until you provision one, and the web client shows a prominent UNPROVISIONED banner until then. Follow docs/getting-started.md to connect the web client, provision a network key, optionally enroll the node under a trust anchor, and send your first message.
Bramble is organized as ESP-IDF components with clear boundaries between protocol logic, radio abstraction, security, reliability, and UI/control layers. The architecture is designed so core protocol behavior can be validated on host and simulator environments before device rollout.
Bramble is an early but fully functional project: the protocol stack is implemented end to end, reviewed and host-tested, and running stable on real hardware (T-Deck Plus, Heltec V3, and Heltec V4). Every change must pass the full host test suite as a required CI gate (test/run_all_tests.sh, which fails if any suite fails or none are found). It has not yet been field-tested at scale, and development is ongoing.
Contributing and Community
Contributions are welcome, and you do not need hardware to make one. The
webapp, the simulator, the host test suites, and the docs all build and run on
an ordinary machine.
CONTRIBUTING.md: setup, the quality gates, branch and
commit conventions, and what a good pull request looks like. Start there.
Note the one step that is easy to miss: run make setup-hooks once per
clone so the pre-commit checks run on your machine instead of failing in CI.
docs/troubleshooting.md: serial permissions,
toolchain targets, port collisions, and the other common first-run stalls.
A self-closing bike lock built as a clamshell ring. A fixed arc bolts to the housing, a hinged arc swings 180 degrees to meet it, and a worm gearmotor closes the loop around the frame and rim on a button press or a BLE…
This repository is all software/PCB schematics for the dynamic lighting system in the CASAR lab. In order to track unbiased nitrogen fixation levels, the light intensity inside their incubation vessel has to match…
This directory contains the planning, specification, and initial KiCad project for RAMS Wearable PCB Revision C. Do not fabricate from this directory yet -- manual schematic wiring and DRC verification are still needed.
A small ESP32-S3 board that drives the wired DMX512 input of a Neewer PL60C panel light so the light can be ramped up slowly in the morning (sunrise alarm). Rev A, 2026-09-02.
40 parts
Questions
How big is the Pager PCB?
It measures 96 × 50 mm and has 2 copper layers, 1.6 mm thick.
What parts does the Pager use?
97 parts, built around the ATGM336H-5N31, ESP32-S3-WROOM-1-N8R2, LORA1262-915TCXO and DW01A. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
Where can I download the Pager KiCad files?
From the justinlindh/bramble repository on GitHub, at the commit this page was made from: the board is hardware/pager/v1/kicad/pager.kicad_pcb and its schematic hardware/pager/v1/kicad/epaper.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Can I use the Pager design in my own project?
Its repository publishes it under the MIT licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).