Files
mc-webui/README.md
T
MarekWoandClaude Opus 5 f82ee981b2 fix(docker): ship the compose file for image installs so HTTPS works there too
The optional HTTPS proxy is defined in the repo's docker-compose.yml behind the
"https" Compose profile, which only git-checkout installs have. Docker Hub /
GHCR installs write their own compose file from a README heredoc that had no
npm service, so COMPOSE_PROFILES=https matched nothing and started the app
alone - exit 0, no warning. The same gap swallowed MC_TRUST_PROXY,
MC_BIND_ADDRESS and MC_DEMO*, which the compose file passes to the app.

Add docker-compose.image.yml - the image-based counterpart of
docker-compose.yml, maintained here and downloaded instead of hand-copied, so
the npm service and every variable stay in sync. The image tag becomes
MC_IMAGE in .env so the file itself needs no editing and can be re-downloaded
when something is added to it.

Docs: README Option A downloads the file (and .env.example) instead of pasting
one, and switches tags via MC_IMAGE; https-setup.md Step 1 splits into the two
install paths, tells image installs to refresh the file, notes that
MC_TRUST_PROXY / MC_BIND_ADDRESS need it too, adds the curl for
npm-default-site.conf (no docker/ folder there) and a troubleshooting row for
"only mc-webui starts, no error".

Verified with `docker compose config` in a scratch project directory: the old
hand-written file plus COMPOSE_PROFILES=https in .env resolves to mc-webui
only, the new file to mc-webui + npm with MC_TRUST_PROXY passed and port 5000
bound to 127.0.0.1; `config --images` lists both images, so update-image.sh
pulls and recreates them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 18:18:36 +02:00

