Home The Playbook Directory
Learn
Settings Guide Field Guides & Resources Certifications
Get
Meshtastic Meshcore Reticulum Nodes About Contact
DIY Build Guide — Live LoRa Edition

Build a MeshCore
Cyberdeck Terminal

A functional MeshCore mesh terminal — Heltec LoRa32 V4 display node, mechanical keyboard, 915 MHz antenna, acrylic base with LED underglow. This is not a prop. It talks to the network.

Build cost
~$160–250
Radio
915 MHz
Protocol
MeshCore
Skill
Intermediate
Soldering
Light
MeshCore cyberdeck terminal — mechanical keyboard with Heltec LoRa32 V4 module, 915 MHz antenna, and cyan LED underglow on acrylic base
AI-generated concept render. The build guide below is for real hardware.
Contents
  1. What you're building
  2. Parts list
  3. The acrylic base
  4. Heltec LoRa32 V4 — overview
  5. Flashing MeshCore firmware
  6. Wiring: antenna, LEDs, USB
  7. LED underglow firmware
  8. Configuring MeshCore
  9. Finishing & branding
  10. Going further
01

What You're Building

This is a desk terminal built around a Heltec LoRa32 V4 — an ESP32-S3 board with a built-in 0.96" OLED, a 915 MHz SX1262 LoRa radio, and a u.FL antenna connector. Flashed with MeshCore companion firmware, it becomes a fully functional MeshCore node. Mounted to the left of a mechanical keyboard on an acrylic base with LED underglow and an external whip antenna, it becomes something you can actually show people.

The Heltec is doing real work here. It's not a Raspberry Pi pretending to be a radio — the LoRa transceiver is on the same board as the display. MeshCore firmware runs directly on the ESP32-S3 and drives the OLED natively: BLE pairing PIN, connection status, radio state. When you send a message from the MeshCore app on your phone over Bluetooth, the companion radio transmits it into the mesh, and repeaters in range route it toward the destination. The antenna on the bracket picks up actual MeshCore traffic in your area.

This is the build for people who are already on MeshCore and want their companion radio to feel like infrastructure instead of a development board zip-tied to a shelf.

Fig. 1 — Exploded assembly view
Exploded assembly of MeshCore cyberdeck terminal Four components shown in exploded view: Heltec LoRa32 V4 module with whip antenna on left, mechanical keyboard in center-right, WS2812B LED strip along base front, and acrylic base plate underneath. Leader lines connect to labels on the right margin. MESHCORE MeshCore SX1262 LoRa u.FL HELTEC V4 Keyboard any TKL, USB HID Heltec LoRa32 V4 ESP32-S3 + SX1262 915 MHz whip SMA bulkhead + coax pigtail LED strip WS2812B, edge-lit acrylic Acrylic base 3mm clear, 52 × 22 cm M3 brass standoffs u.FL → SMA pigtail
Why the Heltec V4 specifically
The V4 is the current production version of the Heltec WiFi LoRa32 line. It uses the ESP32-S3 (not the older ESP32), the SX1262 LoRa chipset (better sensitivity than the SX1276 on V2/V3), and a u.FL connector for the antenna rather than an onboard PCB trace. The u.FL connector matters — it lets you run a proper coax pigtail to an external SMA bulkhead and a real whip antenna on the bracket. MeshCore firmware supports it natively with OLED integration. It's the same platform the Node Star primary node uses.

Firmware target note: The MeshCore web flasher at flasher.meshcore.co.uk lists the Heltec V4 as a supported device. Select it from the device list and choose your role — BLE Companion for a personal desk node. The flasher handles the correct binary and flash offsets automatically. If you see a blank OLED after flashing, try the "merged" build option, which includes the bootloader and partition table in a single image.
02

Parts List

Everything below is available from AliExpress (longer shipping) or Amazon (faster, $10–20 more total). The Heltec V4 ships from AliExpress reliably in 2–3 weeks. The Heltec official store on AliExpress is legitimate — use it over third-party listings.

