The Problem

Off‑grid expeditions, disaster‑response teams, and hobbyist explorers need reliable GPS navigation and team situational awareness when cellular or internet infrastructure is absent. Existing handheld solutions either depend on cloud services, require a paired smartphone, or expose user identity and location to third‑party platforms. This repo attempts to deliver a fully offline‑first system that keeps identity, contacts, messages, maps and tracks on the user’s device, using LoRa, Meshtastic, MeshCore or Reticulum as transport options.

What This Does

Trail Mate is a portfolio of 12 self‑contained projects rather than a single monolith. The modules layer (1299 files, 616 code files) implements core chat, map navigation, device management and contact handling; platform (641 files, 331 code files) provides board‑specific abstractions for ESP‑32, Linux desktops and uConsole hardware. Individual applications live under apps/ (esp32_lvgl, linux_cardputer_zero, linux_sim_shell, linux_uconsole_gtk) each with their own CMakeLists.txt and, where applicable, a Dockerfile for cross‑compilation. third_party/ pulls in Meshtastic, MeshCore and Reticulum libraries, while tools/ contains build‑automation scripts and a custom code‑fact graph. The system toggles between three decentralized network paths (Meshtastic, MeshCore, Reticulum) at runtime, and offline vector tiles are bundled so maps render without a data connection.

How It Is Wired

Execution starts at three entry points: site/index.html (web UI), site/main.js (client‑side JavaScript) and src/main.cpp (firmware bootstrap). The web UI communicates with the native backend through a small JS‑to‑C bridge; src/main.cpp initializes the board abstraction layer and selects the active network protocol. Inside modules/core_chat/ the contact‑secrets file vmp_contact_secrets.h/cpp stores encrypted identity material; the associated test test_vmp_contact_secrets.cpp validates parsing. The import graph analysis of 1500 code files (C 910, C++ 557, Python 31, Shell 2) reports 31 internal modules, 0 import edges, 0 circular dependencies, meaning each project can be built and reasoned about independently. The most‑connected modules (e.g. tools/architecture/check_board_facts_boundary_ready) have Ca = Ce = 0, confirming the modular isolation. Outside the repo, the system can read LoRa radio settings from platform/esp/arduino_common/include/platform/esp/arduino_common/power/battery_adc.h and render LVGL maps via modules/ui_map_runtime/src/map_overlay_snapshot_source.cpp.

How To Use It

Setup – Clone the repo verbatim:

git clone https://github.com/moses-y/trail-mate.git

Build a specific application with CMake; for the Linux cardputer target:

cd trail-mate/apps/linux_cardputer_zero
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)

Configuration – No central config file is imposed; board‑specific pins and LoRa frequency are set in the board‑header files under platform/esp/... and boards/. Environment variables for mesh network selection are read at runtime from src/main.cpp; the current default is Meshtastic.

Running it

  • Firmware: flash the compiled binary from the build/ directory onto the target board via your preferred programmer.
  • Linux host: launch the UI with ./site/main.js (served by any static HTTP server) or open site/index.html in a browser.

The README documents exact docker run commands for the builder image (apps/linux_cardputer_zero/tools/Dockerfile.cardputer-zero-builder) if you need to cross‑compile on a workstation.

Real‑World Use

A search‑and‑rescue crew equipped with Trail Mate devices can share waypoint coordinates and status updates over LoRa without touching the cellular network. Each member’s device runs the same firmware; the modules/core_chat module encrypts messages using locally stored keys (vmp_contact_secrets.h), and the modules/ui_presentation layer displays a shared map derived from bundled offline tiles. If one node loses power, the remaining nodes continue to forward packets mesh‑style, preserving team awareness until the lost device reconnects.

Code Health & Issues

  • Measured findings (static analysis of 1500 files): 452 total issues – 284 high, 168 medium, 0 low. Dominant kind is cognitive_load deep nesting (max indentation depth 8) in platform/esp/arduino_common/include/platform/esp/arduino_common/power/battery_adc.h, modules/ui_presentation/include/ui_presentation/map/map_presentation_source.h and modules/ui_map_runtime/src/map_overlay_snapshot_source.cpp. Fix: flatten with early returns/guard clauses.
  • Code‑health audit (7 findings, 0 critical):
  • HIGH – Pin third‑party GitHub Actions to commit SHA in .github/workflows (currently docker/setup-qemu-action@v3, softprops/action-gh-release@v2).
  • MEDIUM – Declare least‑privilege permissions: contents: read on workflows lacking it (e.g. cardputer-zero-linux.yml).
  • MEDIUM – Pin container base image by digest in apps/linux_cardputer_zero/tools/Dockerfile.cardputer-zero-builder (currently debian:bookworm).
  • MEDIUM – Move large blobs (>5 MB) to Git LFS or external storage; currently code-fact-graph.json 29.6 MB, NotoSansCJKsc-Regular.otf 15.7 MB, code-first-discovery-spine.json 14.9 MB.
  • MEDIUM – Set persist-credentials: false on checkout in .github/workflows/ci.yml.
  • MEDIUM – Add non‑root USER to the builder Dockerfile.
  • LOW – Add timeout-minutes to workflow jobs (4 jobs have no timeout).
  • Repo hygiene – Tests present, CI via GitHub Actions, licence present, lockfile absent, committed secrets YES (the three vmp_contact_secrets files). No root Dockerfile at repo root, but builder Dockerfiles exist.

The Bottom Line

Trail Mate delivers a rare offline‑first, decentralized communication and TAK platform for embedded and Linux handhelds, with clear modular boundaries and a working mesh‑network stack. The codebase suffers from deep nesting in a few presentation files and from security‑relevant hygiene gaps (unpinned Actions, mutable Docker bases, committed secrets). It is well‑suited for hobbyist explorers, rescue teams, or any organization needing reliable, user‑controlled situational awareness off the grid, provided the listed health items are addressed.