🏗️ MeshCore Architecture

MeshCore is more than firmware — it's a carefully layered architecture built around one goal: reliable, deterministic messaging on the kind of microcontrollers you find inside a $30 LoRa radio. Every design decision is shaped by the constraints of embedded hardware: no operating system, kilobytes of RAM, and a radio that can only transmit one packet at a time.

Unlike general-purpose mesh platforms, MeshCore stays deliberately narrow. It handles multi-hop routing and store-and-forward messaging extremely well, and outsources everything else — user interfaces, cloud sync, bot logic — to the layers above it. The result is firmware that boots fast, stays stable for months unattended, and runs on hardware that costs less than a fast-food meal.

The Software Stack

From your phone screen to a radio antenna, every piece of the system has exactly one job. This strict layer separation is what lets the same MeshCore networking library run unchanged on an ESP32, an nRF52840, and an RP2040 — you swap only the board-level glue code at the bottom; everything above it compiles identically.

📱

Client Apps

Android · iOS · Web App · CLI · meshcore.js · pyMC_Core

The user-facing side of MeshCore. Apps let you send messages, browse node maps, manage channels, and configure your radio. They connect to the Companion radio over BLE, USB, or Wi-Fi — the app never touches the LoRa hardware directly.

BLE · USB Serial · Wi-Fi TCP · UART
🎛️

Device Firmware Role

Companion · Repeater · Room Server · Sensor

The top-level personality built on MeshCore's library. Each role is a separate compiled binary that configures the library differently: Companions expose a client API, Repeaters forward packets silently, Room Servers buffer messages, Sensors broadcast telemetry. Same library — four very different behaviors.

Packet routing · queue management · store-and-forward
📦

MeshCore Routing & Messaging Library

Multi-hop routing · Store-and-forward · Queue management · Path discovery

The heart of MeshCore. This C++ library manages how packets move across the mesh: building routing tables, queuing outbound transmissions, storing messages for offline nodes, and deciding which packets to forward. It uses pre-allocated fixed pools — zero dynamic memory allocation after startup — to guarantee stability on chips with 256 KB of RAM.

Abstracted platform calls
🔧

Hardware Abstraction Layer (MainBoard interface)

ESP32 · nRF52840 · RP2040 · STM32

The MainBoard interface is a single C++ contract that isolates MeshCore from the underlying chip. Need to port to a new MCU? Implement MainBoard for that chip and the entire networking stack above it works without a single change. This is why MeshCore runs the same on a $5 Seeed XIAO as on a $35 T-Beam.

Arduino/embedded driver calls · SPI
📡

Radio Drivers (RadioLib)

SX1262 · SX1276 · SX1268 · LLCC68

RadioLib is a popular open-source Arduino library that abstracts the SPI-level register programming for Semtech's LoRa chips. MeshCore delegates all radio hardware control here — setting frequency, spreading factor, bandwidth, and output power — so the networking code never needs to know what chip it's running on.

Chirp spread-spectrum modulation · RF
📻

LoRa Radio Hardware

915 MHz (US/Canada) · 868 MHz (EU) · Semtech SX1262 chipset

The physical radio that modulates data onto a chirp spread-spectrum signal and broadcasts it up to several kilometers on a few milliwatts. LoRa's exceptional sensitivity makes it ideal for battery-powered nodes. As far as MeshCore is concerned, this layer is fully opaque — RadioLib handles everything.

Node Roles

Every device running MeshCore picks exactly one role at flash time. All four roles share the same underlying routing library — the role only determines which features are exposed and how the device behaves on the mesh.

🤝

Companion

The personal radio for end users. A Companion pairs with a smartphone or laptop and bridges the app to the mesh over BLE, USB, or Wi-Fi. If you want to send messages or view the live map, this is what you need. Most handheld and desktop radios are flashed as Companions.

📡

Repeater

Pure infrastructure — no display, no phone app, no user interface. A Repeater listens for packets and forwards them along the best path it knows. Deploying Repeaters on hilltops or building rooftops is the single most effective way to extend mesh coverage. They run unattended for months on solar power.

🏠

Room Server

A store-and-forward mailbox for a channel. When a message is sent, the Room Server buffers it. Any node that was offline at the time can connect later and pull the message history automatically. Room Servers bring async messaging to a protocol that otherwise requires both parties to be online simultaneously.