ComponentWhat to getCostNotes
LoRa display board Heltec WiFi LoRa32 V4 $18–25 ESP32-S3 + SX1262 + 0.96" OLED. Buy from the Heltec official AliExpress store.
Antenna — whip 915 MHz 3dBi whip, SMA-M $4–7 ~17cm rubber duck style. Any SMA-male 915 MHz whip. Avoid the tiny PCB stubs.
Antenna — pigtail u.FL to SMA-F bulkhead, 10cm $3–5 Connects the board's u.FL port to the SMA bulkhead in the bracket. Keep it short.
SMA bulkhead SMA female panel-mount $2–4 Mounts through a drilled hole in the 3D-printed bracket. The pigtail connects inside; the whip screws on outside.
Mechanical keyboard Any TKL, USB $25–60 Budget Redragon (~$30) to Keychron K2 (~$60). USB HID — no driver needed. TKL proportions suit the base layout.
Acrylic sheet 3mm clear, ~52 × 22cm $8–14 Clear for edge-lighting. Hardware store, Amazon, or Inventables. Score-and-snap with utility knife.
LED strip WS2812B 60LED/m, 1m $3–6 Addressable RGB, self-adhesive. Driven by a secondary MCU reading MeshCore serial output. Cyan underglow from a 5V USB supply.
Display bracket 3D printed, matte black PLA $3–6 STL at nodestar.net/builds. Holds Heltec at 15° tilt, has SMA bulkhead hole, M3 mounting points, cable channel.
Standoffs M3 brass, 15mm, ×6 $4–6 Elevates base ~15mm off desk — the gap is what makes edge-lighting work.
Screws M3 × 6mm pan head, ×12 $2–3 Keyboard to standoffs, bracket to standoffs.
Dupont wires Female-to-female, 20cm, ×5 $2–3 LED strip to Heltec GPIO + power. Light soldering alternative: use pin header + crimp.
USB hub Compact 4-port USB-A $6–10 Keyboard + Heltec on one cable run to host. Mount under base with 3M dual-lock.
Branding Matte vinyl sticker or laser-etch $3–20 Applied to acrylic underside. LED strip edge-lights it from below. SVG assets at nodestar.net.
Total ~$87–169 AliExpress low / Amazon with good keyboard high end.
On soldering
The LED strip data line and power can be connected to the Heltec via Dupont jumpers with no soldering if you use a header-equipped board. One solder joint makes it cleaner: tin the LED strip pads and solder 20cm leads directly. That's it. If you genuinely cannot solder, crimp ferrules over stripped wire ends and use a lever connector block — it's slightly bulkier but works fine.
03

The Acrylic Base

The base unifies everything into a single object. It's a piece of 3mm clear acrylic, elevated 15mm above the desk on brass standoffs, with an LED strip along the inside of the front edge. The clear acrylic transmits that light along its full perimeter — edge-lighting. A logo etched or stuck to the underside glows from below. The keyboard and display module mount on top via the same standoffs.

Fig. 2 — Base plate: dimensions, drill pattern, zones
Acrylic base plate top-down view with dimensions Top-down schematic of 52cm × 22cm acrylic base showing display module zone on left, keyboard footprint on right, standoff hole positions, LED strip location, logo zone, optional hexagonal front cutout, and dimension annotations. 52 cm 22 cm — optional hexagonal front cutout — DISPLAY Heltec + bracket ~12 × 10 cm KEYBOARD FOOTPRINT ~36 × 14 cm (TKL) ← WS2812B strip — interior edge, LEDs facing out → logo (underside vinyl) 3.5 mm holes tape before drilling rear SMA bulkhead

Cutting and drilling

Score the acrylic five or six passes with a utility knife against a metal straight edge, then snap over a table edge. Sanded edges actually diffuse LED light better than polished cuts — run 400-grit along the front edge. Drill at low speed with a 3.5mm bit; tape the surface at each drill point first. Acrylic cracks from heat and vibration, not pressure — slow is the only technique.

1
Cut to 52 × 22 cm

Score and snap, or jigsaw with fine-tooth blade. Leave protective film on during cutting. Optional hex front edge: mark with a template, cut with jigsaw, sand smooth.

2
Drill 6 standoff holes

3.5mm bit, low RPM. 2 holes for display bracket, 4 corners for keyboard. Tape surface at each point. Thread M3 brass standoffs from below, hand-tight.