610 lines
26 KiB
Markdown

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
# mc-webui
A lightweight web interface providing browser-based access to MeshCore mesh network.
> [!IMPORTANT]
> ### Updating is blocked until you run one command
>
> Since **2 September 2026**, `git pull` stops and asks for a `Username for 'https://github.com'` on this repository. Both `mcupdate` and the in-app **Update Now** button fail because of it.
>
> **Nothing is wrong with your installation, and this repository is still public.** GitHub changed how its HTTP/2 front end answers anonymous fetches, and the git that ships with Debian 12 (2.39, with libcurl 7.88) now gets a `401` back. Git reports any `401` as a request for credentials — so typing a username, a password or a personal access token will not help.
>
> Run this once on your server:
>
> ```bash
> git config --global http.version HTTP/1.1
> ```
>
> **Still asked for a username after that?** Then you update with `sudo`. `--global` writes to the config of the user who runs it, and root has its own — so run it for root too:
>
> ```bash
> sudo git config --global http.version HTTP/1.1
> ```
>
> Then update as usual. Release **2.14.0** carries the same setting inside `update.sh`, but you need the command above to reach it. Full explanation: [Update asks for a GitHub username](docs/troubleshooting.md#update-asks-for-a-github-username).
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/MarekWo/mc-webui)
> **Which version is this?** The [`VERSION`](VERSION) file always holds the version of the branch you are looking at: on `main` it matches the newest entry under [Releases](https://github.com/MarekWo/mc-webui/releases), on `dev` it carries a `-dev` suffix for the release being prepared. The Releases panel in the sidebar is repository-wide and always shows the newest published release, whichever branch you are browsing.
## Overview
**mc-webui** is a Flask-based web application providing browser-based access to MeshCore mesh network. It communicates directly with your LoRa device (via USB, BLE, or TCP) using the `meshcore` Python library, eliminating the need for SSH/terminal access. Tested on Heltec V3 and Heltec V4.
![Diagram](images/diagram.jpeg)
## Key Features
- **Mobile-first design** - Responsive UI optimized for small screens, with desktop sidebar for wide screens
- **Channel management** - Create, join, share (QR code), and switch between encrypted channels
- **Direct Messages (DM)** - Private messaging with searchable contact selector, delivery tracking, configurable retry strategy, and multi-path routing
- **Smart notifications** - Unread message counters per channel with cross-device sync
- **Contact management** - Manual approval, add via URI/QR, filtering, protection, ignoring, blocking, batch operations, and cleanup tools
- **Global search** - Full-text search across all messages (channels and DMs) with FTS5 backend
- **Database** - Fast and reliable SQLite storage for messages, contacts, and configurations
- **Contact map** - View contacts and own device on OpenStreetMap (Leaflet) with last seen info
- **Message archives** - Automatic daily archiving with browse-by-date selector
- **Interactive Console** - Full MeshCore command suite via WebSocket — repeater, contact, device, and channel management
- **Device dashboard** - Device info, statistics, and contact sharing (QR code / URI)
- **Device configuration** - Edit device name, GPS coordinates (with map picker), advert location sharing, and LoRa radio parameters (frequency, bandwidth, SF, CR, TX power) directly from Settings
- **Quick-access FAB buttons** - Draggable floating action buttons (Filter, Search, DM, Contacts, Settings) on main chat and DM pages, with collapsible visibility and customizable size/spacing
- **Dark/Light theme** - Toggle between dark and light UI themes
- **Settings** - Configurable DM retry parameters, message retention, quote length, route popup timeout, toast notification position/timeout, and theme
- **System Log** - Real-time log viewer with streaming
- **Database backup** - Create, list, and download database backups from the UI
- **@Mentions autocomplete** - Type @ to see contact suggestions with fuzzy search
- **Echo tracking** - "Heard X repeats" with repeater IDs for sent messages, all route paths for incoming messages with deterministic payload matching (persisted across restarts)
- **MeshCore Analyzer** - View packet details on analyzer.letsmesh.net directly from channel messages
- **DM delivery tracking** - ACK-based delivery confirmation with SNR, route, and hop count details
- **Multi-device support** - Database file named after device public key for easy multi-device setups
- **PWA support** - Browser notifications and installable app (experimental)
- **Android app** - Optional companion app that opens your instance full screen, without the browser address bar
- **Full offline support** - Works without internet (local Bootstrap, icons, emoji picker)
For detailed feature documentation, see the [User Guide](docs/user-guide.md).
## Quick Start
### Prerequisites
**1. Meshcore Device (tested on Heltec V4)**
- Flash the device at [https://flasher.meshcore.io/](https://flasher.meshcore.io/). Choose the `Companion USB` role (or `Companion BLE` if you plan to use Bluetooth).
- Configure the device with the Meshcore mobile app (from Google Play Store / App Store): Name, Location (optional), Preset
**2. Linux Server (or Raspberry Pi)**
- Docker and Docker Compose installed ([installation guide](docs/docker-install.md))
- Git installed (only needed for Option B: From Source)
- Supported architectures: `linux/amd64`, `linux/arm64`, `linux/arm/v7` (Raspberry Pi 2/3/4/5 all work)
**Important Notes:**
- Powered by direct meshcore library integration (v2 architecture)
- No manual directory setup needed - all data stored in `./data/` inside the project directory
- Uses a single-container architecture with a fast SQLite database
---
### Option A: Docker Hub (recommended)
The quickest way to get started — no git clone, no building required.
Available image tags:
- `mawoj/mc-webui:latest` — stable release (from `main` branch)
- `mawoj/mc-webui:dev` — latest development version (from `dev` branch)
Images are also mirrored to GitHub Container Registry: `ghcr.io/marekwo/mc-webui`
1. **Create a project directory**
```bash
mkdir ~/mc-webui && cd ~/mc-webui
```
2. **Download `docker-compose.yml`**
```bash
curl -fsSL https://raw.githubusercontent.com/MarekWo/mc-webui/main/docker-compose.image.yml -o docker-compose.yml
```
This is [`docker-compose.image.yml`](docker-compose.image.yml) from this repository — the
image-based counterpart of the compose file used by Option B. Downloading it instead of
writing your own keeps the optional extras working: the HTTPS proxy
([docs/https-setup.md](docs/https-setup.md)) is defined in it behind a Compose *profile*,
and options such as `MC_BIND_ADDRESS`, `MC_TRUST_PROXY` or demo mode are read from it too.
A hand-written file that lacks those lines simply ignores the matching `.env` settings.
**Leave the file unedited.** Everything configurable is a variable read from `.env`
(including the image tag — `MC_IMAGE`), so you can download the file again at any time to
pick up services added in later versions, without touching your own settings.
3. **Create `.env` file (optional)**
**In most cases, no `.env` file is needed!** The defaults work automatically:
- `MC_SERIAL_PORT=auto` — auto-detects your USB device
- `MC_DEVICE_NAME=auto` — auto-detects device name
If you want to set your timezone or override defaults:
```bash
echo "TZ=Europe/Warsaw" > .env
```
Every available option is documented in [`.env.example`](.env.example). You can keep a copy
next to your `.env` for reference — no clone needed:
```bash
curl -fsSL https://raw.githubusercontent.com/MarekWo/mc-webui/main/.env.example -o .env.example
```
<details>
<summary><b>Troubleshooting: Multiple USB devices or detection fails</b></summary>
Check available serial devices:
```bash
ls /dev/serial/by-id/
```
If you see multiple devices, add to your `.env`:
```bash
MC_SERIAL_PORT=/dev/serial/by-id/usb-Espressif_Systems_heltec_...
```
</details>
4. **Verify Serial Device Permissions** (if needed)
```bash
sudo usermod -aG dialout $USER
# Log out and log back in for changes to take effect
```
5. **Start mc-webui**
```bash
docker compose up -d
```
This will:
- Pull the pre-built mc-webui image from Docker Hub
- Create `./data/` directory structure automatically
- Start the mc-webui container
6. **Verify installation**
```bash
docker compose ps
```
The container should show `Up` status. Check logs if needed:
```bash
docker compose logs -f
```
7. **Access the web interface**
Open your browser and navigate to:
```
http://<your-server-ip>:5000
```
To find your server IP: `hostname -I | awk '{print $1}'`
8. **Initial Configuration (In Web UI)**
- Main page loads with chat interface on "Public" channel
- Wait for initial sync (1-2 minutes)
- Optional: Enable manual contact approval in Contact Management
### Option B: From Source (Git Clone)
Choose this option if you want to modify the code, contribute, or run the `dev` branch.
1. **Clone the repository**
```bash
cd ~
git clone https://github.com/MarekWo/mc-webui
cd mc-webui
```
2. **Create configuration file**
```bash
cp .env.example .env
```
**In most cases, no changes are needed!** The defaults work automatically:
- `MC_SERIAL_PORT=auto` - auto-detects your USB device
- `MC_DEVICE_NAME=auto` - auto-detects device name from meshcli
Optionally edit `.env` to set your timezone: `TZ=Europe/Warsaw`
<details>
<summary><b>Troubleshooting: Multiple USB devices or detection fails</b></summary>
Check available serial devices:
```bash
ls /dev/serial/by-id/
```
If you see multiple devices, edit `.env` and set `MC_SERIAL_PORT` explicitly:
```bash
MC_SERIAL_PORT=/dev/serial/by-id/usb-Espressif_Systems_heltec_...
```
</details>
3. **Verify Serial Device Permissions** (if needed)
```bash
sudo usermod -aG dialout $USER
# Log out and log back in for changes to take effect
```
4. **Build and run**
```bash
python3 -m app.version freeze
docker compose up -d --build
```
This will:
- Download base images (Python, Alpine Linux)
- Install the `meshcore` Python library
- Create `./data/` directory structure automatically
- Start the mc-webui container
5. **Verify installation**
```bash
docker compose ps
```
The container should show `Up` status. Check logs if needed:
```bash
docker compose logs -f
```
6. **Access the web interface**
Open your browser and navigate to:
```
http://<your-server-ip>:5000
```
To find your server IP: `hostname -I | awk '{print $1}'`
7. **Initial Configuration (In Web UI)**
- Main page loads with chat interface on "Public" channel
- Wait for initial sync (1-2 minutes)
- Optional: Enable manual contact approval in Contact Management
---
## Basic Usage
1. **View messages** - Main page shows chat history with auto-refresh every 10 seconds
2. **Send messages** - Type in the text field and press Enter (135 bytes for channels, 150 bytes for DM)
3. **Switch channels** - Use the dropdown in navbar
4. **Direct Messages** - Access via menu (☰) → "Direct Messages"
5. **Manage contacts** - Access via menu (☰) → "Contact Management"
6. **Console** - Access via menu (☰) → "Console" for MeshCore commands
7. **Search** - Access via menu (☰) → "Search" for full-text message search
8. **Settings** - Access via menu (☰) → "Settings" for DM retry and other configuration
For complete usage instructions, see the [User Guide](docs/user-guide.md).
---
## Android App
<table>
<tr>
<td width="200" align="center"><a href="images/android-wrapper-setup.jpg"><img src="images/android-wrapper-setup.jpg" width="180"></a></td>
<td>
A companion app that opens your own instance full screen — no address bar, its own icon in the app drawer. Everything still runs on your server; the app only displays it.<br><br>
It is on <a href="https://play.google.com/store/apps/details?id=it.wojtaszek.mc.wrapper">Google Play</a> — install it there and it updates itself. Prefer to skip the Store? Download <a href="android/mc-webui-wrapper.apk"><code>android/mc-webui-wrapper.apk</code></a> instead; both are signed with the same key, so you can switch either way without uninstalling. Either way, enter the address of your instance once (e.g. <code>http://192.168.1.100:5000</code>).<br><br>
Full instructions — including the "unknown sources" and Play Protect warnings, and what the app can and cannot do — are in the <a href="docs/android-app.md">Android App guide</a>.
</td>
</tr>
</table>
---
## Updating
### Docker Hub installation
Pull the latest image and restart:
```bash
cd ~/mc-webui
docker compose pull
docker compose up -d
```
To switch between stable and dev, set the image in `.env` (not in `docker-compose.yml`):
- Stable: `MC_IMAGE=mawoj/mc-webui:latest` — the default when unset
- Development: `MC_IMAGE=mawoj/mc-webui:dev`
Then `docker compose pull && docker compose up -d`.
New optional services occasionally land in the compose file — the HTTPS proxy is one. Pulling a
new image does not bring them, since the file is yours; download the current one over it when you
need one of them:
```bash
curl -fsSL https://raw.githubusercontent.com/MarekWo/mc-webui/main/docker-compose.image.yml -o docker-compose.yml
docker compose up -d
```
That file holds no settings of yours — those all live in `.env` — so overwriting it is safe.
One exception: if you had edited the image tag inside the old file to follow `dev`, the downloaded file resets it to the stable one. Put `MC_IMAGE=mawoj/mc-webui:dev` in `.env` to stay on development builds.
You can also update from the web interface instead of the terminal — see
[Remote updates from web GUI](#remote-updates-from-web-gui-optional) below.
### From Source: Using the update script (recommended)
The easiest way to update mc-webui:
```bash
cd ~/mc-webui
./scripts/update.sh
```
The script automatically pulls changes, freezes the version, and rebuilds containers.
**Optional: Create a global alias for quick updates**
Add to your `~/.bashrc` or `~/.zshrc`:
```bash
alias mcupdate='~/mc-webui/scripts/update.sh'
```
Then reload your shell (`source ~/.bashrc`) and update anytime with:
```bash
mcupdate
```
### Manual update
If you prefer to run commands manually:
```bash
cd ~/mc-webui
git pull
python3 -m app.version freeze
docker compose up -d --build
```
If `git pull` asks for a `Username for 'https://github.com'`, it is not asking for credentials you are missing — see [Update asks for a GitHub username](docs/troubleshooting.md#update-asks-for-a-github-username).
The `python3 -m app.version freeze` command captures the current Git build (date + commit hash) for display in the app menu, underneath the release number from the `VERSION` file. Released versions are tagged `v<version>` and published at [Releases](https://github.com/MarekWo/mc-webui/releases); see [Versioning & Releases](docs/architecture.md#versioning--releases) for how a release is cut.
### Testing experimental features
The `dev` branch contains new features that are still being tested:
```bash
cd ~/mc-webui
git checkout dev
./scripts/update.sh
```
To return to the stable version:
```bash
cd ~/mc-webui
git checkout main
./scripts/update.sh
```
### Remote updates from web GUI (optional)
You can enable one-click updates directly from the mc-webui menu. This requires installing a small webhook service on the host machine. It works with either installation option.
**Docker Hub installation** (no repository) — run this from the folder holding your `docker-compose.yml`:
```bash
cd ~/mc-webui
curl -fsSL https://raw.githubusercontent.com/MarekWo/mc-webui/main/scripts/updater/install.sh | sudo bash
```
It downloads what it needs into `/opt/mc-webui-updater`. Add `MCWEBUI_DIR=/path/to/mc-webui` in front of `sudo` if your instance lives somewhere it cannot guess.
**From Source installation:**
```bash
cd ~/mc-webui
sudo ./scripts/updater/install.sh
```
Either way the installer will:
- Create a systemd service `mc-webui-updater`
- Start a webhook server on port 5050
- Enable automatic startup on boot
The update it performs matches the installation it finds, and it decides that at
the moment you press the button:
| Installation | What "Update" runs |
|---|---|
| Docker Hub image | `docker compose pull` + `docker compose up -d` |
| Git checkout | `git pull`, freeze version, `docker compose up -d --build` |
An image is published a few minutes after the commit it is built from, so
shortly after a release the button can report that the change is on GitHub but
its image is still being built. That is not an error — try again in a few
minutes.
**Usage:**
1. Click the refresh button (↻) next to the version in the menu
2. If an update is available, an "Update" button appears
3. Click "Update" to trigger the update remotely
4. The app will automatically reload when the update completes
**Useful commands:**
```bash
# Check service status
systemctl status mc-webui-updater
# View logs
journalctl -u mc-webui-updater -f
# Uninstall (From Source)
sudo ~/mc-webui/scripts/updater/install.sh --uninstall
# Uninstall (Docker Hub installation)
curl -fsSL https://raw.githubusercontent.com/MarekWo/mc-webui/main/scripts/updater/install.sh | sudo bash -s -- --uninstall
```
**Security note:** The webhook listens on port 5050 on all interfaces — the
Docker container reaches it over the Docker bridge, which rules out binding to
localhost only — and it has no authentication. Anyone who can reach port 5050
can trigger a rebuild. Install it only on a trusted network, or block the port
at your firewall.
---
## Gallery
<table>
<tr>
<td align="center"><a href="gallery/main_window.png"><img src="gallery/main_window.png" width="150"><br>Main Window</a></td>
<td align="center"><a href="gallery/dm.png"><img src="gallery/dm.png" width="150"><br>Direct Messages</a></td>
<td align="center"><a href="gallery/unread_msgs.png"><img src="gallery/unread_msgs.png" width="150"><br>Unread Messages</a></td>
<td align="center"><a href="gallery/msg_archive.png"><img src="gallery/msg_archive.png" width="150"><br>Message Archive</a></td>
</tr>
<tr>
<td align="center"><a href="gallery/menu_1.png"><img src="gallery/menu_1.png" width="150"><br>Menu (1)</a></td>
<td align="center"><a href="gallery/menu_2.png"><img src="gallery/menu_2.png" width="150"><br>Menu (2)</a></td>
<td align="center"><a href="gallery/device_info.png"><img src="gallery/device_info.png" width="150"><br>Device Info</a></td>
<td align="center"><a href="gallery/update_check.png"><img src="gallery/update_check.png" width="150"><br>Update Check</a></td>
</tr>
<tr>
<td align="center"><a href="gallery/update_available.png"><img src="gallery/update_available.png" width="150"><br>Update Available</a></td>
<td align="center"><a href="gallery/remote_update.png"><img src="gallery/remote_update.png" width="150"><br>Remote Update</a></td>
<td align="center"><a href="gallery/updated_successfully.png"><img src="gallery/updated_successfully.png" width="150"><br>Updated Successfully</a></td>
<td align="center"><a href="gallery/meshcli_console.png"><img src="gallery/meshcli_console.png" width="150"><br>Meshcli Console</a></td>
</tr>
<tr>
<td align="center"><a href="gallery/contact_management.png"><img src="gallery/contact_management.png" width="150"><br>Contact Management</a></td>
<td align="center"><a href="gallery/existing_contacts.png"><img src="gallery/existing_contacts.png" width="150"><br>Existing Contacts</a></td>
<td align="center"><a href="gallery/approve_contact.png"><img src="gallery/approve_contact.png" width="150"><br>Approve Contact</a></td>
<td align="center"><a href="gallery/channel_management.png"><img src="gallery/channel_management.png" width="150"><br>Channel Management</a></td>
</tr>
<tr>
<td align="center"><a href="gallery/global_search.png"><img src="gallery/global_search.png" width="150"><br>Global Search</a></td>
<td align="center"><a href="gallery/message_filtering.png"><img src="gallery/message_filtering.png" width="150"><br>Message Filtering</a></td>
<td align="center"><a href="gallery/DM_Settings.png"><img src="gallery/DM_Settings.png" width="150"><br>Settings</a></td>
<td align="center"><a href="gallery/sytem_log.png"><img src="gallery/sytem_log.png" width="150"><br>System Log</a></td>
</tr>
<tr>
<td align="center"><a href="gallery/map.png"><img src="gallery/map.png" width="150"><br>Map</a></td>
<td align="center"><a href="gallery/map_individual.png"><img src="gallery/map_individual.png" width="150"><br>Map (Individual)</a></td>
<td align="center"><a href="gallery/image_preview_1.png"><img src="gallery/image_preview_1.png" width="150"><br>Image Preview (1)</a></td>
<td align="center"><a href="gallery/image_preview_2.png"><img src="gallery/image_preview_2.png" width="150"><br>Image Preview (2)</a></td>
</tr>
</table>
---
## Documentation
| Document | Description |
|----------|-------------|
| [User Guide](docs/user-guide.md) | Complete feature documentation |
| [Android App](docs/android-app.md) | Installing the Android companion app and connecting it to your instance |
| [HTTPS Setup](docs/https-setup.md) | Optional encrypted access via Nginx Proxy Manager (Let's Encrypt, self-signed, IP address) |
| [Demo Mode](docs/demo-mode.md) | Share an instance publicly with the device settings, the console and your data locked |
| [Architecture](docs/architecture.md) | Technical details, API reference |
| [Troubleshooting](docs/troubleshooting.md) | Common issues and solutions |
| [Docker Installation](docs/docker-install.md) | How to install Docker on Debian/Ubuntu |
| [Container Watchdog](docs/watchdog.md) | Auto-restart for unhealthy containers |
| [DM Delivery & Retry Logic](docs/dm-retry-logic.md) | How DM delivery confirmation and retry strategies work |
| [Bluetooth Pairing Guide](docs/meshcore_bluetooth_pairing.md) | How to pair MeshCore devices via BLE on Linux |
---
## Development Status
### Completed Features
- [x] Environment Setup & Docker Architecture (single-container, direct device access)
- [x] Backend Basics (REST API, SQLite database, meshcore library integration)
- [x] Frontend Chat View (Bootstrap UI, message display, quote/reply)
- [x] Message Sending (Send form, reply, quote with configurable length)
- [x] Intelligent Auto-refresh (10s checks, UI updates only when needed)
- [x] Contact Management (Approval, add via URI/QR, filtering, protection, ignore/block, batch operations, cleanup)
- [x] Channel Management (Create, join, share via QR, delete with auto-cleanup)
- [x] Public Channels (# prefix support, auto-key generation)
- [x] Message Archiving (Daily archiving with browse-by-date selector)
- [x] Smart Notifications (Unread counters per channel and total)
- [x] Direct Messages (DM) - Searchable contact selector, delivery tracking, configurable retry, multi-path routing
- [x] Global Message Search - Full-text search across channels and DMs (FTS5)
- [x] Message Content Enhancements - Mention badges, clickable URLs, image previews
- [x] @Mentions Autocomplete - Type @ to get contact suggestions with fuzzy search
- [x] PWA Notifications (Experimental) - Browser notifications and app badge counters
- [x] Full Offline Support - Local Bootstrap libraries and Service Worker caching
- [x] Interactive Console - Full MeshCore command suite (repeater, contact, device, channel management)
- [x] Contact Map - View contacts and own device on OpenStreetMap (Leaflet)
- [x] Echo Tracking - "Heard X repeats" badge for sent channel messages
- [x] MeshCore Analyzer - Packet analysis links on channel messages (analyzer.letsmesh.net)
- [x] DM Delivery Tracking - ACK-based delivery checkmarks with SNR/route details
- [x] Device Dashboard - Device info, statistics, and contact sharing (QR/URI)
- [x] Device Configuration - Edit device name, coordinates (map picker), radio parameters from Settings
- [x] Settings Modal - DM retry parameters, message retention, route popup / toast customization, and dark/light theme
- [x] Quick-Access FAB Buttons - Draggable floating buttons with collapse toggle and size/spacing controls
- [x] System Log - Real-time log viewer with streaming
- [x] Database Backup - Create, list, and download backups from the UI
- [x] Desktop Sidebar - Channel/contact sidebar for wide screens (tablet/desktop)
- [x] Dark/Light Theme - Toggle between dark and light UI themes
- [x] Multi-device Support - Database file named after device public key
- [x] Multi-arch Docker Images - amd64, arm64, arm/v7 (Raspberry Pi supported)
### Next Steps
- [ ] Performance Optimization - Frontend and backend improvements
- [ ] Enhanced Testing - Unit and integration tests
---
## Security Notes
**Important**: This application is designed for **trusted local networks only** and has **no authentication**. Do not expose it to the internet without implementing proper security measures.
If you want to share an instance anyway — a public demo, a group of testers — turn on
[demo mode](docs/demo-mode.md) (`MC_DEMO=true`). Everything that reconfigures the radio,
deletes data or reaches the server is refused, while reading and chatting keep working;
you keep full access from your own network or with an unlock code. It restricts what
visitors can *change*, not what they can *see*, so pair it with a login (NPM's Access
Lists, see [HTTPS Setup](docs/https-setup.md)) if the content itself is private.
---
## Contributing
This is an open-source project. Contributions are welcome!
- All code, comments, and documentation must be in English
- Follow the existing code style
- Test your changes with real hardware if possible
---
## License
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
---
## References
- [MeshCore Documentation](https://meshcore.org)
- [meshcore Python library](https://pypi.org/project/meshcore/)
---
## Buy me a coffee
If you appreciate what I am doing you can [buy me a coffee](https://buycoffee.to/marwoj) :)
<img src="images/QR_buycoffee.png" alt="Buy me a coffee" width="200px">
Thanks!
## Contact
<img src="images/MarWoj_card_QR.png" alt="meshcore://..." width="200px">