📊

Sensor

A headless telemetry transmitter. Sensors broadcast GPS position, temperature, battery voltage, or other environmental data onto the mesh at a configured interval — no display, no app needed. Useful for tracking assets, monitoring remote weather stations, or mapping mesh coverage in hard-to-reach locations.

Apps, Clients & Community Builds

The MeshCore stack doesn't stand alone. A growing ecosystem of official apps, firmware variants, and community tools extends every layer. Here's where each piece actually fits — and no, it's not all UI.

📲

Ripple (Client App · Layer 1)

The official Android companion app from RippleBiz (the company behind MeshCore). Ripple connects to your Companion radio over BLE and provides messaging, live node maps, and channel management. This is pure UI — Ripple itself contains no radio and no firmware; it speaks to the serial/BLE API that the Companion firmware exposes, and the Companion radio does all the actual mesh work.

🖥️

MeshOS (Firmware Variant · Layer 2)

A firmware build that moves the user interface onto the radio itself — no paired phone required. Devices like the T-Deck Pro run MeshOS with a built-in touchscreen showing messages, a node map, and settings directly on the hardware. Under the hood it's still the same MeshCore routing library; MeshOS replaces the phone-facing serial API of the Companion role with a local UI at the firmware level.

📻

Companion Radio (Hardware · Layers 2–4)

A physical device — T-Beam, Heltec, or any supported radio — flashed with the Companion firmware role. Your phone app is just the display terminal; the Companion radio is where the real work happens. It handles packet construction, routing lookups, the HAL, RadioLib, and the physical LoRa transmission. Without one, a phone app has no path into the mesh at all.

🔧

Custom Firmware (Fork · Layer 2)

Community forks that add custom hardware support, sensor integrations, APRS gateways, or new display layouts. Custom builds typically modify only the Device Firmware Role layer — the top-level "personality" binary — while reusing the MeshCore routing library and HAL unchanged. The clean layer separation makes adding a new role practical without touching the networking core.

Key Design Principles

💾 No dynamic memory after startup

MeshCore pre-allocates all packet buffers, routing tables, and message queues at boot time. Once initialized, there are no malloc or new calls in the critical path. This eliminates heap fragmentation — the slow memory leak that causes many embedded systems to mysteriously crash after days of uptime — and makes memory usage fully deterministic and auditable.

🔧 Clean hardware abstraction

The MainBoard interface is a thin C++ abstract class wrapping everything platform-specific: timers, GPIO, sleep modes, and radio access. The networking library never calls a hardware function directly. Porting MeshCore to a new MCU means implementing roughly a dozen methods in MainBoard — the rest of the stack compiles untouched.

📦 Role-based firmware builds

Rather than shipping one monolithic binary with a settings menu, each MeshCore role is a separate compiled binary. A Repeater binary omits the entire BLE stack and client API. A Companion binary omits the store-and-forward storage engine. Smaller binaries mean more flash space for what actually matters, faster boot times, and a reduced attack surface.

🔬 Deliberately thin network stack

MeshCore doesn't try to be an internet replacement. It implements exactly the primitives a community LoRa network needs: addressed messaging, multi-hop routing, and store-and-forward delivery. Leaving out unused features isn't a limitation — it's what keeps the stack fast and well-understood on a chip with a 240 MHz core and no MMU.

How a Message Travels

Here's what actually happens when you tap Send in the MeshCore app:

  1. App → Companion radio — Your device sends the message text plus the destination address to your paired Companion radio over BLE, USB, or Wi-Fi.
  2. Packet construction — The Companion's routing library wraps the message in a MeshCore packet: source address, destination, channel encryption key, sequence number, and hop limit.
  3. Next-hop lookup — The routing library checks its table for the best next hop toward the destination. For an unknown address, it floods the packet to all neighbors and learns from acknowledgments.
  4. Radio transmission — The packet flows down through the HAL to RadioLib, which programs the SX1262 and fires the chirp sequence at 915 MHz (or 868 MHz in Europe).
  5. Repeater forwarding — Any Repeater in range that hears the packet decrements the hop count and re-transmits toward the destination, extending range far beyond line-of-sight.
  6. Destination receives — The destination Companion demodulates the packet, the routing library validates it, and the message is delivered to the connected app — typically within one to two seconds for a direct or single-hop path.