3
Apply underside branding

Peel bottom film. Apply vinyl from center outward, no bubbles. The LED strip will edge-light through the clear acrylic from below.

4
Stick LED strip

Peel adhesive, run strip along the interior of the front edge, LEDs facing outward. Route data + power leads to rear where the Heltec will sit.

5
Mount components

Display bracket on left standoffs, keyboard on right standoffs. Peel top protective film last.

Acrylic troubleshooting
Cloudy edges: sanded edges diffuse light, but if they look milky-white instead of frosted-clear, you've gone too coarse. Step up through 400 → 600 → 1000 grit, then a quick polish with toothpaste or plastic polish on a rag if you want sparkle. Bubbles under vinyl: work from the center out with a credit-card squeegee; lift and re-lay rather than trying to push trapped air sideways. Stress cracks at drill holes: always drill from the protective-film side, low RPM, and back the acrylic with scrap MDF — cracks appear when the bit punches through unsupported acrylic. Film removal order matters: leave the top film on through cutting, drilling, and standoff installation; peel the bottom film right before applying vinyl; peel the top film absolutely last, after every component is mounted. Once the top is off, every fingerprint shows.
04

Heltec LoRa32 V4 — Overview

The Heltec WiFi LoRa32 V4 runs MeshCore firmware natively. The ESP32-S3 handles the mesh routing stack, and the firmware drives the built-in 0.96" OLED automatically — showing your BLE pairing PIN, connection status, radio state, and contact activity without any additional sketch. The SX1262 LoRa radio handles all RF. This board is the entire MeshCore companion node.

The WS2812B LED strip underneath the acrylic base is driven separately by a small secondary MCU (a $3 Seeed XIAO or Arduino Nano) that monitors MeshCore's serial debug output and pulses the LEDs on mesh activity. This keeps the LED logic off the MeshCore firmware entirely — no firmware modifications, no GPIO conflicts.

Fig. 3 — Heltec LoRa32 V4 pinout (relevant pins for this build)
Heltec LoRa32 V4 pinout diagram for cyberdeck build Schematic of Heltec LoRa32 V4 board showing pin header positions on left and right sides, with callouts for 5V, GND, GPIO45 (LED data), USB-C, u.FL antenna connector, built-in OLED, and SX1262 LoRa chip. Annotations indicate which pins connect to LED strip, host machine, and external antenna. MESHCORE BLE: ready PIN: 123456 LoRa 915MHz SX1262 LoRa radio 915 MHz ESP32-S3 240 MHz dual-core WiFi + BLE u.FL USB-C JST batt. 5V GND 3V3 GPIO1 GPIO2 GPIO45 GPIO46 GPIO3 GPIO4 GPIO5 GPIO6 GPIO14 GPIO15 GPIO16 GPIO17 GPIO18 GPIO19 → LED strip +5V → LED strip GND → LED strip DATA WS2812B DIN → host machine (MeshCore companion protocol) → coax pigtail → SMA bulkhead → whip Heltec WiFi LoRa32 V4
GPIO45 for LED strip — and the 3.3V → 5V signal gotcha
GPIO45 is a reasonable choice for WS2812B data on the V4 — it's not used by the internal LoRa SPI bus or the OLED I2C lines, and on the ESP32-S3 it isn't a problematic strapping pin in normal boot configurations. Always cross-check against the latest Heltec V4 schematic on their GitHub before committing, since strapping/peripheral assignments can shift between board revisions. If GPIO45 is unavailable in your revision, GPIO46 or any other unused S3 GPIO works just as well.

Logic-level mismatch: The ESP32-S3 outputs 3.3V on its GPIOs, but WS2812B strips technically expect a 5V data line (the threshold is ~0.7×VDD ≈ 3.5V). In practice it usually works, especially with a short data run and a fresh first LED — but it's officially out of spec. Two robust fixes: (1) use a 74AHCT125 or SN74LVC1T45 single-gate level shifter on the data line, or (2) sacrifice the first LED as a "level-shifter" and connect the strip's DOUT to LED #2 instead. The 300Ω series resistor at the data input also helps signal integrity but does not raise the voltage.

