mc-webui

mc-webui · Releases

from GitHub · updated 2026-08-07

9 releases

  1. v2.7.0 # 15 hours ago · 2026-08-07 14:23 UTC

    Features

    • The device's Statistics tab now shows everything the device actually reports. Open the menu, pick Device, and switch to Statistics: until now it listed the battery, an error counter, the number of packets sent, and then some counts out of mc-webui's own database — while the stats command in the Console, reading exactly the same data from exactly the same device, printed a good deal more. The reason was a plain mismatch of field names: the tab asked the device for "uptime", "queue", "airtime" and "packets received" under names the firmware does not use, so those rows quietly disappeared instead of showing up empty, and nobody could tell the difference between a value the device withholds and a value the app failed to ask for. All of them are back, and with them the ones that were never displayed at all — last RSSI, last SNR and the noise floor (worth knowing: how loud the band is where your node sits determines what it can still hear), the split of sent and received packets into flood and direct, the count of RX errors, and channel utilization, which is the share of the time since the last reboot that your radio spent either transmitting or receiving. The tab is now laid out in four titled groups — System Information, Radio Statistics, Packet Statistics and Database — the same grouping, in the same order, with the same labels as the status view for a remote repeater under My Repeaters, so the two read the same way. Airtime is shown as a duration (8h 31m) rather than a number of minutes. Everything here except the Database group is counted from the last device reboot, not for all time.

    Fixes

    • The Path Analyzer map no longer shows raw HTML in its pop-ups. Click a repeater on the map — either a hop on the route or one of the amber candidates the analyzer offers where the path is ambiguous — and the pop-up naming it ended the second line with the literal text <code>47</code> instead of the repeater's hash in a monospaced box. Only the display was affected; the hash itself was always correct.
    • A message you sent no longer loses the list of repeaters that heard it when something else goes out at the same moment. Your own messages find out which repeaters picked them up by listening for their own echo coming back off the mesh a few seconds later — and while waiting, the app could only keep track of one message at a time. Send a message and then press Resend on an older one, or send two in quick succession, and the second action took over that slot; when the first message's echo finally arrived it was filed as somebody else's traffic. The message kept its text but never got its signal badge, its repeater list or its Analyzer button, and nothing would bring them back. On the test server this affected roughly one message in thirty. The app now keeps every recent send in mind at once, and listens for five minutes instead of one, because repeats do sometimes arrive minutes after the send. Resend repairs the damage too: a message with no badge could not be re-armed before — re-arming needed exactly the packet identifier that was missing — so it is now recovered from the copy of the packet the app keeps at send time. Press Resend on a badge-less message, wait for a repeater to pick it up, and the badge appears. One thing this cannot fix: if no repeater in range repeated your message at all, or the repeat was lost on the way, there is no echo to hear and the badge stays empty — that is the radio, not the app.
    • Resending an old message now asks first. Resend puts the exact same packet back on the air, and repeaters normally recognise it and stay quiet — that is the whole point, it only reaches the ones that missed it the first time. But a repeater only remembers packets it saw recently, so past a certain age nothing recognises it any more and the message spreads across the channel as if it were brand new: everyone sees it again, dated today. …
  2. v2.6.0 # 5 days ago · 2026-08-03 07:10 UTC

    Features

    • The Android app can now sign in to a server that asks for a password. Putting mc-webui behind a reverse proxy is what makes publishing it to the internet reasonable, and the usual next step is to make that proxy demand a username and password — an Access List in Nginx Proxy Manager, for instance. The app had no answer for that: it showed the proxy's bare "401 Authorization Required" page and stopped there, which meant the phone was the one thing you could not protect. It now asks for the login the first time it connects and remembers it per server address, so later launches go straight in; get it wrong and the same prompt returns with the username already filled in. This appears only when your server actually asks for a password — an instance without one, local http:// or a proxy with no access control, behaves exactly as it always has and never shows this screen. One thing worth knowing: if you turn the password on, or change it, while the app is already open, the app cannot notice mid-session — close it and open it again. This is app version 1.3 — install the new .apk over the one you have; it is signed with the same key, so it goes in as an update and keeps your server address. See android-app.md.
    • The HTTPS guide now explains how to put a password in front of mc-webui. The guide always mentioned that Nginx Proxy Manager can do this — mc-webui has no accounts of its own — but never said how, which made the one step that actually matters for an instance published to the internet the one step you had to work out yourself. https-setup.md now walks through creating an Access List and attaching it to your proxy host, and is clearer about a distinction that is easy to miss: requiring a login keeps strangers out, while closing port 5000 (MC_BIND_ADDRESS=127.0.0.1) stops your own network from reaching the app around the proxy — and therefore around the password. Publishing to the internet wants both; a server whose testers still use http://<address>:5000 wants only the first.
  3. v2.5.0 # 5 days ago · 2026-08-03 05:42 UTC

    Features

    • You can now reach mc-webui over HTTPS. Until now the interface was served over plain HTTP only, which meant the address bar warned it was not secure, and — less obviously — that browsers quietly withheld a set of features they reserve for encrypted connections. There is now an optional HTTPS front end you switch on with a single line in .env; it starts Nginx Proxy Manager next to the app, and you pick your certificate in its web interface rather than editing configuration files. Three routes are covered: a free Let's Encrypt certificate for a public domain, a Let's Encrypt certificate via a DNS challenge — the one worth knowing about, because it gives a fully trusted certificate on a server that is not exposed to the internet at all, with no port forwarding — and a self-signed certificate for reaching the server by its IP address. Existing installations are untouched: nothing starts and nothing changes unless you ask for it, and updates keep working exactly as before. The guide is https-setup.md, including which switch to be careful about (Websockets Support — leave it off and several open tabs will crawl) and why a self-signed certificate cannot work with the Android app.
    • The interface can be translated, and Polish has started. mc-webui was written English-only, with every label and message baked into the code. There is now a translation system behind it, and a Language setting at the top of Settings → Appearance. It covers the whole interface: the main window — menu, chat, message bubbles, its dialogs and Settings — every panel that opens in its own window (System Log, Console, My Repeaters, Path Analyzer, Contacts, Direct Messages), and the running commentary too: the small toasts after every action, the confirmation dialogs, the search results, the update flow and the notifications your phone shows when the app is in the background. Error text that comes back from the server itself is still English — that is the one part left, and it is a separate job. Your choice applies to the browser you set it in and also becomes the default for anyone else opening the server without a preference of their own.
    • You can add a language yourself, without waiting for a release. A language is a single file. Copy en.json from app/translations/, translate the values, and drop it into a translations folder inside your config directory — the same place the database lives. Refresh the page and it appears in the Language list, named however you named it, with no rebuild and no restart. Anything you leave untranslated falls back to English, so a half-finished translation is perfectly usable. A file you drop in also overrides one that ships with the app, so you can correct the built-in Polish on your own server. English and Polish ship in the box; everything else is open to whoever wants to write it. See translations.md, which explains the format and — importantly — which words to leave alone: mesh terms like flood, hop, advert, RSSI and the repeater roles stay English in every language, because that is what the firmware, the CLI and the forums all use. The Console and the log lines themselves stay English for the same reason.
    • Times and dates behave the same in every language. Only the words are translated — "Yesterday" becomes "Wczoraj", "5 min ago" becomes "5 min temu". The clock and the number formatting keep following your browser's own settings, so switching the menus to English will not suddenly turn your 24-hour clock into "9:53 AM". One display of large numbers on the repeater statistics page had been hard-coded to American thousands separators; it now follows your locale like everything else.

    Fixes

    • Copy buttons work over plain HTTP again. Copying a public key, a channel key or a routing path did nothing on some pages when mc-webui was open over http:// on a network address — no er …
  4. v2.4.2 # 8 days ago · 2026-07-31 11:07 UTC

    Fixes

    • Unread counts stand out in the channel list on a phone. On a wide screen, a channel with unread messages shows the count in a blue badge next to its name. On a narrow screen the channel list is a drop-down from the top bar, and there the same number was drawn in plain text, the same colour and size as everything else in the row — easy to read as part of the timestamp and easy to miss entirely. It is now the same blue badge as on a wide screen.
  5. v2.4.1 # 8 days ago · 2026-07-31 07:37 UTC

    Fixes

    • You can keep mc-webui open in several tabs again. Two or three open windows used to bring the whole thing to a crawl — the message list crept, buttons took ten or twenty seconds to do anything, and the status could sit on "Connecting…". It looked exactly like an overloaded server, and it wasn't: the server was answering in a few thousandths of a second the entire time. The live connection that pushes new messages to an open page was running in a mode that keeps a browser connection permanently occupied, and a browser only allows six connections to one address shared across every tab. Three tabs took the lot, so everything else — loading messages, marking them read, sending — queued in the browser waiting for a free one. That connection now uses a proper WebSocket, which does not come out of that budget. Measured with three tabs open: a request that had been taking around 15 seconds now takes about 12 milliseconds. The advice to keep only one window open no longer applies. If you run mc-webui behind a reverse proxy that isn't set up to pass WebSocket connections through, the page quietly falls back to the old behaviour and works exactly as before.
    • Messages no longer go missing after the app has been in the background. Coming back to a minimised app — or to a phone that had been asleep — could show a chat that quietly stopped at whatever message arrived last before the screen went off, with everything since then missing until the app was force-stopped and reopened. New messages reach an open page over a live connection, and Android tears that connection down while the app sits in the background; nothing then went back to ask the server what had been missed. Now every way back from a gap re-reads the list: the connection coming back, the app returning to the foreground, and a heartbeat that notices when the page has been frozen. The same applies to direct messages, and to a browser tab that lost its network for a while.
    • A Refresh item in the menu. The browser's pull-to-refresh has no equivalent in the Android app, so there is now a Refresh entry at the top of the menu that reloads the messages from the server on demand — in the app, and everywhere else too.
    • The connection-status check is about five times cheaper. Every open page asks the server how the mesh device is doing — on load, once a minute after that, and each time you come back to a tab you had left. Answering that took roughly a quarter of a second, almost none of it spent on the device itself: the server was counting the rows of every table in the database to report two numbers, and the row it needed for the "last message" timestamp was found by reading the entire message table and sorting it. The heaviest part, counting the radio-echo records, was thrown away unused — and that table only ever grows, so the check was getting slower the longer an instance had been running. It now asks for exactly the three values it needs, in one go. This is a smaller effect than the bundling below and it does not change what you see on screen; it does take a recurring cost off the server on every open page.
    • Far less load on the server while you have messages on screen. Whenever new radio traffic came in, the page asked the server about every message on screen separately — hundreds of individual requests at a time, repeated every few seconds, and the same messages over and over. On a busy channel that was thousands of requests a minute from a single tab, which left the server little room to answer anything else; the worst of it looked like the mesh device had dropped off, with the message list stuck on "Loading messages…" and the status on "Connecting…", while the device was connected the whole time. Those requests are now bundled into one. A page that needed hundreds of requests per update now needs a single one. The remaining reason several windows were slow is fixed separately — see the first entry above.
  6. v2.4.0 # 9 days ago · 2026-07-29 19:16 UTC

    New features

    • The Android app can send notifications now. When the app shipped in 2.3.0, notifications were the one thing it couldn't do, and the advice was to keep a Chrome "Add to Home Screen" install alongside it. That's no longer necessary — turn notifications on in the mc-webui menu as usual, allow the permission Android asks for, and new messages and pending contacts arrive as ordinary Android notifications. Tapping one reopens the app. Two things are actually better here than in the browser: they work over plain http:// too (Chrome refuses notifications on an unencrypted page), and the app shows up in Android's notification settings like any other, so you can silence it or change its sound there. The same limit as the browser still applies: notifications arrive while the app is open or recently in the background, and stop once Android suspends it — reopening the app catches you up. Requires app version 1.1; see the Android App guide for how to update.
  7. v2.3.0 # 10 days ago · 2026-07-28 19:20 UTC

    New features

    • There is an Android app now. A small companion app opens your own instance full screen — no address bar, its own icon in the app drawer, and it looks like a proper Android app rather than a page in a browser. It holds no mesh logic of its own: on first run it asks for the address of your server (http://192.168.1.100:5000 on the local network, or your https:// hostname behind a reverse proxy), remembers it, and from then on launches straight into mc-webui. Everything still runs on your server and your MeshCore device. It is not on Google Play, so you download the .apk from the repository and install it yourself — the new Android App guide walks through that, including the "unknown sources" permission and the Play Protect notice Android shows for any app that didn't come from the Play Store. Scanning contact QR codes works (on https:// instances — over plain http:// the camera is blocked by the same browser rule that applies in Chrome), and database backups download to the phone's Downloads folder. One thing stays with the browser: notifications, which the app has no access to — if you rely on them, keep the Chrome "Add to Home Screen" install alongside it, the two work happily side by side. The app's source sits next to the .apk, so you can read what you are installing or build it yourself.
  8. v2.2.0 # 12 days ago · 2026-07-27 10:12 UTC

    New features

    • Quotes now use the > convention everyone else already uses. Quoting a message used to wrap it in guillemets — @[Daniel] »Hejka« Cześć! — a shape mc-webui invented back when it couldn't send multi-line messages. It now puts the quote on its own line behind a > and drops the cursor underneath it, so a reply reads as a quote in the standard MeshCore app and every other client too, not just here:

      @[Daniel] >Are we still on for tonight?
      Yes, 8pm works.
      

      Quotes you type by hand get the same italic, tinted styling, so > written manually now looks like a proper quote as well. Nothing you received earlier changes: the old »…« form is still recognised and still displayed exactly as before.

  9. v2.1.0 # 13 days ago · 2026-07-26 17:23 UTC

    New features

    • Releases now have version numbers. This is the first numbered release: the menu shows 2.1.0 with the exact build (date and commit) underneath, so "which version are you on?" has a short answer, and the build is still there when a problem needs pinning down. Each release is tagged on GitHub with these notes attached, so you can see what changed without digging through the commit history.
    • The Path Analyzer map starts on the route you asked for. The map used to plot every located repeater on top of your route, which buried the path you actually wanted to see. It now opens showing just that route, and two checkboxes in the map's top corner add the rest back when you want it: All repeaters brings back the purple dots of uninvolved repeaters, and Alternative paths draws the other copies of the same message your node overheard. Both start off, and switching them never moves or re-zooms the map, so you keep the view you panned to.
    • See where a message's routes actually differ. With Alternative paths on, each of the message's other routes gets its own light colour, matched by a coloured dot next to it in the side list, so you can tell the lines apart — tap one to see its hops and SNR. Copies of one message usually travel most of the same way, so only the stretches where an alternative really diverges are drawn, plus a dot marking where it ends. Often that's the last hop alone, which used to be invisible under the main route.
    • The Path Analyzer remembers your filters. Time range, hop and hash-size filters, the text searches, and the Routes segment length are kept between visits, so a working set like "Last 1 day + 2/3-byte" no longer has to be set up every single time. Clear resets and forgets them. Opening the analyzer from a chat route ignores your saved filters for that visit, so they can't hide the message you tapped through to. The settings are stored by your browser, not on the device — each browser or phone keeps its own.
    • Jump from a chat route straight to the map. Tapping a route under a channel message used to just copy it to the clipboard. Now it opens the Path Analyzer on its map view with that message selected and that exact route already drawn — the quickest way to see where a message physically travelled. Copying isn't gone: each route in the popup keeps a small clipboard icon for pasting into the console's change_path.

    Reliability & polish

    • Your own sent channel messages no longer show a route that isn't theirs. A bug could attach a stranger's overheard packet to your just-sent message, so the delivery badge and the Path Analyzer occasionally displayed a repeater hash and a physically impossible path that were never part of your message. Sent-message echoes are now matched exactly, so the route you see is really yours.