If the destination was offline when the message was sent, a Room Server on the channel stores the packet. The next time that node connects, it syncs queued messages automatically — no resend required.

MeshCore vs. Other LoRa Firmware

MeshCore isn't the only firmware that runs on these radios. Here's how it compares to the most popular alternatives:

Firmware Network Model Best For Trade-off
Meshtastic Flood-based mesh Large public networks, easy onboarding, huge device support Higher RF overhead from flooding; heavier firmware binary
Reticulum Full cryptographic network stack Privacy-first, resilient comms over any medium Significantly higher complexity; not LoRa-native
MeshCore Routed with store-and-forward Community repeater networks, low-power long-term deployments Smaller ecosystem; fewer supported device types currently
LoRaWAN / TTN Star topology — end nodes → gateways → cloud IoT sensor reporting, GPS trackers, utility meters Requires internet-connected gateways; no peer-to-peer, no offline operation

MeshCore and Meshtastic share more library DNA than you might expect. Both are built on the Arduino/PlatformIO framework and both use RadioLib as the SPI-level driver for Semtech LoRa chips (SX1262, SX1276, SX1268) — so the code that actually twiddles radio registers is essentially the same library in both projects. Both also target the same MCU families (ESP32, nRF52840, RP2040) and build against the same vendor SDKs (ESP-IDF, Zephyr/nRF SDK).

Where they diverge is in the layers above RadioLib: Meshtastic uses Protocol Buffers (protobuf) for packet serialization and carries a noticeably heavier dependency tree as a result; MeshCore uses a compact custom binary packet format with no serialization library dependency at all, keeping the binary smaller and boot time faster.

MeshCore also defines its own MainBoard hardware-abstraction interface so the networking library never calls platform APIs directly, whereas Meshtastic's hardware support is woven more tightly into the main firmware code.

Bottom line: if you can read one codebase you'll recognize the radio and platform layers in the other — the meaningful differences are in the messaging and packet layers, not the radio plumbing.

LoRaWAN & The Things Network

LoRaWAN is easy to confuse with mesh LoRa networks because both run on the same Semtech radio silicon (SX1262, SX1276, SX1268) at the same frequencies (915 MHz in North America, 868 MHz in Europe). Below the physical layer the architectures diverge completely.

🌐 Star topology, not mesh

LoRaWAN is a hub-and-spoke protocol: end nodes (sensors, trackers, meters) transmit uplink packets that are received by one or more internet-connected gateways. Those gateways forward packets to a network server — either the community-run The Things Network ↗ or a private server — which then passes data to an application server. End nodes never communicate with each other directly. There is no multi-hop routing, no store-and-forward between nodes, and no operation without internet connectivity somewhere in the chain. If the gateway goes offline, the network goes silent.

🔌 Same chips, entirely different firmware

A LoRaWAN-flashed T-Beam and a MeshCore T-Beam contain the identical SX1262 radio — the hardware is interchangeable. What differs is everything above it. LoRaWAN firmware runs the LoRaWAN MAC protocol: over-the-air activation (OTAA), frame counters, Adaptive Data Rate (ADR), and Class A/B/C device profiles. MeshCore replaces all of that with its own routing library, store-and-forward engine, and compact binary packet format. Flashing one firmware replaces the other entirely — the radio hardware doesn't care.

📚 RadioLib: the shared radio driver

RadioLib is the shared layer. The same open-source Arduino library MeshCore uses to program the SX1262 added full LoRaWAN support in version 6.x — so the SPI-level register driver is theoretically the same code path whether the device is running MeshCore or a LoRaWAN stack built on RadioLib. Many LoRaWAN Arduino projects still use the older MCCI arduino-lmic stack (a separate implementation that predates RadioLib's LoRaWAN mode), but the trend is toward RadioLib for new builds. Either way, the physical chip driver is the thinnest possible shared layer — above it, the two stacks have almost nothing in common.

When LoRaWAN makes more sense

LoRaWAN excels at one-way, low-duty-cycle telemetry: a soil moisture sensor phoning home every ten minutes, a GPS tracker pinging its location, a water-level gauge on a remote creek. These nodes need to reach a server, not other nodes. If you need two people to exchange messages when the internet is down — or need a packet to hop across several radios to reach someone three ridgelines away — LoRaWAN can't help. That's precisely the gap MeshCore and Meshtastic fill.