Power draw: 30 WS2812B LEDs at full white draw up to 1.8 A at 5V — well over the 500 mA a single USB 2.0 port supplies. This build keeps brightness capped at ~150/255 and uses a single solid color, which keeps draw under 500 mA, but if you crank it up or add more LEDs, power the strip from a dedicated 5V rail (powered USB hub, USB-PD trigger board, or a separate 5V/2A supply) rather than the Heltec's USB-C input. Sharing the Heltec's 5V rail with a fully-lit 30-LED strip will brown out the radio.
05

Flashing MeshCore Firmware

MeshCore firmware flashes to the Heltec V4 in about two minutes via the official web flasher. No Python environment, no platform-specific toolchain. Connect the board over USB-C, open the flasher in Chrome or Edge, and select your board and role. For a desk companion node, choose BLE Companion. The OLED will show the MeshCore boot screen and BLE pairing PIN on completion.

Option A — Web flasher (recommended)

browser — official MeshCore web flasher
# Open in Chrome or Edge (requires WebSerial API support)
https://flasher.meshcore.co.uk

# Steps:
# 1. Connect Heltec V4 via USB-C (hold BOOT if not detected)
# 2. Select device: "Heltec V4"
# 3. Select role:
#      - "BLE Companion"  ← for a personal desk node (phone app over Bluetooth)
#      - "USB Companion"  ← for host-connected serial companion (no BLE)
#      - "Repeater"       ← infrastructure only, no user messaging
#      - "Room Server"    ← BBS-style message store for the mesh
# 4. Click Flash — downloads latest stable firmware and writes it
# 5. Wait ~90 seconds. OLED shows the MeshCore boot screen + BLE PIN.
# 6. Done. Open the MeshCore app and pair via Bluetooth.

Option B — esptool CLI

terminal — flash with esptool
# Python 3.8+ required
pip install esptool

# Download the correct .bin from flasher.meshcore.io for your board + role
# For merged builds (includes bootloader + partition table):
esptool.py --port /dev/ttyUSB0 write_flash 0x0 meshcore-heltec-v4-ble-companion-merged.bin

# For non-merged builds (board already has valid bootloader):
esptool.py --port /dev/ttyUSB0 write_flash 0x10000 meshcore-heltec-v4-ble-companion.bin
1
Connect via USB-C

If the board is not detected, put it in bootloader mode: hold the BOOT button, plug in USB-C, then release BOOT after ~1 second. The ESP32-S3 has a built-in USB-CDC bootloader so no special USB driver is normally needed on Linux or modern Windows/macOS — but on older Windows you may need the Espressif USB JTAG/serial driver from the Espressif site. Linux users: add yourself to the dialout group (sudo usermod -aG dialout $USER) and log out/in. If WebSerial still can't see the device, try a different USB-C cable — many "charge-only" cables silently fail.

2
Open flasher.meshcore.co.uk

Use Chrome or Edge. Select Heltec V4 from the device list, then choose your firmware role. For this build, pick BLE Companion — it lets you connect via the MeshCore phone app over Bluetooth while keeping the OLED active.

3
Flash

Click Flash. The tool erases the board, downloads the latest stable release, and writes it. Takes 60–90 seconds. If the OLED stays blank after flashing, try the merged build option — it includes the bootloader and partition table in a single image.

4
Confirm boot

The OLED shows the MeshCore logo, then switches to the companion info screen with the BLE pairing PIN. If it stays blank, hold RESET once and wait 5 seconds.

5
Set region via app

Open the MeshCore app on your phone (Android or iOS), connect via Bluetooth using the PIN shown on the OLED. Tap the settings cog → scroll to Radio SettingsChoose Preset → select your region (US Recommended for 915 MHz, EU Recommended for 868 MHz, AU Recommended for 915–928 MHz). The node applies the correct frequency plan immediately.

Frequency legality
915 MHz ISM band usage rules vary by country. In the US (FCC Part 15), 902–928 MHz is license-free for low-power spread-spectrum. In the EU, use 868 MHz — select the EU preset in the app. In Australia, 915–928 MHz — select the AU preset. The MeshCore region preset controls frequency plan, channel spacing, and transmit power limits automatically. Always set it correctly before operating.
06

Wiring: Antenna, LEDs, USB

Fig. 4 — Complete wiring schematic for display module assembly
Wiring schematic for Heltec LoRa32 V4 display module Schematic showing Heltec V4 board in center, with three connection paths: antenna coax pigtail from u.FL to SMA bulkhead above, LED strip connected via 5V/GND/GPIO45 on left, and USB-C to host machine on right. Annotations explain each connection. Heltec V4 MCORE SX1262 SMA bulkhead u.FL→SMA pigtail 10 cm, low-loss 915 MHz 3dBi rubber duck WS2812B LED strip +5V GND DIN +5V GND DATA→GPIO45 USB-C → host machine MeshCore companion protocol + LED controller Wiring summary strip +5V → Heltec 5V strip GND → Heltec GND strip DIN → GPIO45 u.FL → pigtail → SMA USB-C → host No soldering if using pin headers + Dupont

Antenna assembly

The u.FL connector on the Heltec V4 is small and fragile — seat the pigtail connector firmly but don't rock it. The pigtail runs inside the 3D-printed bracket housing to the SMA bulkhead, which is pressed into a 6.5mm hole in the bracket wall and secured with its nut from the outside. The whip antenna screws onto the external SMA thread. Keep the pigtail coax as short as practical — under 10–15 cm; the thin RG178/1.13mm cable used in u.FL pigtails has high loss per meter at 915 MHz, and every extra centimeter is signal you don't get back. Add a small loop of strain relief at the u.FL end with a dot of hot glue or kapton tape — vibration on the bracket is what kills these connectors, not RF.

Real-world range & testing
The V4's higher TX power (~28 dBm on the native firmware target) is genuinely an improvement over older Heltec boards, but range still depends almost entirely on antenna height, line of sight, obstructions, and how dense the local mesh is. A node at desk height inside a stucco-and-foil house will be lucky to reach 1–2 km even with a perfect antenna; the same node on a roof with a 5dBi colinear can hit 10+ km in flat terrain.

To actually measure what your build is doing, connect to the companion node via the MeshCore app and check the contact list — each contact shows when it was last heard. For deeper diagnostics, connect via USB serial and watch the debug output. In the app, send a Flood Routed Advert (the signal icon at top) and watch for responses — if you see "Heard {x} repeat(s)" you're connected to the mesh. RSSI and SNR values appear in the app's contact details for each node.
u.FL handling
Connect and disconnect the u.FL pigtail no more than necessary — the connector is rated for ~30 mate/unmate cycles. Seat it by pressing straight down until you feel a click. Never pull by the coax cable itself; grip the connector body with fingernails or flat tweezers.
Power, EMI, and "it doesn't work" — quick triage
A few real-world gotchas worth knowing about before you blame the firmware:

Power budget. The Heltec, the secondary MCU, the keyboard, and the LED strip all share whatever the host USB hub can supply. A passive 4-port hub off a single laptop USB-A port gives you ~500 mA total — barely enough. Use a powered hub with its own 5V/2A or 5V/3A brick. If the OLED randomly resets when LEDs flash bright, you're brown-out tripping; that's a power problem, not a code problem.

EMI between the radio and the rest of the deck. The 915 MHz transmitter sits centimeters from a USB hub, a mechanical keyboard's diode matrix, and a WS2812B clock line — all of which radiate broadband noise. In practice this is fine for receive, but if you see degraded RSSI compared to a standalone Heltec, try (a) routing USB cables away from the antenna coax, (b) adding ferrite beads on the keyboard and hub USB cables, and (c) keeping the antenna whip vertical and at least 5–10 cm above the keyboard plane.

Common symptoms & first checks.
OLED blank after flash: hold RESET for 2 seconds, wait 5; if still blank, re-flash with the merged build option and confirm the correct device was selected in the flasher.
No LEDs at all: check the secondary MCU is actually powered (its onboard LED should be on), confirm baud rate matches between Heltec debug serial and the XIAO's Serial1, and verify GND is shared between the strip, the XIAO, and the Heltec.
LEDs flicker erratically: data line too long, no ground reference, or 3.3V → 5V signal issue (see GPIO45 note above).
Node never appears in the app: make sure you flashed the BLE Companion firmware (not USB-only or Repeater). The BLE pairing PIN displays on the OLED — enter it in the MeshCore app when prompted. If pairing fails, try forgetting the device in your phone's Bluetooth settings and reconnecting.
07

LED Underglow Firmware

MeshCore firmware already drives the OLED natively — you don't touch it. What this sketch adds is the WS2812B underglow. It runs on a secondary microcontroller: a $3 Seeed XIAO ESP32C3, an Arduino Nano, or any small board with a spare GPIO. That secondary MCU mounts under the base, watches the Heltec's serial debug output over a second USB connection, and pulses the LED strip cyan on mesh activity. No firmware modification to the Heltec required, ever.

A caveat about serial-string parsing
Grepping the Heltec's debug log for substrings like "RX" and "advert" is the simplest possible trigger and works fine today, but it's brittle: the exact wording of MeshCore's debug output is not a stable API, and a future firmware release can rename or restructure those lines without warning. If this sketch ever stops flashing the LEDs after a MeshCore update, that's almost certainly why — open a serial terminal on the host, watch the new log format, and update the strstr() patterns.

For a more robust setup, use the MeshCore companion protocol library (meshcore_py on PyPI or meshcore.js) on the host machine and have it publish a clean signal — a GPIO pulse, a UDP packet, an MQTT message — to the secondary MCU on received messages. That uses the supported binary companion protocol instead of debug-text scraping and won't break across firmware versions. Slightly more setup, much more durable.
Secondary MCU setup
The Seeed XIAO ESP32C3 is the cleanest fit — it's 21mm wide, USB-C, and runs on 3.3V logic that the WS2812B DIN line can accept with a 300Ω series resistor. Mount it under the base with 3M dual-lock tape next to the USB hub. Power it from one of the hub's USB-A ports. In Arduino IDE: add the Seeed XIAO board package, select XIAO_ESP32C3. Install the FastLED library via Library Manager.
meshterm_leds.ino — LED underglow controller (secondary MCU)
// MeshTerm — LED underglow controller
// Runs on Seeed XIAO ESP32C3 (or Arduino Nano)
// Reads MeshCore serial debug output, animates WS2812B strip
// nodestar.net/builds/meshterm

#include <FastLED.h>

#define LED_PIN   3    // GPIO3 on XIAO ESP32C3; D6 on Nano
#define NUM_LEDS  30   // adjust to your strip length
#define BAUD      115200

CRGB leds[NUM_LEDS];

// Activity state
bool     rxFlash    = false;  // true for one frame on packet receipt
uint32_t lastPacket = 0;
uint32_t flashEnd   = 0;
char     lineBuf[256];
int      lineIdx    = 0;

void setup() {
  Serial.begin(BAUD);     // USB serial (host monitoring, optional)
  Serial1.begin(BAUD);    // Hardware serial → Heltec TX pin
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(150);
}

void checkMeshCoreSerial() {
  // MeshCore debug output contains "RX" on received packets
  while (Serial1.available()) {
    char c = Serial1.read();
    if (c == '\n' || lineIdx >= 254) {
      lineBuf[lineIdx] = '\0';
      // Trigger flash on incoming packet or node advert
      if (strstr(lineBuf, "RX") || strstr(lineBuf, "advert") ||
          strstr(lineBuf, "msg") || strstr(lineBuf, "flood")) {
        rxFlash  = true;
        flashEnd = millis() + 300;  // flash for 300ms
        lastPacket = millis();
      }
      lineIdx = 0;
    } else {
      lineBuf[lineIdx++] = c;
    }
  }
}

void updateLEDs() {
  uint32_t now = millis();
  bool flashing = (now < flashEnd);

  if (flashing) {
    // White flash on packet receipt
    for (int i = 0; i < NUM_LEDS; i++)
      leds[i] = CRGB(200, 255, 255);
  } else {
    // Breathing cyan — exponential sine for natural feel
    float t = now / 2200.0f * PI;
    uint8_t b = (uint8_t)((exp(sin(t)) - 0.36f) / 2.35f * 140);
    // MeshCore blue tint when recently active, cyan base otherwise
    bool recentlyActive = (now - lastPacket < 10000);
    CRGB color = recentlyActive
      ? CRGB(0, (uint8_t)(b * 0.6f), b)   // blue-cyan: active
      : CRGB(0, (uint8_t)(b * 0.83f), b);  // pure cyan: idle
    for (int i = 0; i < NUM_LEDS; i++)
      leds[i] = color;
  }
  FastLED.show();
}

void loop() {
  checkMeshCoreSerial();
  updateLEDs();
  delay(25);
}
Wiring the secondary MCU to the Heltec
Connect the Heltec's TX pin → XIAO RX (Serial1) with a single jumper wire. Both boards share GND through the USB hub. The XIAO monitors MeshCore debug output without interfering with the Heltec at all. The WS2812B strip DATA line connects to XIAO GPIO3 via a 300Ω resistor. Power the strip from the hub's 5V through a USB-A breakout or inline splitter.
08

Configuring MeshCore

After flashing and setting your region preset, the companion node works immediately. Most configuration is done through the MeshCore app over Bluetooth. For desktop use, the web client at meshcore.nz connects over USB Serial and offers the same feature set in a browser tab.

Connect the MeshCore app

MeshCore app — initial setup
# Install the MeshCore app (Android / iOS) or open meshcore.nz in Chrome

# Steps:
# 1. Open the app → tap Connect
# 2. Select your Heltec V4 from the Bluetooth device list
# 3. Enter the BLE pairing PIN shown on the Heltec OLED
#      (default is 123456 if no display; shown on-screen if OLED is active)
# 4. App syncs contacts, channels, and messages
# 5. Tap the settings cog (top-right) to open node settings
# 6. Scroll to Radio Settings → Choose Preset → select your region

Common configuration tasks

MeshCore app — settings and first steps
# Set your region (required before operating)
Settings → Radio Settings → Choose Preset → "US Recommended"
# (or EU Recommended, AU Recommended, etc.)

# Set a node name (shows to other MeshCore users)
Settings → Node Name → "LB Mesh Base"

# Send a Flood Routed Advert to announce yourself to the mesh
# Tap the signal/wave icon at the top of the app
# If repeaters are in range, you'll see "Heard {x} repeat(s)"

# Join a public channel
Settings → Channels → Add Channel → enter channel name + shared secret

# Connect to a Room Server (BBS-style message board)
# Room servers appear in your contact list after they respond to your advert
# Tap the room server → Messages to read and post
USB serial console — repeater/server setup (advanced)
# For repeater or room server firmware, use the web flasher's console
# or a serial terminal at 115200 baud after flashing

# Set frequency (required for repeaters — no app connection available)
freq 915.0

# Set node name
name "LB-RPT-01"

# Set position (lat, lon for the mesh map)
lat 33.77
lon -118.19

# View current config
status
1
Set region preset

In the MeshCore app: Settings → Radio Settings → Choose Preset → US Recommended (or your region). This is mandatory — the node won't operate on the correct frequency plan without it.

2
Name the node

Settings → Node Name. Other mesh users will see this in their contact list after you send an advert.

3
Send a Flood Routed Advert

Tap the signal icon in the app. This announces your node to the mesh. Unlike Meshtastic, MeshCore nodes only discover each other via adverts — patience is key. If repeaters are in range, you'll see confirmation.

4
Join channels or room servers

Public channels broadcast to all subscribers. Room servers store message history — you can disconnect and retrieve missed messages later. Both appear in the app once configured.

5
Verify with a test message

Send a direct message to another contact, or post to a channel. If the message shows "Heard {x} repeat(s)" the mesh is routing your traffic through infrastructure.

Companion nodes do not repeat
This is a fundamental MeshCore architecture decision. Companion radios — the firmware you flash for a personal device — send and receive messages but do not relay traffic for other nodes. Only devices flashed with Repeater firmware act as infrastructure. This keeps the airwaves cleaner and extends battery life. If you want your desk node to also relay traffic, you'll need a second Heltec flashed as a Repeater mounted in a better RF position (roof, window, high shelf).
09

Finishing & Branding

3D-printed bracket

The display bracket holds the Heltec at a 15° forward tilt, provides a mount point for the SMA bulkhead (6.5mm hole in the rear wall), includes a cable channel for the pigtail coax and LED strip leads, and has M3 inserts for mounting to the acrylic standoffs. Print in matte black PLA at 0.2mm layer height — no supports needed with the bracket oriented face-down. The tilt angle keeps the OLED readable from a seated position without leaning forward.

Surface texture

PLA straight off the printer looks fine. For a more finished look: Plasti-Dip rubberized coating in matte black, two coats. Hydro-dipping with carbon-fiber hydrographic film is the higher-effort option. Kits run $20–30 on Amazon.

Cable management

Route the keyboard USB, Heltec USB-C, and XIAO USB-C to a shared exit at the rear through a compact 4-port hub mounted underneath with 3M dual-lock tape. One cable out to your machine. The LED strip leads route inside the bracket housing through the cable channel in the STL.

Branding

Underside vinyl works immediately. For the etched-acrylic look: Ponoko or a local makerspace, laser-etch, $10–20. The etch catches LED edge-light differently from vinyl — more diffuse, more permanent. MeshCore and Node Star SVG assets are available at nodestar.net/assets.

Community builds
Share photos at nodestar.net or tag #meshcore and #cyberdeck on Mastodon. Build variations — different keyboards, alternative enclosures, external battery, integrated SBCs — are welcome as community contributions to the build guide repository.
10

Going Further

"The mesh should feel like a place you inhabit, not an app you check."

The natural next step is embedding a small SBC — a Pi Zero 2W, a Pi 4, or a mini PC — below the base or in a rear enclosure. Connect it to the Heltec over USB and run the MeshCore companion protocol library (meshcore_py or meshcore.js) as a service. At that point you have a local mesh node that the keyboard talks to directly, serves the web client on your LAN, logs all mesh traffic to a local database, and operates off a single power cable.

From there: the MeshCore companion protocol lets you build whatever you want on top. Auto-reply bots. Integration with Home Assistant or MQTT. A map display on a second monitor showing every node your terminal has heard. A script that pages you when a specific contact comes online. The companion protocol is documented and libraries exist for Python and JavaScript.

The r/cyberdeck community has documented builds with integrated e-ink status panels, solar charging, NFC readers, and satellite fallback via Garmin inReach. The acrylic base format scales to all of it. Everything in this guide is a starting point.

A few directions worth specifically calling out:

Solar + battery, untethered. The Heltec V4 has an onboard 1S Li-ion charge controller and JST-PH battery connector — drop in an 18650 holder or a 3.7V 2000 mAh pouch cell, add a small 5–6V solar panel through a TP4056 (or directly to the V4's solar input on revisions that expose it), and you have a node that runs indefinitely on a sunny windowsill. The acrylic deck stays plugged in at the desk; the radio module becomes optionally cable-free.

Dedicated repeater. If you want your desk build to also extend the mesh for others, add a second Heltec V4 flashed with Repeater firmware and mount it higher — roof, window, top of a bookshelf. MeshCore's architecture separates companion and repeater roles deliberately: companions don't relay, repeaters don't chat. One desk node for you, one infrastructure node for the mesh.

Alternative firmware: Meshtastic. If you're more interested in broadcast-style peer chat, automatic node discovery, and a mature ecosystem of integrations, take a look at Meshtastic. It targets the same SX1262-class hardware as MeshCore but optimizes for peer communication rather than structured routing. The hardware build in this guide doesn't change — you just flash a different image.

Display alternatives. The 0.96" OLED is fine but small. Builders who prefer a larger, low-power readout often swap in a 2.9" or 4.2" e-ink module driven from the host SBC over SPI, leaving the Heltec to do nothing but radio. E-ink updates more slowly but is readable in direct sunlight and uses near-zero idle power — a much better fit if you ever take the deck outside.

Keyboard alternatives. Any USB or USB-C mechanical keyboard with a footprint roughly 28–32 cm wide will fit the standoff pattern in the STL with minor edits. Cheap 60% boards from the usual AliExpress shops work, as do nicer hot-swap kits if you want to choose your own switches. For a more cyberdeck-coded look, consider an ortholinear board (Planck, Preonic) or a split board mounted symmetrically around the display module.

Questions, corrections, build reports: Please reach out through our contact page.