<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Igor Bubelov</title>
        <link>https://bubelov.com/series/btc-map-reports/</link>
        <description>All posts by Igor Bubelov</description><atom:link href="https://bubelov.com/series/btc-map-reports/index.xml" rel="self" type="application/rss+xml" />
        <item>
            <title>BTC Map October Recap</title>
            <link>https://bubelov.com/blog/2026/btcmap-10/</link>
            <pubDate>Mon, 02 Nov 2026 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2026/btcmap-10/</guid>
            <description>&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: this only reflects my personal work this month. Visit the &lt;a href=&#34;https://blog.btcmap.org/&#34;&gt;BTC Map Blog&lt;/a&gt; for consolidated monthly reports.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2026/btcmap-10/og_hu_c8fe51ccdb39873b.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2026/btcmap-10/og_hu_ffa089b5f451957a.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    &lt;figcaption&gt;The desktop app&lt;/figcaption&gt;
&lt;/figure&gt;&lt;/p&gt;
&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#android&#34;&gt;Android&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&#34;#compose-multiplatform&#34;&gt;Compose Multiplatform&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#desktop-app&#34;&gt;Desktop App&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#packaging&#34;&gt;Packaging&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#notes&#34;&gt;Notes&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#events--submissions&#34;&gt;Events &amp;amp; Submissions&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#admin--moderation&#34;&gt;Admin &amp;amp; Moderation&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#map-work&#34;&gt;Map Work&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#beta-updates&#34;&gt;Beta Updates&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#dev-tools&#34;&gt;Dev Tools&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#api&#34;&gt;API&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&#34;#notes-1&#34;&gt;Notes&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#place-images&#34;&gt;Place Images&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#event-review&#34;&gt;Event Review&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#areas&#34;&gt;Areas&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#users--access&#34;&gt;Users &amp;amp; Access&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#dashboard&#34;&gt;Dashboard&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#maintenance&#34;&gt;Maintenance&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#docs&#34;&gt;Docs&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#cli&#34;&gt;CLI&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#ansible&#34;&gt;Ansible&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#future-plans&#34;&gt;Future Plans&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;android&#34;&gt;Android&lt;/h2&gt;
&lt;p&gt;I predicted last month that the Compose Multiplatform rewrite would dominate this report, and it did. What started as a shared module and a proof of concept is now the whole app: Android runs the same Composables as the new desktop client, the old View layer is gone, and for the first time BTC Map has a native build for Linux, Windows and macOS.&lt;/p&gt;
&lt;h3 id=&#34;compose-multiplatform&#34;&gt;Compose Multiplatform&lt;/h3&gt;
&lt;p&gt;The migration happened in the open, one slice at a time, and it touched every screen. The Android app is now a single host fragment wrapped around the shared UI root, and the pile of fragments, dialog fragments and XML layouts it used to carry is down to two layouts.&lt;/p&gt;
&lt;p&gt;Moving code into the shared module also meant leaving the Android-only libraries behind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OkHttp became Ktor, Gson became kotlinx.serialization, and java.time became kotlinx-datetime&lt;/li&gt;
&lt;li&gt;The database layer turned suspending, which the upcoming web target needs, with a small bridge for the synchronous Compose screens&lt;/li&gt;
&lt;li&gt;A wasmJs target now compiles the shared core, so a web client is no longer blocked at the data layer&lt;/li&gt;
&lt;li&gt;Android and desktop share one string catalog, translated into all 36 app languages&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;desktop-app&#34;&gt;Desktop App&lt;/h3&gt;
&lt;p&gt;The new &lt;code&gt;:desktopApp&lt;/code&gt; module renders the shared UI in a desktop window.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2026/btcmap-10/desktop_hu_56524f25bbce6fd2.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2026/btcmap-10/desktop_hu_85fcb2388a7a35d8.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    &lt;figcaption&gt;The desktop app&amp;rsquo;s settings screen&lt;/figcaption&gt;
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;There is no platform-specific UI to maintain, so desktop gets the same features as Android, plus a few that make sense with a mouse:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Right-click the map to add a place, event or note at the clicked point&lt;/li&gt;
&lt;li&gt;Hover states on the area chips and the toolbar&lt;/li&gt;
&lt;li&gt;Keyboard shortcuts and copy actions in the search field&lt;/li&gt;
&lt;li&gt;A language setting that applies at the next launch&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compose Desktop has no native Wayland backend on Linux, so it runs through XWayland, and Java 2D applies only whole-number scales there. A KDE session at 275% arrived as 200%, and the shared UI looked smaller than it does on Android. The app now reads the real scale from the compositor and uses it as the window density.&lt;/p&gt;
&lt;h3 id=&#34;packaging&#34;&gt;Packaging&lt;/h3&gt;
&lt;p&gt;Conveyor builds the release packages on our Linux machine: a Linux AppImage, a Windows MSIX with an installer and a portable zip, and a signed macOS app with a Sparkle update feed. Previously we could only produce the AppImage, because jpackage cannot cross-compile. The Windows and macOS packages are still self-signed, so the installer asks the user to trust the certificate first, and the Windows build installs but does not start yet, which is an upstream MapLibre runtime issue.&lt;/p&gt;
&lt;h3 id=&#34;notes&#34;&gt;Notes&lt;/h3&gt;
&lt;p&gt;Notes are a new feature I am quite happy about. A signed-in user drops a free-form text pin anywhere on the map, and it is private by default with an option to publish it. They are meant to add context regarding the surrounding area.&lt;/p&gt;
&lt;p&gt;In the app, notes are a fourth marker layer next to merchants, events and exchanges. They are never clustered, they wear the standard marker colours (or a chosen icon), they sync incrementally like the other tables, and a new My notes screen lets you edit, flip visibility and delete them.&lt;/p&gt;
&lt;h3 id=&#34;events--submissions&#34;&gt;Events &amp;amp; Submissions&lt;/h3&gt;
&lt;p&gt;Submitting an event from the app was impossible until now. There is a proper add-event screen with date and time pickers and a positioning map, and the time is sent as a floating local wall-clock plus &lt;code&gt;timezone=auto&lt;/code&gt;, so an event at 19:00 happens at 19:00 where it is, not where the submitter is.&lt;/p&gt;
&lt;p&gt;The rest of the submission lifecycle came with it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A My events screen listing every submission, upcoming first, with duplicate and revoke actions&lt;/li&gt;
&lt;li&gt;Revoking a pending submission through the new self-service endpoint&lt;/li&gt;
&lt;li&gt;An event review queue for event managers, admins and roots, badged with the number of pending submissions&lt;/li&gt;
&lt;li&gt;An event sheet on the map, so an event opens in place instead of a separate screen&lt;/li&gt;
&lt;li&gt;A delete action for the submitter while the event is pending, and for privileged roles at any time&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;admin--moderation&#34;&gt;Admin &amp;amp; Moderation&lt;/h3&gt;
&lt;p&gt;The app is no longer only for reading. Area managers get a Manage areas screen listing cached communities with never-verified areas first, a detail screen with the area polygon and its fields, and the ability to verify an area and edit its name and description. Admins and roots get user management (roles and geofence, following the server policy exactly) and a place image moderation screen for the new uploads.&lt;/p&gt;
&lt;h3 id=&#34;map-work&#34;&gt;Map Work&lt;/h3&gt;
&lt;p&gt;MapLibre Compose 0.20.0 landed this month, and most of the map work went into closing the gap with the old Google Maps implementation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A compass above the community chips that appears whenever the view is not facing north&lt;/li&gt;
&lt;li&gt;A map tilt setting, and rotation, tilt, centre and zoom all remembered&lt;/li&gt;
&lt;li&gt;A place stays selected and the pin stays visible when you leave the map to report, boost or comment&lt;/li&gt;
&lt;li&gt;The map&amp;rsquo;s features load before the first frame instead of waiting for a move&lt;/li&gt;
&lt;li&gt;Correct CJK and Hangul labels through a bundled glyph provider with an OpenFreeMap fallback&lt;/li&gt;
&lt;li&gt;Search accepts coordinates, and OpenStreetMap results from Nominatim now sit under the local BTC Map hits, paced to its one-request-per-second policy&lt;/li&gt;
&lt;li&gt;Basemap points of interest that are not merchants open a small sheet with the localized name (with pinyin ruby), category and coordinates, plus &amp;ldquo;It accepts bitcoins&amp;rdquo; and &amp;ldquo;Save as note&amp;rdquo; actions&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;beta-updates&#34;&gt;Beta Updates&lt;/h3&gt;
&lt;p&gt;Beta builds can finally update themselves in place: the update button downloads the APK with a progress bar and hands it to the system installer, the manifest carries a build time so a rebuild at the same version code is still offered, and the settings screen gained an About section with a manual update check.&lt;/p&gt;
&lt;h3 id=&#34;dev-tools&#34;&gt;Dev Tools&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;devtools&lt;/code&gt; script grew into a real tool. &lt;code&gt;app run&lt;/code&gt; covers the desktop app (under Compose Hot Reload) and Android, which now runs in Waydroid instead of a Google AVD, since the container boots Android on the host kernel and needs neither the emulator binary nor a system image. &lt;code&gt;app deploy-beta&lt;/code&gt; takes the platforms to publish as flags, &lt;code&gt;deploy-release&lt;/code&gt; became &lt;code&gt;prepare-release&lt;/code&gt;, and the thin &lt;code&gt;adb&lt;/code&gt; and Gradle wrappers are gone.&lt;/p&gt;
&lt;h2 id=&#34;api&#34;&gt;API&lt;/h2&gt;
&lt;p&gt;The API added the rest of the surface the new clients need. Most of it is the v4 REST API catching up with the RPC layer, since mobile apps never speak RPC.&lt;/p&gt;
&lt;h3 id=&#34;notes-1&#34;&gt;Notes&lt;/h3&gt;
&lt;p&gt;The notes feature started on the API side. A new &lt;code&gt;note&lt;/code&gt; table holds a coordinate, text, an icon and a public flag, and the v4 API exposes &lt;code&gt;POST /v4/notes&lt;/code&gt;, &lt;code&gt;GET|PATCH|DELETE /v4/notes/{id}&lt;/code&gt;, &lt;code&gt;GET /v4/notes/search&lt;/code&gt; and &lt;code&gt;GET /v4/users/me/notes&lt;/code&gt;. Public notes are geo-searchable, private ones are visible only to their author, and the owner list supports &lt;code&gt;updated_since&lt;/code&gt; and &lt;code&gt;include_deleted&lt;/code&gt; so clients can sync incrementally.&lt;/p&gt;
&lt;h3 id=&#34;place-images&#34;&gt;Place Images&lt;/h3&gt;
&lt;p&gt;Photos went from report evidence to a first-class store:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;POST /v4/places/{id}/images&lt;/code&gt; lets signed-in users attach a photo to a place directly, and &lt;code&gt;GET /v4/places/{id}/images&lt;/code&gt; serves the metadata&lt;/li&gt;
&lt;li&gt;Photos are validated like report evidence: at most 10 MB decoded, at most 20k pixels per side, raster formats only&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DELETE /v4/places/{id}/images/{image_id}&lt;/code&gt; removes an upload, but only the uploader, admin or root may call it&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /v4/place-images&lt;/code&gt; lists the newest uploads across every place for moderation, and &lt;code&gt;GET /v4/users/me/place-images&lt;/code&gt; lists your own&lt;/li&gt;
&lt;li&gt;The uploader is exposed as a nested &lt;code&gt;author&lt;/code&gt; object, resolved across &lt;code&gt;image.db&lt;/code&gt; and &lt;code&gt;main.db&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;event-review&#34;&gt;Event Review&lt;/h3&gt;
&lt;p&gt;Events now carry a review status (&lt;code&gt;pending&lt;/code&gt;, &lt;code&gt;live&lt;/code&gt; or &lt;code&gt;rejected&lt;/code&gt;) and an optional &lt;code&gt;submitted_by&lt;/code&gt; attribution. Signed-in users submit through &lt;code&gt;POST /v4/events&lt;/code&gt;, track their own through &lt;code&gt;GET /v4/users/me/events&lt;/code&gt;, and revoke a pending submission with &lt;code&gt;DELETE /v4/events/{id}&lt;/code&gt;. Event managers and above approve or reject through &lt;code&gt;PUT /v4/events/{id}/status&lt;/code&gt;. Public reads stay live-only by default, and the geofence check moved into a shared &lt;code&gt;service/geofence&lt;/code&gt; module used by both REST and RPC.&lt;/p&gt;
&lt;h3 id=&#34;areas&#34;&gt;Areas&lt;/h3&gt;
&lt;p&gt;Area management opened up over REST:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;POST /v4/areas&lt;/code&gt; creates an area with a fixed set of named fields, rejecting geofenced callers, since a new top-level area falls outside everything they manage&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PATCH /v4/areas/{id}&lt;/code&gt; updates named fields only, with an immutable alias, nulls clearing optional tags and contact channels filtered through an allowlist&lt;/li&gt;
&lt;li&gt;&lt;code&gt;verified_at&lt;/code&gt; is now part of the area response and the delta sync&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /v4/areas/{id}/reports&lt;/code&gt; returns a single area&amp;rsquo;s daily history in a typed shape instead of a raw tags map&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;users--access&#34;&gt;Users &amp;amp; Access&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;GET /v4/users&lt;/code&gt; is an admin/root-only username search, and &lt;code&gt;PATCH /v4/users/{id}&lt;/code&gt; updates roles and geofences while keeping admin as the role ceiling. Token versus user role precedence moved into one &lt;code&gt;Auth::effective_roles&lt;/code&gt; helper so REST and RPC authorize identically.&lt;/p&gt;
&lt;p&gt;I also started tracking &lt;code&gt;last_used_at&lt;/code&gt; on access tokens, so unused or leaked tokens can be spotted. It is stamped on successful authentication and stays out of the &lt;code&gt;updated_at&lt;/code&gt; trigger.&lt;/p&gt;
&lt;h3 id=&#34;dashboard&#34;&gt;Dashboard&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;GET /v4/dashboard/infra&lt;/code&gt; serves the analytics dashboard to the &lt;code&gt;dashboard&lt;/code&gt;, &lt;code&gt;admin&lt;/code&gt; and &lt;code&gt;root&lt;/code&gt; roles, mirroring the RPC gate.&lt;/p&gt;
&lt;h3 id=&#34;maintenance&#34;&gt;Maintenance&lt;/h3&gt;
&lt;p&gt;A large part of the API&amp;rsquo;s month was paying down dependency debt, and it went deeper than version numbers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rusqlite 0.40 and deadpool-sqlite 0.14, moving bundled SQLite to 3.53.2&lt;/li&gt;
&lt;li&gt;nostr 0.45, matrix-sdk 0.19, argon2 0.6, sha2 0.11 and base64 0.23, with the breaking changes handled and existing password hashes still verifying&lt;/li&gt;
&lt;li&gt;clap is gone, after disabling a default feature on &lt;code&gt;names&lt;/code&gt; that pulled it in for a CLI we never use&lt;/li&gt;
&lt;li&gt;Declared version floors raised to match &lt;code&gt;Cargo.lock&lt;/code&gt;, so the manifest describes what we actually build&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The most satisfying cleanup was the OpenGraph image renderer. We used the &lt;code&gt;staticmap&lt;/code&gt; crate, which dragged in an old rustls and six RUSTSEC advisories. It is replaced by an in-house renderer that fetches the covering tiles, composites them with the &lt;code&gt;image&lt;/code&gt; crate, draws the marker so its tip sits on the element and encodes a 600x315 JPEG.&lt;/p&gt;
&lt;h3 id=&#34;docs&#34;&gt;Docs&lt;/h3&gt;
&lt;p&gt;The new endpoints came with REST documentation pages for notes, place images and the infrastructure dashboard, and the users page grew the admin search and update calls.&lt;/p&gt;
&lt;h2 id=&#34;cli&#34;&gt;CLI&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;area get&lt;/code&gt;, &lt;code&gt;area add&lt;/code&gt; and &lt;code&gt;area update&lt;/code&gt; now use the v4 REST API instead of RPC, with percent-encoded path segments for aliases with spaces or non-ASCII characters&lt;/li&gt;
&lt;li&gt;&lt;code&gt;set-area-tag&lt;/code&gt; is replaced by &lt;code&gt;area update&lt;/code&gt;, which supports &lt;code&gt;--name&lt;/code&gt;, &lt;code&gt;--type&lt;/code&gt;, &lt;code&gt;--description&lt;/code&gt; with &lt;code&gt;--clear-description&lt;/code&gt;, &lt;code&gt;--geojson&lt;/code&gt; and repeatable &lt;code&gt;--contact&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;area add&lt;/code&gt; requires &lt;code&gt;--type&lt;/code&gt; and accepts an optional &lt;code&gt;--name&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;ansible&#34;&gt;Ansible&lt;/h2&gt;
&lt;p&gt;Infrastructure work was mostly maintenance this month, and it was a good reminder of why it matters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every host was running a kernel vulnerable to CVE-2026-98432, a remote root in the IPv4 TCP IP-options code. Several of them exposed Go listeners with no packet filter in front. All five hosts were upgraded, rebooted and verified with their services healthy.&lt;/li&gt;
&lt;li&gt;Database replication on the backup host had been failing since August 17 because the deployed script used &lt;code&gt;mkdir&lt;/code&gt; where the repo has &lt;code&gt;mkdir -p&lt;/code&gt;, and every run after the first aborted under &lt;code&gt;set -e&lt;/code&gt;. The snapshot timer kept compressing copies frozen at that date. The repo fix never landed because the inventory pointed at a hostname that does not resolve. The correct script is deployed and a full 4 GB sync plus an incremental run were verified.&lt;/li&gt;
&lt;li&gt;The new Overpass host joined the inventory with a full system upgrade and SSH hardening. I also documented an API outage caused by &lt;code&gt;fcgiwrap&lt;/code&gt; running a single worker, where one large query blocked every other request for about seven minutes. The fix is documented but not applied yet.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;future-plans&#34;&gt;Future Plans&lt;/h2&gt;
&lt;p&gt;A few things on my mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cut the 1.3.0 release.&lt;/li&gt;
&lt;li&gt;Get the desktop builds to a state ready for public beta.&lt;/li&gt;
&lt;li&gt;Keep pushing the web target, now that the shared core compiles for it.&lt;/li&gt;
&lt;li&gt;Continue moving the CLI and the docs from RPC to v4.&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map September Recap</title>
            <link>https://bubelov.com/blog/2026/btcmap-09/</link>
            <pubDate>Fri, 02 Oct 2026 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2026/btcmap-09/</guid>
            <description>&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: this only reflects my personal work this month. Visit the &lt;a href=&#34;https://blog.btcmap.org/&#34;&gt;BTC Map Blog&lt;/a&gt; for consolidated monthly reports.&lt;/p&gt;
&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#thanks&#34;&gt;Thanks&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#android&#34;&gt;Android&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&#34;#120-release&#34;&gt;1.2.0 Release&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#offline-first&#34;&gt;Offline First&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#places--reports&#34;&gt;Places &amp;amp; Reports&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#events--activity-feed&#34;&gt;Events &amp;amp; Activity Feed&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#documentation&#34;&gt;Documentation&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#bug-fixes--polish&#34;&gt;Bug Fixes &amp;amp; Polish&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#api&#34;&gt;API&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&#34;#delta-sync&#34;&gt;Delta Sync&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#events&#34;&gt;Events&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#search&#34;&gt;Search&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#place-reports-submissions--images&#34;&gt;Place Reports, Submissions &amp;amp; Images&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#auth&#34;&gt;Auth&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#maintenance&#34;&gt;Maintenance&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#cli&#34;&gt;CLI&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#event-admin&#34;&gt;Event Admin&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#infra&#34;&gt;Infra&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&#34;#overpass&#34;&gt;Overpass&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#fleet--maintenance&#34;&gt;Fleet &amp;amp; Maintenance&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#website&#34;&gt;Website&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#future-plans&#34;&gt;Future Plans&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;thanks&#34;&gt;Thanks&lt;/h2&gt;
&lt;p&gt;Thanks to &lt;a href=&#34;https://dalliard.ch/&#34;&gt;Nathanael&lt;/a&gt; for another round of bug reports and testing.&lt;/p&gt;
&lt;h2 id=&#34;android&#34;&gt;Android&lt;/h2&gt;
&lt;p&gt;It has been six months since our last Android release. Version 1.2.0 shipped on September 30, and most of the work below feeds into it.&lt;/p&gt;
&lt;h3 id=&#34;120-release&#34;&gt;1.2.0 Release&lt;/h3&gt;
&lt;p&gt;The release finally collects the offline, search and account work into a stable build. The headline items:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Global search covering places, communities and conferences&lt;/li&gt;
&lt;li&gt;Full offline mode with a bundled world map and downloadable high-res region packs&lt;/li&gt;
&lt;li&gt;Community pulse and community/country screens&lt;/li&gt;
&lt;li&gt;Optional accounts with saved places and areas, and a personalized activity feed&lt;/li&gt;
&lt;li&gt;Per-app language selection on Android 13+&lt;/li&gt;
&lt;li&gt;Simplified add-location and verify/report flows&lt;/li&gt;
&lt;li&gt;Human-readable opening hours and a database/image diagnostics screen&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;offline-first&#34;&gt;Offline First&lt;/h3&gt;
&lt;p&gt;This was the through-line of the month. The app now ships curated data snapshots so a fresh install is usable without a network:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Full place records, so the first sync only fetches the delta since the snapshot&lt;/li&gt;
&lt;li&gt;The full areas snapshot, including borders&lt;/li&gt;
&lt;li&gt;Place-comments and events snapshots, so comments and event search work offline&lt;/li&gt;
&lt;li&gt;A low-zoom world basemap&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The map, area screen, search and activity feed read from the local database and stay usable offline, and the sync state is centralized and observable through a new database stats screen.&lt;/p&gt;
&lt;p&gt;I also added downloadable high-res offline map packs per region, using MapLibre&amp;rsquo;s offline manager, with a size estimate before download and progress and delete controls afterwards.&lt;/p&gt;
&lt;h3 id=&#34;places--reports&#34;&gt;Places &amp;amp; Reports&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A native place submission form with a draggable-pin mini map, replacing the external btcmap.org link&lt;/li&gt;
&lt;li&gt;A native verify/report screen that posts to the new place-report endpoint, with the verify and report actions split&lt;/li&gt;
&lt;li&gt;Place issues on the area screen, and OpenStreetMap deep links&lt;/li&gt;
&lt;li&gt;Opening hours summarized per weekday with today highlighted&lt;/li&gt;
&lt;li&gt;btcmap.org place links now open in the app instead of the browser&lt;/li&gt;
&lt;li&gt;Boosted places now appear at the top of search results&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;events--activity-feed&#34;&gt;Events &amp;amp; Activity Feed&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A dedicated event screen with deep link support&lt;/li&gt;
&lt;li&gt;The activity feed split into Local and Following tabs, with the filter moved into a dialog&lt;/li&gt;
&lt;li&gt;Upcoming-event badges on area icons and clickable event cards on the area screen&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;documentation&#34;&gt;Documentation&lt;/h3&gt;
&lt;p&gt;I published a new documentation website: &lt;a href=&#34;https://android.btcmap.org&#34;&gt;android.btcmap.org&lt;/a&gt;. It is fully static, so it loads instantly, and its minimalistic Material-inspired design with plenty of screenshots makes the user guides a real pleasure to read. I am genuinely happy with how it turned out.&lt;/p&gt;
&lt;h3 id=&#34;bug-fixes--polish&#34;&gt;Bug Fixes &amp;amp; Polish&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Fixed a pile of auth session races: token encryption, 401 handling, revoking tokens on sign-out and recovering undecryptable tokens&lt;/li&gt;
&lt;li&gt;Sped up search by reading only the fields results need&lt;/li&gt;
&lt;li&gt;Rendered outdated merchants with reduced opacity and gray icons, and filtered the oldest ones out by default&lt;/li&gt;
&lt;li&gt;Disabled map rotation by default, with an opt-in setting&lt;/li&gt;
&lt;li&gt;Hardened the map against rotation and edge-case input, and bounded the area geometry cache&lt;/li&gt;
&lt;li&gt;Restored the Carto Dark Matter style as a bundled option and fixed several marker and layout issues&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;api&#34;&gt;API&lt;/h2&gt;
&lt;p&gt;Most of my API work this month went into areas and events. I promoted both to first-class citizens by enabling incremental sync and proper localization support, so caching clients can finally treat them the same way they already treat places and comments.&lt;/p&gt;
&lt;h3 id=&#34;delta-sync&#34;&gt;Delta Sync&lt;/h3&gt;
&lt;p&gt;I extended the v4 delta sync from places and comments to areas and events, so caching clients can pull only what changed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /v4/events&lt;/code&gt; now accepts &lt;code&gt;updated_since&lt;/code&gt;, &lt;code&gt;limit&lt;/code&gt; and &lt;code&gt;include_deleted&lt;/code&gt;, returning a change log ordered by &lt;code&gt;updated_at, id&lt;/code&gt;. Soft-deleted rows come back only with &lt;code&gt;include_deleted=true&lt;/code&gt; and carry &lt;code&gt;deleted_at&lt;/code&gt;, so clients can evict them locally.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /v4/areas&lt;/code&gt; gained the same incremental mode with an &lt;code&gt;AreaDelta&lt;/code&gt; projection that exposes the bbox but no raw tags or geometry unless &lt;code&gt;geo_json&lt;/code&gt; is explicitly requested.&lt;/li&gt;
&lt;li&gt;The area delta carries &lt;code&gt;localized_name&lt;/code&gt; and &lt;code&gt;localized_description&lt;/code&gt;, built from the &lt;code&gt;name:&amp;lt;lang&amp;gt;&lt;/code&gt; and &lt;code&gt;description:&amp;lt;lang&amp;gt;&lt;/code&gt; tags, so a client can localize area names without a request per language.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also fixed a subtle bug where comment timestamps in delta sync were compared as raw text instead of instants, which could make a client skip rows.&lt;/p&gt;
&lt;h3 id=&#34;events&#34;&gt;Events&lt;/h3&gt;
&lt;p&gt;Events used to be allowed without a start date. I made &lt;code&gt;starts_at&lt;/code&gt; mandatory (migration 119 rebuilds the table with a NOT NULL constraint) and removed the now-dead &amp;ldquo;undated events are always returned&amp;rdquo; branches from &lt;code&gt;get_events&lt;/code&gt;, &lt;code&gt;/v4/events&lt;/code&gt;, the area upcoming events and search.&lt;/p&gt;
&lt;p&gt;The bigger change is timezones. &lt;code&gt;create_event&lt;/code&gt; and &lt;code&gt;update_event&lt;/code&gt; now accept either an RFC 3339 timestamp with an explicit offset or a floating local time plus a timezone, where &lt;code&gt;auto&lt;/code&gt; infers the zone from the event&amp;rsquo;s coordinates via &lt;code&gt;tzf-rs&lt;/code&gt; (DST aware). The resolved offset is echoed back so callers can verify what was inferred. The unused &lt;code&gt;cron_schedule&lt;/code&gt; column was dropped entirely.&lt;/p&gt;
&lt;h3 id=&#34;search&#34;&gt;Search&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;/v4/search&lt;/code&gt; now matches events by name alongside places and areas, keeping the same future-or-undated filter as &lt;code&gt;/v4/events&lt;/code&gt;. Area results carry their icon, so clients no longer need a follow-up request per row.&lt;/p&gt;
&lt;p&gt;I also added a &lt;code&gt;lang&lt;/code&gt; query parameter to &lt;code&gt;GET /v4/areas/{id}&lt;/code&gt; for localized names and descriptions, and attached upcoming events to the area lat/lon search results by testing each point against the area polygon. A new &lt;code&gt;GET /v4/areas/{id}/events&lt;/code&gt; endpoint serves the same data with an optional date window.&lt;/p&gt;
&lt;h3 id=&#34;place-reports-submissions--images&#34;&gt;Place Reports, Submissions &amp;amp; Images&lt;/h3&gt;
&lt;p&gt;I opened the user-facing write paths on REST, since mobile apps are less privileged clients that never use RPC:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;POST /v4/place-reports&lt;/code&gt; and &lt;code&gt;POST /v4/place-submissions&lt;/code&gt; mirror the &lt;code&gt;report_place&lt;/code&gt; and &lt;code&gt;submit_place&lt;/code&gt; RPCs for signed-in users, always recording &lt;code&gt;origin=&#39;user&#39;&lt;/code&gt; and the caller in a new &lt;code&gt;submitted_by&lt;/code&gt; column.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /v4/places/{id}/images&lt;/code&gt; lets signed-in users attach a photo to a place directly, and &lt;code&gt;GET /v4/places/{id}/images&lt;/code&gt; serves them.&lt;/li&gt;
&lt;li&gt;Place reports accept optional photo evidence (at most five photos, raster-only, size and dimension limited)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also taught the issue sync to prefix titles with the country and community tags, and to pass raw &lt;code&gt;osm:&amp;lt;tag&amp;gt;&lt;/code&gt; extra fields (address, payment methods) through to the paste-ready OSM tag block.&lt;/p&gt;
&lt;h3 id=&#34;auth&#34;&gt;Auth&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;POST /v4/auth/signout&lt;/code&gt; now revokes the bearer token that authenticates the request, while leaving the user&amp;rsquo;s other tokens valid. It mirrors the existing RPC method, so the mobile clients can stay on REST for the whole session lifecycle.&lt;/p&gt;
&lt;h3 id=&#34;maintenance&#34;&gt;Maintenance&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Guarded &lt;code&gt;sync_elements&lt;/code&gt; with a process-wide atomic flag, so a manual or retried call can&amp;rsquo;t start a second sync&lt;/li&gt;
&lt;li&gt;Stopped returning soft-deleted &lt;code&gt;area_element&lt;/code&gt; links from the v4 places and areas endpoint, with a regression test&lt;/li&gt;
&lt;li&gt;Added more element icons and refreshed the v4 and RPC docs&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;cli&#34;&gt;CLI&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;event create&lt;/code&gt; now requires &lt;code&gt;--starts-at&lt;/code&gt;, and &lt;code&gt;event update&lt;/code&gt; dropped &lt;code&gt;--clear-starts-at&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;event create&lt;/code&gt; and &lt;code&gt;event update&lt;/code&gt; gained &lt;code&gt;--timezone&lt;/code&gt; (auto or an IANA name) and dropped the old cron-schedule flags&lt;/li&gt;
&lt;li&gt;Fixed &lt;code&gt;event update&lt;/code&gt; clobbering fields on partial updates and expanded its options&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;event-admin&#34;&gt;Event Admin&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Added &amp;ldquo;Clone previous event&amp;rdquo; to the add form, listing past events by distance so a new event can start from a template&lt;/li&gt;
&lt;li&gt;Removed the cron schedule and area fields from the event form&lt;/li&gt;
&lt;li&gt;Added an editable UTC offset (defaulting to the browser timezone for the entered date), then switched to sending &lt;code&gt;timezone: auto&lt;/code&gt; and let the server infer the zone from the location&lt;/li&gt;
&lt;li&gt;Auto-bump the end date when the start date passes it&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;infra&#34;&gt;Infra&lt;/h2&gt;
&lt;h3 id=&#34;overpass&#34;&gt;Overpass&lt;/h3&gt;
&lt;p&gt;For a long time we relied on a public Overpass instance for our OpenStreetMap sync. This month it became progressively less reliable: syncs would stall, and at times we lagged OpenStreetMap by 12 hours or more. New merchants and edits took far too long to reach the map, and the instance&amp;rsquo;s reliability was entirely out of our hands.&lt;/p&gt;
&lt;p&gt;So I set up our own Overpass server at &lt;code&gt;overpass.btcmap.org&lt;/code&gt; and switched the sync over to it. It is not ready for public use yet, but if it holds up we might offer it to the broader community in the future.&lt;/p&gt;
&lt;h3 id=&#34;fleet--maintenance&#34;&gt;Fleet &amp;amp; Maintenance&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Added a README with a server fleet table (roles, IP addresses, maintenance dates) and a &lt;code&gt;MAINTENANCE.md&lt;/code&gt; log, replacing the informal notes&lt;/li&gt;
&lt;li&gt;Recorded maintenance sessions for gitea, lnd and umami: full system upgrades, reboot autonomy tests and SSH hardening&lt;/li&gt;
&lt;li&gt;Added the lnd, lnbits/nostr and umami hosts to the inventory&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;website&#34;&gt;Website&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Self-service signup with a username and password, so users no longer have to accept an auto-generated account&lt;/li&gt;
&lt;li&gt;An events section on community and country pages, fed by the new &lt;code&gt;/v4/areas/{id}/events&lt;/code&gt; endpoint&lt;/li&gt;
&lt;li&gt;Android app metadata, and faster beta APK downloads via the CDN&lt;/li&gt;
&lt;li&gt;Dropped a vestigial areas and reports sync from the leaderboard pages&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;future-plans&#34;&gt;Future Plans&lt;/h2&gt;
&lt;p&gt;A few things on my mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I&amp;rsquo;ve just started a Kotlin Multiplatform shared module and a Compose Multiplatform rewrite of the UI, with a desktop app as the eventual payoff. That will dominate the next report.&lt;/li&gt;
&lt;li&gt;Cut the next Android release once the Compose work settles.&lt;/li&gt;
&lt;li&gt;Continue the API docs cleanup.&lt;/li&gt;
&lt;li&gt;Finish eradicating the legacy v2 endpoints from the website.&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map August Recap</title>
            <link>https://bubelov.com/blog/2026/btcmap-08/</link>
            <pubDate>Tue, 01 Sep 2026 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2026/btcmap-08/</guid>
            <description>&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: this only reflects my personal work this month. Visit the &lt;a href=&#34;https://blog.btcmap.org/&#34;&gt;BTC Map Blog&lt;/a&gt; for consolidated monthly reports.&lt;/p&gt;
&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#thanks&#34;&gt;Thanks&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#api&#34;&gt;API&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&#34;#geofences&#34;&gt;Geofences&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#area-manager&#34;&gt;Area Manager&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#place-reports&#34;&gt;Place Reports&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#rpc-refactor&#34;&gt;RPC Refactor&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#docs&#34;&gt;Docs&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#auth--logging&#34;&gt;Auth &amp;amp; Logging&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#electrum&#34;&gt;Electrum&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#area-bbox-sync&#34;&gt;Area BBox Sync&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#maintenance&#34;&gt;Maintenance&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#cli&#34;&gt;CLI&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#dashboard&#34;&gt;Dashboard&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#event-admin&#34;&gt;Event Admin&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#android&#34;&gt;Android&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&#34;#build-infrastructure&#34;&gt;Build Infrastructure&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#dev-tools&#34;&gt;Dev Tools&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#openstreetmap-attribution&#34;&gt;OpenStreetMap Attribution&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#bug-fixes--polish&#34;&gt;Bug Fixes &amp;amp; Polish&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#ansible&#34;&gt;Ansible&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#website&#34;&gt;Website&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#blog&#34;&gt;Blog&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#future-plans&#34;&gt;Future Plans&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;thanks&#34;&gt;Thanks&lt;/h2&gt;
&lt;p&gt;Thanks to &lt;a href=&#34;https://dalliard.ch/&#34;&gt;Nathanael&lt;/a&gt; for testing the new geofences and admin interface in Switzerland.&lt;/p&gt;
&lt;h2 id=&#34;api&#34;&gt;API&lt;/h2&gt;
&lt;p&gt;The API absorbed the bulk of my time again this month. The big theme was access control, since we need to decentralize admin work and let locals maintain their own data. A new &lt;code&gt;area_manager&lt;/code&gt; role and a per-user geofence that constrains both area and event managers to a region they are actually responsible for.&lt;/p&gt;
&lt;h3 id=&#34;geofences&#34;&gt;Geofences&lt;/h3&gt;
&lt;p&gt;I added a &lt;code&gt;geofence&lt;/code&gt; column to the &lt;code&gt;user&lt;/code&gt; table that holds a comma-separated list of area ids. When non-empty, its behavior is role-dependent:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;event_manager&lt;/code&gt; callers are rejected if the event&amp;rsquo;s &lt;code&gt;area_id&lt;/code&gt; or &lt;code&gt;(lat, lon)&lt;/code&gt; falls outside every fenced area&amp;rsquo;s GeoJSON.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;area_manager&lt;/code&gt; callers can only mutate areas with full &lt;code&gt;id&lt;/code&gt; match regardless of GeoJSON, so they can&amp;rsquo;t touch nested areas, and &lt;code&gt;add_area&lt;/code&gt; call is rejected outright (admins and roots still create areas on request).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;admin&lt;/code&gt; and &lt;code&gt;root&lt;/code&gt; are exempt, and an empty geofence means unrestricted.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new &lt;code&gt;set_user_geofence&lt;/code&gt; RPC sets or clears the whitelist.&lt;/p&gt;
&lt;h3 id=&#34;area-manager&#34;&gt;Area Manager&lt;/h3&gt;
&lt;p&gt;The new &lt;code&gt;Role::AreaManager&lt;/code&gt; unlocks &lt;code&gt;add_area&lt;/code&gt;, &lt;code&gt;get_area&lt;/code&gt;, &lt;code&gt;set_area_tag&lt;/code&gt;, &lt;code&gt;set_area_image&lt;/code&gt;, &lt;code&gt;remove_area_tag&lt;/code&gt;, &lt;code&gt;remove_area&lt;/code&gt; and &lt;code&gt;search&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;place-reports&#34;&gt;Place Reports&lt;/h3&gt;
&lt;p&gt;I added a new fire-and-forget &lt;code&gt;report_place&lt;/code&gt; RPC that lets trusted external sources record typed reports (&lt;code&gt;verified&lt;/code&gt;, &lt;code&gt;refused_sats&lt;/code&gt;, &lt;code&gt;out_of_business&lt;/code&gt;, &amp;hellip;) against an existing BTC Map place. It comes with a new &lt;code&gt;place_report&lt;/code&gt; table (&lt;code&gt;place_id&lt;/code&gt;, &lt;code&gt;origin_id&lt;/code&gt;, &lt;code&gt;extra_fields&lt;/code&gt; JSON, &lt;code&gt;ticket_url&lt;/code&gt; (populated by a future background job, not user-facing), and the usual soft-delete columns).&lt;/p&gt;
&lt;p&gt;I also added the public &lt;code&gt;GET /v4/place-submissions&lt;/code&gt; endpoint, which exposes open, non-revoked rows from &lt;code&gt;place_submission&lt;/code&gt; with an optional &lt;code&gt;source=&lt;/code&gt; filter.&lt;/p&gt;
&lt;h3 id=&#34;rpc-refactor&#34;&gt;RPC Refactor&lt;/h3&gt;
&lt;p&gt;Most area RPCs were moved from the flat &lt;code&gt;src/rpc/&lt;/code&gt; into dedicated &lt;code&gt;src/rpc/area/&lt;/code&gt; and &lt;code&gt;src/rpc/event/&lt;/code&gt; submodules. It is mostly churn, but it makes the directory tree match the docs tree.&lt;/p&gt;
&lt;p&gt;I also renamed &lt;code&gt;generate_bboxes&lt;/code&gt; to &lt;code&gt;generate_area_bboxes&lt;/code&gt; for consistency, and &lt;code&gt;generate_element_icons&lt;/code&gt; now iterates every element in the database via &lt;code&gt;select_updated_since(UNIX_EPOCH, ...)&lt;/code&gt; instead of looping over an id range.&lt;/p&gt;
&lt;h3 id=&#34;docs&#34;&gt;Docs&lt;/h3&gt;
&lt;p&gt;The area RPC docs were split from a single &lt;code&gt;area-methods.md&lt;/code&gt; into per-method files under &lt;code&gt;docs/rpc/area/&lt;/code&gt;, mirroring the structure already used by &lt;code&gt;docs/rpc/event/&lt;/code&gt;. Each file follows the event pattern: Description, Params, Result Format, Allowed Roles, and Examples. I also added an event RPC API index page and refreshed the main index pages.&lt;/p&gt;
&lt;h3 id=&#34;auth--logging&#34;&gt;Auth &amp;amp; Logging&lt;/h3&gt;
&lt;p&gt;Handlers (and the &lt;code&gt;rest::auth&lt;/code&gt; Auth extractor) now write the resolved user id into the request extensions via &lt;code&gt;AuthenticatedUser&lt;/code&gt;. The Log middleware reads it back so the request table records who is calling each endpoint instead of always leaving &lt;code&gt;user_id&lt;/code&gt; NULL.&lt;/p&gt;
&lt;p&gt;I also replaced the raw &lt;code&gt;Query returned no rows&lt;/code&gt; error that surfaced when calling an RPC with an unknown or revoked bearer token. It&amp;rsquo;s now a friendly &lt;code&gt;Invalid bearer token&lt;/code&gt; JSON-RPC error, with focused tests for both cases.&lt;/p&gt;
&lt;h3 id=&#34;electrum&#34;&gt;Electrum&lt;/h3&gt;
&lt;p&gt;A new &lt;code&gt;ping_electrum_servers&lt;/code&gt; RPC probes every configured electrum server in parallel with the standard &lt;code&gt;server.ping&lt;/code&gt; JSON-RPC request and reports per-server success/failure.&lt;/p&gt;
&lt;p&gt;Each server has a 5-second timeout. The outer call never fails because of a single unhealthy server — the results just carry &lt;code&gt;ok&lt;/code&gt; + &lt;code&gt;latency_ms&lt;/code&gt; or &lt;code&gt;ok=false&lt;/code&gt; + &lt;code&gt;error&lt;/code&gt;. Allowed for admin and root roles.&lt;/p&gt;
&lt;h3 id=&#34;area-bbox-sync&#34;&gt;Area BBox Sync&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;add_area&lt;/code&gt; and &lt;code&gt;set_area_tag&lt;/code&gt; (when applied with &lt;code&gt;geo_json&lt;/code&gt;) used to leave the &lt;code&gt;bbox_*&lt;/code&gt; columns stale until someone manually ran &lt;code&gt;generate_bboxes&lt;/code&gt;. Both paths now derive the bbox from the stored GeoJSON via the existing &lt;code&gt;BboxGenerator&lt;/code&gt; and update the columns in the same transaction. &lt;code&gt;set_area_tag&lt;/code&gt; also validates &lt;code&gt;geo_json&lt;/code&gt; before persisting it.&lt;/p&gt;
&lt;h3 id=&#34;maintenance&#34;&gt;Maintenance&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Pinned the build target CPU&lt;/li&gt;
&lt;li&gt;Fixed a pile of clippy lints&lt;/li&gt;
&lt;li&gt;Counted only active &lt;code&gt;area_elements&lt;/code&gt; in &lt;code&gt;generate_reports&lt;/code&gt; (it used to include soft-deleted ones)&lt;/li&gt;
&lt;li&gt;Filtered soft-deleted &lt;code&gt;area_elements&lt;/code&gt; from area-scoped feeds in &lt;code&gt;new_places_for_area&lt;/code&gt; and &lt;code&gt;get_comments&lt;/code&gt;, with a regression test&lt;/li&gt;
&lt;li&gt;Fixed &lt;code&gt;started_at&lt;/code&gt; being overwritten in the &lt;code&gt;generate_reports&lt;/code&gt; response&lt;/li&gt;
&lt;li&gt;Cleaned up several README files&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;cli&#34;&gt;CLI&lt;/h2&gt;
&lt;p&gt;The CLI picked up wrappers for most of the new API surface:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;place report&lt;/code&gt; calls the new &lt;code&gt;report_place&lt;/code&gt; RPC (the old &lt;code&gt;import&lt;/code&gt; module was renamed to &lt;code&gt;place&lt;/code&gt; to match)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;electrum-server ping&lt;/code&gt; wraps &lt;code&gt;ping_electrum_servers&lt;/code&gt; with an &lt;code&gt;--include-deleted&lt;/code&gt; flag matching &lt;code&gt;get_electrum_servers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;area add&lt;/code&gt; wraps &lt;code&gt;add_area&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;area generate-bboxes&lt;/code&gt; wraps the renamed &lt;code&gt;generate_area_bboxes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;element generate-icons&lt;/code&gt; was renamed from &lt;code&gt;generate-element-icons&lt;/code&gt; to match the new no-argument RPC signature&lt;/li&gt;
&lt;li&gt;&lt;code&gt;area generate-element-mapping&lt;/code&gt; was renamed from &lt;code&gt;generate-areas-elements-mapping&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;dashboard&#34;&gt;Dashboard&lt;/h2&gt;
&lt;p&gt;I hid bots and other non-user traffic from the unique IPs pie chart on the dashboard. They were swamping the slice for actual BTC Map users.&lt;/p&gt;
&lt;h2 id=&#34;event-admin&#34;&gt;Event Admin&lt;/h2&gt;
&lt;p&gt;Event editing is now fully wired up. The marker popup got a &lt;code&gt;Rename&lt;/code&gt; action that swaps the event name for an inline editor (Enter to save, Esc to cancel) and calls &lt;code&gt;update_event&lt;/code&gt; via RPC, and an &lt;code&gt;Edit&lt;/code&gt; button that opens the full event form.&lt;/p&gt;
&lt;p&gt;I also fixed a shadowed &lt;code&gt;event&lt;/code&gt; variable that was preventing &lt;code&gt;update_event&lt;/code&gt; from firing, and surfaced the real error message from the API&amp;rsquo;s &lt;code&gt;error.data&lt;/code&gt; envelope (e.g. &lt;code&gt;Location (51.5, -0.1) is outside your geofence&lt;/code&gt;) instead of the generic &lt;code&gt;Server error&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;android&#34;&gt;Android&lt;/h2&gt;
&lt;p&gt;Most of my Android work this month was around build infrastructure rather than features.&lt;/p&gt;
&lt;h3 id=&#34;build-infrastructure&#34;&gt;Build Infrastructure&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Bumped AGP to 9.3.2 and Gradle wrapper to 9.5.0&lt;/li&gt;
&lt;li&gt;Added release signing config (previously the signing key lived in CI; it now lives in &lt;code&gt;app/build.gradle.kts&lt;/code&gt; and the CI workflow drops its signing block)&lt;/li&gt;
&lt;li&gt;Added a new &lt;code&gt;beta&lt;/code&gt; build type, with a matching &lt;code&gt;app deploy&lt;/code&gt; command in the devtools script&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;dev-tools&#34;&gt;Dev Tools&lt;/h3&gt;
&lt;p&gt;I added a &lt;code&gt;devtools&lt;/code&gt; helper script at the repo root that wraps the common emulator and app commands: &lt;code&gt;emulator start/stop&lt;/code&gt;, &lt;code&gt;app install/run/uninstall/deploy&lt;/code&gt;. The script is documented in &lt;code&gt;AGENTS.md&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;openstreetmap-attribution&#34;&gt;OpenStreetMap Attribution&lt;/h3&gt;
&lt;p&gt;Added a small &amp;ldquo;© OpenStreetMap contributors&amp;rdquo; attribution overlay to the map fragment, with a settings toggle to show or hide it.&lt;/p&gt;
&lt;h3 id=&#34;bug-fixes--polish&#34;&gt;Bug Fixes &amp;amp; Polish&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Fixed a &lt;code&gt;ConcurrentModificationException&lt;/code&gt; in &lt;code&gt;ViewportCache&lt;/code&gt; by snapshotting items before serializing GeoJson when &lt;code&gt;onCameraIdle&lt;/code&gt; fires while a previous &lt;code&gt;loadInBounds&lt;/code&gt; coroutine is still iterating&lt;/li&gt;
&lt;li&gt;Updated the Material Symbols font to the 2026-08-28 snapshot, switched glyphs to the outlined variant, and added a handful of new icons (&lt;code&gt;18_up_rating&lt;/code&gt;, &lt;code&gt;destruction&lt;/code&gt;, &lt;code&gt;dresser&lt;/code&gt;, &lt;code&gt;favorite&lt;/code&gt;, &lt;code&gt;info&lt;/code&gt;, &lt;code&gt;water_drop&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;ansible&#34;&gt;Ansible&lt;/h2&gt;
&lt;p&gt;I moved the API backups to a new dedicated volume.&lt;/p&gt;
&lt;h2 id=&#34;website&#34;&gt;Website&lt;/h2&gt;
&lt;p&gt;I added Skate Spots as a new BTC Map app sponsor. Nothing else.&lt;/p&gt;
&lt;h2 id=&#34;blog&#34;&gt;Blog&lt;/h2&gt;
&lt;p&gt;I migrated one of my old historical BTC Map posts from this site into the official &lt;a href=&#34;https://blog.btcmap.org/&#34;&gt;BTC Map Blog&lt;/a&gt;, so all of our consolidated reporting now lives in one place.&lt;/p&gt;
&lt;h2 id=&#34;future-plans&#34;&gt;Future Plans&lt;/h2&gt;
&lt;p&gt;A few things on my mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cut a new Android release.&lt;/li&gt;
&lt;li&gt;Keep working on RPC documentation.&lt;/li&gt;
&lt;li&gt;Continue the RPC submodule migration.&lt;/li&gt;
&lt;li&gt;Add a dashboard widget for the place-report data once we have enough volume to make it interesting.&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map July Recap</title>
            <link>https://bubelov.com/blog/2026/btcmap-07/</link>
            <pubDate>Mon, 03 Aug 2026 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2026/btcmap-07/</guid>
            <description>&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: this only reflects my personal work this month. Visit the &lt;a href=&#34;https://blog.btcmap.org/&#34;&gt;BTC Map Blog&lt;/a&gt; for consolidated monthly reports.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2026/btcmap-07/events_hu_7fd6b177b13ab9fb.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2026/btcmap-07/events_hu_a3e087c0f9dc5f4d.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    &lt;figcaption&gt;Events&lt;/figcaption&gt;
&lt;/figure&gt;&lt;/p&gt;
&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#api&#34;&gt;API&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&#34;#wallets&#34;&gt;Wallets&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#electrum&#34;&gt;Electrum&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#platform-stats&#34;&gt;Platform Stats&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#config&#34;&gt;Config&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#maintenance&#34;&gt;Maintenance&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#android&#34;&gt;Android&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&#34;#caches&#34;&gt;Caches&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#controllers&#34;&gt;Controllers&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#area-screen&#34;&gt;Area Screen&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#activity-feed&#34;&gt;Activity Feed&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#event-admin&#34;&gt;Event Admin&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#dashboard&#34;&gt;Dashboard&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#cli&#34;&gt;CLI&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#future-plans&#34;&gt;Future Plans&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;api&#34;&gt;API&lt;/h2&gt;
&lt;p&gt;Most of my July went into the API, and most of that went into the wallet subsystem.&lt;/p&gt;
&lt;h3 id=&#34;wallets&#34;&gt;Wallets&lt;/h3&gt;
&lt;p&gt;I implemented wallet xpub tracking in order to improve internal transparency and observability. On-the-fly &lt;code&gt;electrs&lt;/code&gt; queries were pretty slow, so I also had to add a cache layer. The dashboard now reads from the snapshot instead of talking to Electrum directly.&lt;/p&gt;
&lt;h3 id=&#34;electrum&#34;&gt;Electrum&lt;/h3&gt;
&lt;p&gt;Electrum server configuration used to be a single &lt;code&gt;conf.electrum_url&lt;/code&gt; string. I moved it to a dedicated &lt;code&gt;electrum_server&lt;/code&gt; table managed by four new RPCs (&lt;code&gt;get_electrum_servers&lt;/code&gt;, &lt;code&gt;add_electrum_server&lt;/code&gt;, &lt;code&gt;update_electrum_server&lt;/code&gt;, &lt;code&gt;remove_electrum_server&lt;/code&gt;), with descending priority ordering and soft deletion.&lt;/p&gt;
&lt;p&gt;I also added a small experimental SPKI-pinned Electrum client built on rustls + x509-parser for self-hosted Electrum servers with self-signed certs.&lt;/p&gt;
&lt;h3 id=&#34;platform-stats&#34;&gt;Platform Stats&lt;/h3&gt;
&lt;p&gt;I added platform stats to the dashboard RPC. It reports which platforms hit us (Android, web, etc.) over the 1/7/30-day windows and groups calls by platform/client app name (if supplied), which is useful for prioritizing our limited resources and for anomaly detection.&lt;/p&gt;
&lt;h3 id=&#34;config&#34;&gt;Config&lt;/h3&gt;
&lt;p&gt;Boost element prices moved from three hardcoded &lt;code&gt;paywall_boost_element_{30,90,365}d_price_sat&lt;/code&gt; columns into a single &lt;code&gt;boost_element_prices&lt;/code&gt; JSON array, so admins can configure arbitrary boost durations.&lt;/p&gt;
&lt;h3 id=&#34;maintenance&#34;&gt;Maintenance&lt;/h3&gt;
&lt;p&gt;I unpegged the Rust toolchain, fixed a pile of clippy 1.96 lints, and derived &lt;code&gt;strum::AsRefStr&lt;/code&gt; on most &lt;code&gt;Columns&lt;/code&gt; enums.&lt;/p&gt;
&lt;h2 id=&#34;android&#34;&gt;Android&lt;/h2&gt;
&lt;p&gt;The big story this month is that &lt;code&gt;MapFragment&lt;/code&gt; is no longer a god class. It shed roughly 500 lines and is now a thin orchestrator over a handful of focused components.&lt;/p&gt;
&lt;h3 id=&#34;caches&#34;&gt;Caches&lt;/h3&gt;
&lt;p&gt;I extracted &lt;code&gt;MerchantsCache&lt;/code&gt; into its own file (with proper async query handling and bounds-split across the antimeridian), then mirrored the pattern for events and exchanges via &lt;code&gt;EventsCache&lt;/code&gt; and &lt;code&gt;ExchangesCache&lt;/code&gt;. All three share a new &lt;code&gt;ViewportCache&amp;lt;T&amp;gt;&lt;/code&gt; base class that handles the initial fetch in its &lt;code&gt;init&lt;/code&gt; block, the camera-idle follow-ups, query cancellation, and id-based deduplication.&lt;/p&gt;
&lt;h3 id=&#34;controllers&#34;&gt;Controllers&lt;/h3&gt;
&lt;p&gt;Four controllers were extracted from &lt;code&gt;MapFragment&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MapSetupController&lt;/code&gt; for map style and layer setup&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MapSelectionController&lt;/code&gt; for place/event/exchange selection&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SearchController&lt;/code&gt; for the search overlay&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LocationController&lt;/code&gt; (with a constructor race fixed in &lt;code&gt;ViewportCache&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new &lt;code&gt;publish.sh&lt;/code&gt; helper was added to the repo to streamline publishing new builds.&lt;/p&gt;
&lt;h3 id=&#34;area-screen&#34;&gt;Area Screen&lt;/h3&gt;
&lt;p&gt;Upcoming events are now displayed as clickable cards with icons in the area screen, with a dedicated background drawable. The Phuket area screen got its website URL overridden and aligned to start. One-off events are listed alongside upcoming events, with upcoming events sorted by date.&lt;/p&gt;
&lt;h3 id=&#34;activity-feed&#34;&gt;Activity Feed&lt;/h3&gt;
&lt;p&gt;Local activity feed gained filter support, so users can scope it to a specific area and period (filter icon added, menu and layout updated). Area image loading was optimized to avoid redundant network calls.&lt;/p&gt;
&lt;h2 id=&#34;event-admin&#34;&gt;Event Admin&lt;/h2&gt;
&lt;p&gt;I started a new internal project: Event Admin. It is a small static admin site that talks to the BTC Map API and lets admins browse, rename, and edit events directly on the map. The marker popup got a &lt;code&gt;Rename&lt;/code&gt; action that swaps the event name for an inline editor (Enter to save, Esc to cancel) and calls &lt;code&gt;update_event&lt;/code&gt; via RPC, and an &lt;code&gt;Edit&lt;/code&gt; button that opens the full event form.&lt;/p&gt;
&lt;h2 id=&#34;dashboard&#34;&gt;Dashboard&lt;/h2&gt;
&lt;p&gt;Dashboard caught up to the wallet work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Added platform stats&lt;/li&gt;
&lt;li&gt;Added wallet stats with snapshot timestamp&lt;/li&gt;
&lt;li&gt;Added per-wallet transaction popup&lt;/li&gt;
&lt;li&gt;Adapted the wallets UI to the new &lt;code&gt;wallet&lt;/code&gt; RPC shape (&lt;code&gt;add_wallet&lt;/code&gt;/&lt;code&gt;get_wallets&lt;/code&gt;/&lt;code&gt;update_wallet&lt;/code&gt;/&lt;code&gt;remove_wallet&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;cli&#34;&gt;CLI&lt;/h2&gt;
&lt;p&gt;The CLI gained wrappers for the new wallet and electrum server RPCs (&lt;code&gt;wallet add/get/update/remove&lt;/code&gt;, &lt;code&gt;electrum-server add/get/update/remove&lt;/code&gt;), a new &lt;code&gt;event update-event&lt;/code&gt; command, and type-specific search commands. Existing &lt;code&gt;event&lt;/code&gt; commands were synced with the new &lt;code&gt;update_event&lt;/code&gt;/&lt;code&gt;get_events&lt;/code&gt; shapes.&lt;/p&gt;
&lt;h2 id=&#34;future-plans&#34;&gt;Future Plans&lt;/h2&gt;
&lt;p&gt;A few things on my mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prepare a new Android release. The MapFragment refactor clears the runway.&lt;/li&gt;
&lt;li&gt;Keep pushing on the wallet side. New transaction notifications and more ergonomic CLI would be nice.&lt;/li&gt;
&lt;li&gt;Continue expanding the dashboard with more of the data we already collect.&lt;/li&gt;
&lt;li&gt;General API cleanup. The DB layer needs some love, and I also need a better taxonomy for all the RPCs we have.&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map June Recap</title>
            <link>https://bubelov.com/blog/2026/btcmap-06/</link>
            <pubDate>Wed, 01 Jul 2026 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2026/btcmap-06/</guid>
            <description>&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: this only reflects my personal work this month. Visit the &lt;a href=&#34;https://blog.btcmap.org/&#34;&gt;BTC Map Blog&lt;/a&gt; for consolidated monthly reports.&lt;/p&gt;
&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#dashboard&#34;&gt;Dashboard&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#api&#34;&gt;API&lt;/a&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;a href=&#34;#auth&#34;&gt;Auth&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#area-images&#34;&gt;Area Images&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#place-import-stats&#34;&gt;Place Import Stats&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#observability&#34;&gt;Observability&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;a href=&#34;#maintenance&#34;&gt;Maintenance&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#cli&#34;&gt;CLI&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#website&#34;&gt;Website&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#android&#34;&gt;Android&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#ansible&#34;&gt;Ansible&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#future-plans&#34;&gt;Future Plans&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;dashboard&#34;&gt;Dashboard&lt;/h2&gt;
&lt;p&gt;I started a new internal project this month: BTC Map Dashboard. It is a small static site that talks to the BTC Map API and renders the analytics snapshot from the new &lt;code&gt;dashboard&lt;/code&gt; RPC. I kept it deliberately tiny: no bundler, no framework, no build step, just plain HTML, CSS, and a few ES modules. The goal is to give admins a quick health check without having to SSH into our servers.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2026/btcmap-06/dashboard_hu_8aefd1fa5a1fb7da.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2026/btcmap-06/dashboard_hu_ed89ebd65f420e30.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    &lt;figcaption&gt;Dashboard&lt;/figcaption&gt;
&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&#34;api&#34;&gt;API&lt;/h2&gt;
&lt;p&gt;The biggest chunk of my month went into the API.&lt;/p&gt;
&lt;h3 id=&#34;auth&#34;&gt;Auth&lt;/h3&gt;
&lt;p&gt;I finally stabilized RPC auth flow for third party integrations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;signup&lt;/code&gt; is the new registration endpoint&lt;/li&gt;
&lt;li&gt;&lt;code&gt;signin&lt;/code&gt; issues an access token&lt;/li&gt;
&lt;li&gt;&lt;code&gt;signout&lt;/code&gt; revokes the current token&lt;/li&gt;
&lt;li&gt;&lt;code&gt;get_api_keys&lt;/code&gt; and &lt;code&gt;revoke_api_key&lt;/code&gt; let users inspect and invalidate their active sessions&lt;/li&gt;
&lt;li&gt;&lt;code&gt;whoami&lt;/code&gt; returns the linked account&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All non-auth RPCs now require an authenticated session. Anon access is limited to &lt;code&gt;signin&lt;/code&gt; and &lt;code&gt;signup&lt;/code&gt;. I also added support for scoped tokens, so the dashboard can be issued a token that can only call &lt;code&gt;dashboard&lt;/code&gt; and nothing else.&lt;/p&gt;
&lt;h3 id=&#34;area-images&#34;&gt;Area Images&lt;/h3&gt;
&lt;p&gt;This is the feature I am most excited about, after the dashboard. Up to now, area icons and banners were scattered between the main DB, the filesystem, and a few half-broken scripts. I introduced a dedicated &lt;code&gt;image.db&lt;/code&gt; table for area images, plus a new &lt;code&gt;v4/area-image&lt;/code&gt; REST endpoint with type and dimensions hints.&lt;/p&gt;
&lt;h3 id=&#34;place-import-stats&#34;&gt;Place Import Stats&lt;/h3&gt;
&lt;p&gt;Place import origins used to be hardcoded in a few Rust constants, which made it painful to onboard new wallets and merchant sources. I moved them into a dedicated DB table and exposed stats on the dashboard endpoint, including per-origin success/failure counts. A few long-dead endpoints and startup checks were deleted along the way.&lt;/p&gt;
&lt;h3 id=&#34;observability&#34;&gt;Observability&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;dashboard&lt;/code&gt; RPC now also returns log volume and counts of logged requests over the 1/7/30-day windows. A new &lt;code&gt;top_rest_api_calls&lt;/code&gt; block lists the ten busiest REST endpoints in the last 24 hours, which is useful for spotting abuse and unintentional hot paths. I also added LND and storage stats to the same response, refactored the log queries, and started logging HTTP methods on every request.&lt;/p&gt;
&lt;h3 id=&#34;maintenance&#34;&gt;Maintenance&lt;/h3&gt;
&lt;p&gt;I bumped &lt;code&gt;geojson&lt;/code&gt; to 1.0, unpegged the Rust toolchain, refreshed dependencies, and added native CORS handling so we can stop relying on the reverse proxy for it. The old &lt;code&gt;btcmap.db&lt;/code&gt; and &lt;code&gt;images.db&lt;/code&gt; files were renamed to &lt;code&gt;main.db&lt;/code&gt; and &lt;code&gt;image.db&lt;/code&gt; to match the rest of the naming.&lt;/p&gt;
&lt;h2 id=&#34;cli&#34;&gt;CLI&lt;/h2&gt;
&lt;p&gt;The CLI now speaks the new auth API. &lt;code&gt;signin&lt;/code&gt; returns the token under the &lt;code&gt;api_key&lt;/code&gt; field, &lt;code&gt;signout&lt;/code&gt; revokes the current token. I added two area image commands (&lt;code&gt;generate-area-icons&lt;/code&gt; and &lt;code&gt;set-area-image&lt;/code&gt;) and a simple install script, and reorganized the command tree now that there are quite a few subcommands.&lt;/p&gt;
&lt;h2 id=&#34;website&#34;&gt;Website&lt;/h2&gt;
&lt;p&gt;The tagging-issues and leaderboard pages were still hitting now authorized-only JSON-RPC endpoints. I migrated them to the public REST API, so our website is now finally RPC-free.&lt;/p&gt;
&lt;h2 id=&#34;android&#34;&gt;Android&lt;/h2&gt;
&lt;p&gt;Local activity feed got filter support, so users can scope it to a specific area and period. I also optimized area image loading and added a dedicated activity feed icon. MapLibre and a few other key dependencies were bumped.&lt;/p&gt;
&lt;h2 id=&#34;ansible&#34;&gt;Ansible&lt;/h2&gt;
&lt;p&gt;Image database backups were not actually happening. I added &lt;code&gt;image.db&lt;/code&gt; to the backup playbook, updated the snapshot script, and pruned a couple of dead helper files.&lt;/p&gt;
&lt;h2 id=&#34;future-plans&#34;&gt;Future Plans&lt;/h2&gt;
&lt;p&gt;No exact plans, but I&amp;rsquo;ll probably be improving dashboard and working towards a new Android app release.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map May Recap</title>
            <link>https://bubelov.com/blog/2026/btcmap-05/</link>
            <pubDate>Thu, 04 Jun 2026 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2026/btcmap-05/</guid>
            <description>&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: this only reflects my personal work this month. Visit the &lt;a href=&#34;https://blog.btcmap.org/&#34;&gt;BTC Map Blog&lt;/a&gt; for consolidated monthly reports.&lt;/p&gt;
&lt;h2 id=&#34;ansible&#34;&gt;Ansible&lt;/h2&gt;
&lt;p&gt;BTC Map servers are managed by different people and have no setup instructions, which makes it hard to maintain or reproduce our infrastructure. I&amp;rsquo;m trying to fix this with Ansible and have made some progress cleaning up and formalizing a few things on our main API server.&lt;/p&gt;
&lt;p&gt;The most notable change is our API logging. We had a few discussions, and the consensus was that we should keep logs for only 30 days. Logs are valuable for debugging, but we don&amp;rsquo;t want our users to leave a permanent record, even if it&amp;rsquo;s just IP addresses and other non-personally-identifiable information.&lt;/p&gt;
&lt;p&gt;Aside from privacy concerns, we don&amp;rsquo;t have much disk space, and keeping more data than necessary slows down our workflow. Now, 30-day log retention is automated.&lt;/p&gt;
&lt;h2 id=&#34;observability&#34;&gt;Observability&lt;/h2&gt;
&lt;p&gt;On the API side, I included top user agents in the daily infra report and added a few new analytical RPCs documenting the most useful queries.&lt;/p&gt;
&lt;p&gt;I also started working on a general admin dashboard endpoint. It may become part of our website or live as a standalone service at dashboard.btcmap.org or something.&lt;/p&gt;
&lt;h2 id=&#34;android&#34;&gt;Android&lt;/h2&gt;
&lt;p&gt;The update checker logic was tangled up with the main UI controller, which made it hard to maintain and test. I pulled it into a standalone component and added a few tests.&lt;/p&gt;
&lt;p&gt;I also tightened up back button and gesture handling and removed a couple of shared mutable state issues that occasionally caused some annoying bugs.&lt;/p&gt;
&lt;h2 id=&#34;future-plans&#34;&gt;Future Plans&lt;/h2&gt;
&lt;p&gt;I don&amp;rsquo;t have any specific plans or hard commitments, but I will probably focus on these three areas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dashboard endpoint + UI, to improve observability&lt;/li&gt;
&lt;li&gt;Refactoring and improving the place import pipeline to onboard new wallets and other merchant sources&lt;/li&gt;
&lt;li&gt;More infrastructure documentation and formalization to simplify maintenance and address the bus factor&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map April Recap</title>
            <link>https://bubelov.com/blog/2026/btcmap-04/</link>
            <pubDate>Sat, 02 May 2026 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2026/btcmap-04/</guid>
            <description>&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: this only reflects my personal work this week. Visit the &lt;a href=&#34;https://blog.btcmap.org/&#34;&gt;BTC Map Blog&lt;/a&gt; for consolidated monthly reports.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2026/btcmap-04/feed_hu_1fc52df6f649a6b7.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2026/btcmap-04/feed_hu_e6f07cae771c272.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    &lt;figcaption&gt;Activity feed&lt;/figcaption&gt;
&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&#34;auth&#34;&gt;Auth&lt;/h2&gt;
&lt;p&gt;BTC Map now has opt-in authentication, and it&amp;rsquo;s a necessary step in the project&amp;rsquo;s evolution. In organic communities, admins often start as regular users, so onboarding new admins is difficult without a pool of user accounts that have built up digital reputation over time.&lt;/p&gt;
&lt;p&gt;Another reason to sign up is the ability to save places and areas, which enables personalized activity feeds based on your locations of interest.&lt;/p&gt;
&lt;h2 id=&#34;activity-feeds&#34;&gt;Activity Feeds&lt;/h2&gt;
&lt;p&gt;Looking at maps is fun, but it&amp;rsquo;s almost impossible to see what&amp;rsquo;s changed since your last visit. Maybe your city had 50 Bitcoin merchants and now it has 51. How do you find that needle in a haystack?&lt;/p&gt;
&lt;p&gt;Solving such problems requires a temporal activity feed. The feed can be scoped to a local area or a set of your favorite places and areas. I believe this feature will improve BTC Map&amp;rsquo;s usability in a big way.&lt;/p&gt;
&lt;h2 id=&#34;performance&#34;&gt;Performance&lt;/h2&gt;
&lt;p&gt;My performance work focused on improving cold start time in the Android app. Previously, it queried all places and fed them to a clustering engine, which took about a second to complete. As a result, users stared at an empty map while waiting for places to load.&lt;/p&gt;
&lt;p&gt;The new algorithm only queries the visible area, with some safety margins, to avoid re-querying the database if the user moves the map slightly.&lt;/p&gt;
&lt;h2 id=&#34;website&#34;&gt;Website&lt;/h2&gt;
&lt;p&gt;No contributions&lt;/p&gt;
&lt;h2 id=&#34;api&#34;&gt;API&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;REST authentication&lt;/li&gt;
&lt;li&gt;New endpoints for managing saved places and areas&lt;/li&gt;
&lt;li&gt;Allow binding events to areas&lt;/li&gt;
&lt;li&gt;Support cron-like schedules for recurring events&lt;/li&gt;
&lt;li&gt;Support wide icons for areas&lt;/li&gt;
&lt;li&gt;Documentation updates&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;android&#34;&gt;Android&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Implement authentication&lt;/li&gt;
&lt;li&gt;Add saved places and areas management UI&lt;/li&gt;
&lt;li&gt;Implement activity feed&lt;/li&gt;
&lt;li&gt;Display upcoming events in the activity feed based on cron schedules&lt;/li&gt;
&lt;li&gt;Filter out outdated places by default&lt;/li&gt;
&lt;li&gt;Speed up cold start&lt;/li&gt;
&lt;li&gt;Add area screen&lt;/li&gt;
&lt;li&gt;Improve module isolation and composition&lt;/li&gt;
&lt;li&gt;Increase test coverage&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;future-plans&#34;&gt;Future Plans&lt;/h2&gt;
&lt;p&gt;The Android app will need some polish before it&amp;rsquo;s ready for the next release, so I suspect I&amp;rsquo;ll be busy with that. There are also quite a few things to refactor and optimize on the API side, so that will be my secondary priority.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map March Recap</title>
            <link>https://bubelov.com/blog/2026/btcmap-03/</link>
            <pubDate>Wed, 01 Apr 2026 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2026/btcmap-03/</guid>
            <description>&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: this only reflects my personal work this week. Visit the &lt;a href=&#34;https://blog.btcmap.org/&#34;&gt;BTC Map Blog&lt;/a&gt; for consolidated monthly reports.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2026/btcmap-03/communities_hu_83b0fa427247baa6.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2026/btcmap-03/communities_hu_d89b3b521dda539e.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    &lt;figcaption&gt;Nearby communities&lt;/figcaption&gt;
&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&#34;global-direction&#34;&gt;Global Direction&lt;/h2&gt;
&lt;p&gt;My focus in March was on performance, discoverability, and multi-language support.&lt;/p&gt;
&lt;p&gt;Those things might sound random, but if you&amp;rsquo;ve ever used the BTC Map website, you probably know that some pages are borderline unusable. They can take a few minutes to load or just hang forever. Websites are not something I have a lot of experience with, but I was able to improve things on the performance front.&lt;/p&gt;
&lt;p&gt;Performance can only get you so far if you don&amp;rsquo;t know where to look. BTC Map data is fragmented across many pages with weak or no interlinking. The best improvement I was able to deliver was showing nearby communities to users browsing the map. Many users are unaware that we offer interesting insights on local communities, and that we help communities onboard new members by showing their main contact links.&lt;/p&gt;
&lt;p&gt;Speaking of language, only half of our users prefer English (based on browser language preference), but it was the only supported language until recently. I believe that improving language support can bring us more users, as many local bitcoiners in the place where I live aren&amp;rsquo;t comfortable using English at all.&lt;/p&gt;
&lt;h2 id=&#34;website&#34;&gt;Website&lt;/h2&gt;
&lt;p&gt;Performance-wise, I was able to speed up our leaderboards, including top editors, top countries, and top communities. Those pages now often load in under a second, even from a cold start.&lt;/p&gt;
&lt;p&gt;There are no gains in discoverability yet, aside from showing more data on our dashboard. But it&amp;rsquo;s a good start, since it reminds us that most of our communities have missed their re-verification deadline (set to one year). We need to fix this ASAP.&lt;/p&gt;
&lt;p&gt;I also authored a few patches improving multi-language support and added a Russian translation. Neither is perfect yet, but at least things are set in motion.&lt;/p&gt;
&lt;h2 id=&#34;api&#34;&gt;API&lt;/h2&gt;
&lt;p&gt;Most API changes I authored focused on supporting localized names and adding optimized endpoints aimed at improving website performance.&lt;/p&gt;
&lt;p&gt;I also conducted an experiment using LLMs to translate hard-to-parse OSM working hours into a human-readable format. This feature is working fine, and I rolled it out to a few regions.&lt;/p&gt;
&lt;p&gt;Our Overpass sync started having some hard-to-debug issues, which motivated me to improve observability in that area. Now our API saves all the important details about every Overpass sync run, whether successful or not.&lt;/p&gt;
&lt;p&gt;I was also able to repair country flags and pave the way for storing all area images in an SQLite database, which is our medium-term goal.&lt;/p&gt;
&lt;h2 id=&#34;android&#34;&gt;Android&lt;/h2&gt;
&lt;p&gt;I finally released BTC Map Android v1.1.0, which is something I worked on since November 2025. Here are some release highlights:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add Carto Dark Matter map style&lt;/li&gt;
&lt;li&gt;Display current country and nearby communities on the map&lt;/li&gt;
&lt;li&gt;Enable map rotation&lt;/li&gt;
&lt;li&gt;Display localized place names&lt;/li&gt;
&lt;li&gt;Improve opening hours display and translation&lt;/li&gt;
&lt;li&gt;Improve clustering&lt;/li&gt;
&lt;li&gt;Make adaptive color scheme opt in, default to website colors&lt;/li&gt;
&lt;li&gt;Improve payment flow&lt;/li&gt;
&lt;li&gt;Add support for many new languages&lt;/li&gt;
&lt;li&gt;Improve testability and test coverage&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&amp;rsquo;re an Android app user, I encourage you to update and leave your feedback.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Another productive month, but there&amp;rsquo;s still a lot of technical debt to address and new ideas to experiment with.&lt;/p&gt;
&lt;p&gt;One thing I&amp;rsquo;ve been considering is adding a list-based activity feed alongside our default map view. Something like a social media activity feed, but scoped to Bitcoin-only activity in your area or the areas you&amp;rsquo;re watching. As a cherry on top, we could add bitcoiner event notifications there, improving discoverability by interlinking the lesser known features we offer.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map February Recap</title>
            <link>https://bubelov.com/blog/2026/btcmap-02/</link>
            <pubDate>Sun, 01 Mar 2026 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2026/btcmap-02/</guid>
            <description>&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: this only reflects my personal work this week. Visit the &lt;a href=&#34;https://blog.btcmap.org/&#34;&gt;BTC Map Blog&lt;/a&gt; for consolidated monthly reports.&lt;/p&gt;
&lt;h2 id=&#34;infra&#34;&gt;Infra&lt;/h2&gt;
&lt;h3 id=&#34;backup-server&#34;&gt;Backup Server&lt;/h3&gt;
&lt;p&gt;BTC Map infrastructure is hacky, mostly because we lack contributors with strong ops skills. I handle most maintenance, but I&amp;rsquo;m no expert, and I tend to prioritize fun tasks over boring ones.&lt;/p&gt;
&lt;p&gt;Backups are boring, but you can&amp;rsquo;t avoid them forever as the project grows. Our old backup system was too unreliable, so I finally forced myself to set up a dedicated backup server.&lt;/p&gt;
&lt;p&gt;This server regularly fetches critical data from the API server. While the API server is accessible to the whole team, this server is only accessible by me. That protects our backups if someone else on the team is hacked, but if I&amp;rsquo;m hacked, it&amp;rsquo;s game over.&lt;/p&gt;
&lt;p&gt;Not ideal, but better than the status quo, and the places themselves are hosted on OSM with an excellent decentralized backup system. More people with API server access should set up their own backups to improve the new setup, and I&amp;rsquo;m planning to help with that.&lt;/p&gt;
&lt;h3 id=&#34;ansible&#34;&gt;Ansible&lt;/h3&gt;
&lt;p&gt;Our servers are undocumented. That&amp;rsquo;s something we&amp;rsquo;ll need to fix long-term. I started drafting Ansible configs to slowly document our existing fleet. It already partially covers two servers, but there&amp;rsquo;s a lot of work ahead.&lt;/p&gt;
&lt;h2 id=&#34;website&#34;&gt;Website&lt;/h2&gt;
&lt;h3 id=&#34;merchant-page-speedup&#34;&gt;Merchant Page Speedup&lt;/h3&gt;
&lt;p&gt;The merchant page is one of the most-used in the web app, and its performance was abysmal due to a full API sync dependence. A full sync means fetching up to a million JSON objects, which is not optimal for a random visitor with no pre-existing cache.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not sure why it relied on a full sync, probably legacy UI design decisions that didn&amp;rsquo;t account for API capabilities. I added a few new endpoints to break away from the sync, leading to orders-of-magnitude performance improvements for cold clients. Things that often took minutes now load in seconds or less.&lt;/p&gt;
&lt;h3 id=&#34;events-map&#34;&gt;Events Map&lt;/h3&gt;
&lt;p&gt;The events map is still an unmerged draft, but it could be an important step for BTC Map web app (Android app has it already). In many regions, Bitcoin events and meetups are more popular than merchants, and there&amp;rsquo;s no good source for event data.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/teambtcmap/btcmap.org/pull/757&#34;&gt;https://github.com/teambtcmap/btcmap.org/pull/757&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;android&#34;&gt;Android&lt;/h2&gt;
&lt;p&gt;Preview builds are available here: &lt;a href=&#34;https://github.com/teambtcmap/btcmap-android/releases/tag/preview&#34;&gt;https://github.com/teambtcmap/btcmap-android/releases/tag/preview&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;improved-clustering&#34;&gt;Improved Clustering&lt;/h3&gt;
&lt;p&gt;The new clustering approach offers a smooth user experience, but it required significant refactoring and testing. It finally feels stable enough to release, I&amp;rsquo;m planning to roll out a new Android app version next month.&lt;/p&gt;
&lt;p&gt;A nice side effect: map rotation is back. The old clustering didn&amp;rsquo;t support it, so I had to disable it.&lt;/p&gt;
&lt;h3 id=&#34;website-styles&#34;&gt;Website Styles&lt;/h3&gt;
&lt;p&gt;Custom user themes work fine for normal widgets, but the map isn&amp;rsquo;t a normal widget as it can introduce contrast issues. Some people also use light map styles in dark mode and vice versa.&lt;/p&gt;
&lt;p&gt;The new Android app uses well-tested website colors by default, which work well in both light and dark modes. I tested them with all supported map styles and liked the results.&lt;/p&gt;
&lt;p&gt;You can still opt into custom Material colors through settings, or set your own. The Android app is now the most customizable Bitcoin map out there.&lt;/p&gt;
&lt;h2 id=&#34;api&#34;&gt;API&lt;/h2&gt;
&lt;h3 id=&#34;logging&#34;&gt;Logging&lt;/h3&gt;
&lt;p&gt;Our API logs all requests for analytics and debugging. That data isn&amp;rsquo;t connected to user accounts (users don&amp;rsquo;t even have accounts), and old records are auto-erased, saving storage costs and ensuring we don&amp;rsquo;t keep permanent records.&lt;/p&gt;
&lt;p&gt;The new logging system is much faster and saves additional fields like user agent. That&amp;rsquo;s handy for debugging, the latest example was accidentally banning our own e2e test runner for API abuse.&lt;/p&gt;
&lt;h3 id=&#34;og-cache&#34;&gt;OG Cache&lt;/h3&gt;
&lt;p&gt;OpenGraph images are what you see when sharing links. For BTC Map merchants, you&amp;rsquo;ll see a map with a pin in the middle. These images are generated on the fly by our API, but they rely on OSM tile servers, and we don&amp;rsquo;t want to abuse their generosity.&lt;/p&gt;
&lt;p&gt;The new cache ensures we only ask OSM servers once per merchant, reducing load on their infrastructure and improving our own latency.&lt;/p&gt;
&lt;h3 id=&#34;new-database-structure&#34;&gt;New Database Structure&lt;/h3&gt;
&lt;p&gt;BTC Map&amp;rsquo;s database now consists of three simple files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;main.db&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;images.db&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;log.db&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The names are self-descriptive, and the structure makes our data portable. For example, the backup server can just use &lt;code&gt;sqlite3_rsync&lt;/code&gt; on these files for incremental backups.&lt;/p&gt;
&lt;h3 id=&#34;fetching-place-areas&#34;&gt;Fetching Place Areas&lt;/h3&gt;
&lt;p&gt;This endpoint is handy when showing a BTC Map location and you also want to show which communities or country it belongs to.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://api.btcmap.org/v4/places/20423/areas&#34;&gt;https://api.btcmap.org/v4/places/20423/areas&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;fetching-place-activity&#34;&gt;Fetching Place Activity&lt;/h3&gt;
&lt;p&gt;This endpoint adds optional context to places, useful for third-party apps. Currently, it shows core lifecycle events (created, updated, deleted). I plan to add &amp;ldquo;commented&amp;rdquo; and &amp;ldquo;boosted&amp;rdquo; events in the future.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://api.btcmap.org/v4/places/8660/activity&#34;&gt;https://api.btcmap.org/v4/places/8660/activity&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;developer-portal&#34;&gt;Developer Portal&lt;/h2&gt;
&lt;p&gt;Since BTC Map clients don&amp;rsquo;t support user accounts, some sensitive operations can&amp;rsquo;t be done anonymously. We do have an auth system, used by moderators and third-party integrations.&lt;/p&gt;
&lt;p&gt;Onboarding new accounts has always been hard, so I created a simple website that automates signups and API key management.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://developer.btcmap.org/&#34;&gt;https://developer.btcmap.org/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;It was a productive month. I&amp;rsquo;m especially proud of improving our fundamentals: cleaning up API data and dramatically speeding up the merchant page.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map January Recap</title>
            <link>https://bubelov.com/blog/2026/btcmap-01/</link>
            <pubDate>Sun, 01 Feb 2026 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2026/btcmap-01/</guid>
            <description>&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: this only reflects my personal work in January. Visit &lt;a href=&#34;https://blog.btcmap.org/&#34;&gt;BTC Map Blog&lt;/a&gt; to get consolidated monthly reports.&lt;/p&gt;
&lt;h2 id=&#34;discord-is-no-more&#34;&gt;Discord Is No More&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m proud to report that BTC Map is no longer dependent on Discord. I migrated the remainder of our channels and bots to our new Matrix space.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve also removed the Discord links from the landing page footer. I guess we&amp;rsquo;ll just let the old server slowly fade away.&lt;/p&gt;
&lt;h2 id=&#34;android-clustering&#34;&gt;Android Clustering&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s been good progress on a new clustering method for the Android app. The animations feel smooth, but there&amp;rsquo;s a noticeable performance hit. I&amp;rsquo;ll keep working with this API since the old one has been deprecated by MapLibre.&lt;/p&gt;
&lt;h2 id=&#34;health-checks&#34;&gt;Health Checks&lt;/h2&gt;
&lt;p&gt;The API health checks are working fine, but I noticed a few website health check failures. I&amp;rsquo;ve added more logging, and it looks like there are some SSL issues (curl exit code 35):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;111B blob data&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: * IPv6: &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;none&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: * IPv4: 75.2.60.5
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: *   Trying 75.2.60.5:443...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: * ALPN: curl offers h2,http/1.1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt; bytes data&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: * TLSv1.3 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;OUT&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;, TLS handshake, Client hello &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;1&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1554&lt;/span&gt; bytes data&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: * SSL Trust Anchors:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: *   CAfile: /etc/ssl/certs/ca-certificates.crt
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;2.1K blob data&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: * TLS connect error: error:00000000:lib&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;::reason&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;0&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: * OpenSSL SSL_connect: Connection reset by peer in connection to btcmap.org:443
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;76B blob data&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: * closing connection &lt;span class=&#34;c1&#34;&gt;#0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;healthcheck&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;898007&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: curl: &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;35&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; Recv failure: Connection reset by peer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m not entirely sure what&amp;rsquo;s causing it, but it looks like the issue is on Netlify&amp;rsquo;s side. I&amp;rsquo;ll keep monitoring that curl call to collect more data.&lt;/p&gt;
&lt;h2 id=&#34;event-api&#34;&gt;Event API&lt;/h2&gt;
&lt;p&gt;Events are still an experimental feature I added for fun in the Android app. The goal is to see if there&amp;rsquo;s any organic demand for it.&lt;/p&gt;
&lt;p&gt;I personally maintain a few events in Asia, but we were recently contacted by the guy behind &lt;a href=&#34;https://bitcoinwalk.org/&#34;&gt;BitcoinWalk&lt;/a&gt;, who wanted to sync our databases.&lt;/p&gt;
&lt;p&gt;The problem was, we didn&amp;rsquo;t have an event API or event-scoped admin roles. So I built the missing endpoints, and they&amp;rsquo;re now live. BitcoinWalk is already using the new API, which is why you can see dozens of new events in the BTC Map Android app.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re a web or iOS developer and want to see events on your platform, pull requests are welcome.&lt;/p&gt;
&lt;h2 id=&#34;payment-infra&#34;&gt;Payment Infra&lt;/h2&gt;
&lt;p&gt;We care about privacy, but we also don&amp;rsquo;t want spam, so we&amp;rsquo;ve spent a lot of time messing with paywalls. Our apps don&amp;rsquo;t require signups, but some stuff, like anonymous comments and boosts, will cost you a few sats. We weren&amp;rsquo;t sure if users would bite, but we&amp;rsquo;ve seen a steady trickle of paid invoices.&lt;/p&gt;
&lt;p&gt;Our old invoicing server is a total hack job though. It&amp;rsquo;s unreliable and held together by digital duct tape. My main mission in January was to finally fix this mess.&lt;/p&gt;
&lt;p&gt;I looked at a few options and ended up with a new server running &lt;code&gt;Bitcoin Core/Knots&lt;/code&gt; and &lt;code&gt;LND&lt;/code&gt;. Our old setup used the LNBits API, which was always the weakest link. The other headache was &lt;code&gt;CLN&lt;/code&gt;, which is a maintenance nightmare. I&amp;rsquo;m a big fan of the single-binary approach (thanks, &lt;code&gt;bitcoind&lt;/code&gt;), and &lt;code&gt;LND&lt;/code&gt; gets that right.&lt;/p&gt;
&lt;p&gt;The new server is live. I&amp;rsquo;ll probably keep the old one around as a backup. By routing all new invoices to the new box, I can finally poke at the old one without breaking everything.&lt;/p&gt;
&lt;h2 id=&#34;sharing-knowledge&#34;&gt;Sharing Knowledge&lt;/h2&gt;
&lt;p&gt;I also wrote up my whole node setup quest in a &lt;a href=&#34;https://bubelov.com/blog/2026/how-to-accept-bitcoin/&#34;&gt;dedicated post&lt;/a&gt;. I&amp;rsquo;ll probably follow up with a few more deep-dives, but this is a solid start.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map December Recap</title>
            <link>https://bubelov.com/blog/2025/btcmap-12/</link>
            <pubDate>Wed, 31 Dec 2025 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2025/btcmap-12/</guid>
            <description>&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: this only reflects my personal work in December. Visit the &lt;a href=&#34;https://blog.btcmap.org/&#34;&gt;BTC Map Blog&lt;/a&gt; for consolidated monthly reports.&lt;/p&gt;
&lt;h2 id=&#34;improve-startup-time&#34;&gt;Improve Startup Time&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m gradually moving BTC Map API chat automations from Discord to Matrix. The first experimental Matrix integration was blocking and significantly increased API server startup time (from ~2 seconds to ~10+ seconds). In December, I set up an asynchronous lazy initialization, and it seems to be working well.&lt;/p&gt;
&lt;h2 id=&#34;drop-boosts-table&#34;&gt;Drop Boosts Table&lt;/h2&gt;
&lt;p&gt;Boosts now use the REST API and can be performed anonymously. That means it&amp;rsquo;s not a good idea to rely on the old boosts table, which is tied to admin RPC and requires specific fields like an admin user ID. It was causing issues in the internal reporting, so I decided to remove the table entirely. The generic &lt;code&gt;invoice&lt;/code&gt; table is sufficient and is already fully integrated into our REST API. Anonymous users can request invoices for sat-walled actions like leaving a comment or boosting a merchant. Once those invoices are paid, we perform the associated actions directly, no extra tables are needed, and we can rely on invoice metadata alone.&lt;/p&gt;
&lt;h2 id=&#34;rpc-log&#34;&gt;RPC Log&lt;/h2&gt;
&lt;p&gt;We still have a few Discord hooks that fire when sensitive admin RPC calls are made. Since we&amp;rsquo;re moving from Discord to Matrix, I spent some time reviewing those ad-hoc notifications and realized our current approach doesn&amp;rsquo;t scale well.&lt;/p&gt;
&lt;p&gt;So I created a dedicated table to log all RPC calls. This enables a few new uses. We can still monitor the log and send Matrix notifications for critical events, but it&amp;rsquo;s also a fully structured storage that we can expose via the same API. That opens a path to building our own admin web interface.&lt;/p&gt;
&lt;p&gt;Storing the log in a structured, platform-agnostic way is a solid improvement, and it also lets us simplify the code quite a bit.&lt;/p&gt;
&lt;h2 id=&#34;health-checks&#34;&gt;Health Checks&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;ve always had a hard time tracking whether our most critical systems were actually up. We used to rely on an external &amp;ldquo;uptime bot&amp;rdquo;, which caused constant headaches with false positives and sneaky, almost DDoS-like behavior.&lt;/p&gt;
&lt;p&gt;I ended up writing a few scripts that probe the health of our key components. Now if something goes down, the script can send a notification straight to Matrix.&lt;/p&gt;
&lt;h2 id=&#34;organize-rpc-calls&#34;&gt;Organize RPC Calls&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;rpc&lt;/code&gt; module is a mess, so I spent time cleaning it up. The work is far from done, but at least there&amp;rsquo;s progress!&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map November Recap: Steady Growth, Challenges, and Community Contributions</title>
            <link>https://bubelov.com/blog/2024/btcmap-nov/</link>
            <pubDate>Sun, 01 Dec 2024 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2024/btcmap-nov/</guid>
            <description>&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#dev-updates-stability-observability-and-performance&#34;&gt;Dev Updates: Stability, Observability, and Performance&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#admin-updates-growing-areas-backlog&#34;&gt;Admin Updates: Growing Areas Backlog&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#trending-countries&#34;&gt;Trending Countries&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#trending-communities&#34;&gt;Trending Communities&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#global-metrics&#34;&gt;Global Metrics&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;dev-updates-stability-observability-and-performance&#34;&gt;Dev Updates: Stability, Observability, and Performance&lt;/h2&gt;
&lt;p&gt;November was a relatively quiet month, with a focus on addressing technical debt and resolving performance bottlenecks in the BTC Map backend. No other development activities related to BTC Map were reported.&lt;/p&gt;
&lt;h2 id=&#34;admin-updates-growing-areas-backlog&#34;&gt;Admin Updates: Growing Areas Backlog&lt;/h2&gt;
&lt;p&gt;Rockedf continues to manage our places backlog efficiently, with no tasks left unhandled. However, the areas backlog continues to grow due to limited admin activity.&lt;/p&gt;
&lt;h2 id=&#34;trending-countries&#34;&gt;Trending Countries&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/za&#34;&gt;South Africa&lt;/a&gt; - 410 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/br&#34;&gt;Brazil&lt;/a&gt; - 220 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/it&#34;&gt;Italy&lt;/a&gt; - 116 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/th&#34;&gt;Thailand&lt;/a&gt; - 107 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/ch&#34;&gt;Switzerland&lt;/a&gt; - 67 changes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;South Africa led the way with the most changes, primarily focused on data updates. Brazil added nearly 100 new places and re-verified many existing ones. Italy saw significant data quality improvements due to dedicated maintenance efforts. Thailand&amp;rsquo;s changes were driven by a &lt;a href=&#34;https://www.matichon.co.th/local/news_4918882&#34;&gt;new local community&lt;/a&gt;. Switzerland experienced a minor data quality improvement, mostly related to a local ATM network.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-nov/merchant_hu_91494a34e76fcde1.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-nov/merchant_hu_a4896474ee961425.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    &lt;figcaption&gt;Bitcoin merchant in Thailand.&lt;/figcaption&gt;
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;A big thanks to &lt;a href=&#34;https://btcmap.org/tagger/7522075&#34;&gt;Rockedf&lt;/a&gt; for contributing to almost every region!&lt;/p&gt;
&lt;h2 id=&#34;trending-communities&#34;&gt;Trending Communities&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/bitcoin-amantikir&#34;&gt;Bitcoin Amantikir&lt;/a&gt; - 92 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/bitcoin-witsand&#34;&gt;Bitcoin Witsand&lt;/a&gt; - 79 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/bitcoin-cape-town-monthly-meetup&#34;&gt;Bitcoin Cape Town Monthly Meetup&lt;/a&gt; - 50 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/bitshack&#34;&gt;Bitshack&lt;/a&gt; - 35 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/free-madeira&#34;&gt;FREE Madeira&lt;/a&gt; - 33 changes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Bitcoin Amantikir achieved a flawless 100% up-to-date rating through dedicated efforts. Bitcoin Witsand maintained its high rating, solidifying its position as one of Africa&amp;rsquo;s top Bitcoin hubs.&lt;/p&gt;
&lt;h2 id=&#34;global-metrics&#34;&gt;Global Metrics&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Verified merchants increased by 1.3% to 7,055, continuing the upward trend.&lt;/li&gt;
&lt;li&gt;Total merchants grew by 3.2% to 12,689, double the long-term trend.&lt;/li&gt;
&lt;li&gt;The average verification age increased by 4% to 357 days, slightly reducing data reliability.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;New merchant additions are at an all-time high, but maintaining up-to-date records remains a challenge. The main bottleneck continues to be the lack of local maintainers.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Overall, progress is positive, but we need to address the following key issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Many locations are outdated, and we need additional maintainers to verify merchant status and Bitcoin acceptance.&lt;/li&gt;
&lt;li&gt;We aim to highlight top-performing merchants to improve discoverability. Comments are currently unavailable on our iOS app and website due to a lack of active developers. We welcome contributions from anyone with relevant skills.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The best way to help is by re-verifying &lt;a href=&#34;https://btcmap.org/map?outdated&#34;&gt;outdated locations&lt;/a&gt; in your area.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map Monthly Recap - October 2024</title>
            <link>https://bubelov.com/blog/2024/btcmap-oct/</link>
            <pubDate>Fri, 01 Nov 2024 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2024/btcmap-oct/</guid>
            <description>&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#merchant-comments&#34;&gt;Merchant Comments&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#vector-maps&#34;&gt;Vector Maps&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#trending-countries&#34;&gt;Trending Countries&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#trending-communities&#34;&gt;Trending Communities&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#global-metrics&#34;&gt;Global Metrics&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;merchant-comments&#34;&gt;Merchant Comments&lt;/h2&gt;
&lt;p&gt;I released merchant comments API last month, and I was busy integrating it in our Android app. Here are my key observations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Comments are a solid quality indicator, so I decided to show the number of comments on map pins, making it super easy to discover the highest quality merchants&lt;/li&gt;
&lt;li&gt;Comments are extremely valuable, they often contain useful tips and warnings, and they also mention discounts and promotions&lt;/li&gt;
&lt;li&gt;Comments are currently our best source of data on real user activity. Areas without comments are suspicious, so we can use comment data to identify fake or abandoned areas&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-oct/comments_hu_5960506c886753ce.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-oct/comments_hu_34d9b1a53f41c23b.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    &lt;figcaption&gt;Map markers with the number of comments&lt;/figcaption&gt;
&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&#34;vector-maps&#34;&gt;Vector Maps&lt;/h2&gt;
&lt;p&gt;We had some good progress on switching to open source vector map dataset, powered by &lt;a href=&#34;https://openfreemap.org/&#34;&gt;OpenFreeMap&lt;/a&gt;. After some initial discussions and tests, we decided to go ahead and roll out vector maps in the coming weeks. OpenFreeMap is a really cool project, our users can even self-host their own map data provider by following &lt;a href=&#34;https://github.com/hyperknot/openfreemap/blob/main/docs/self_hosting.md&#34;&gt;the official instructions&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;trending-countries&#34;&gt;Trending Countries&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/br&#34;&gt;Brazil&lt;/a&gt; - 309 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/nl&#34;&gt;Netherlands&lt;/a&gt; - 202 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/it&#34;&gt;Italy&lt;/a&gt; - 154 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/es&#34;&gt;Spain&lt;/a&gt; - 130 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/sv&#34;&gt;El Salvador&lt;/a&gt; - 84 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/za&#34;&gt;South Africa&lt;/a&gt; - 80 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/ke&#34;&gt;Kenya&lt;/a&gt; - 77 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/sk&#34;&gt;Slovakia&lt;/a&gt; - 77 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/de&#34;&gt;Germany&lt;/a&gt; - 66 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/us&#34;&gt;United States of America&lt;/a&gt; - 61 changes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Top 5 countries are well-known bitcoiner hubs, but South Africa and Kenya never showed up in our top trending countries list. Something might be brewing there, but only time will tell.&lt;/p&gt;
&lt;p&gt;Big thanks to &lt;a href=&#34;https://btcmap.org/tagger/7522075&#34;&gt;Rockedf&lt;/a&gt; for contributing to almost every region!&lt;/p&gt;
&lt;h2 id=&#34;trending-communities&#34;&gt;Trending Communities&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/porto-alegre-bitcoin&#34;&gt;Porto Alegre Bitcoin&lt;/a&gt; - 89 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/bitcoin-dada-nairobi&#34;&gt;Bitcoin Dada Nairobi&lt;/a&gt; - 77 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/the-core&#34;&gt;The Core&lt;/a&gt; - 77 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/arnhem-bitcoin-city&#34;&gt;Arnhem Bitcoin City&lt;/a&gt; - 58 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/einundzwanzig-portugal&#34;&gt;Einundzwanzig Portugal&lt;/a&gt; - 56 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/einundzwanzig-schweiz&#34;&gt;Einundzwanzig Schweiz&lt;/a&gt; - 44 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/bitcoin-association-switzerland&#34;&gt;Bitcoin Association Switzerland&lt;/a&gt; - 44 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/free-madeira&#34;&gt;Free Madeira&lt;/a&gt; - 44 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/dezentralschweiz&#34;&gt;Dezentralschweiz&lt;/a&gt; - 44 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/de-bitcoin-meetup&#34;&gt;De Bitcoin Meetup&lt;/a&gt; - 41 changes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Porto Alegre vent from 60% up-to-date to 100% up-to-date, thanks to &lt;a href=&#34;https://btcmap.org/tagger/19288099&#34;&gt;Go BTC&lt;/a&gt; contributions.&lt;/p&gt;
&lt;h2 id=&#34;global-metrics&#34;&gt;Global Metrics&lt;/h2&gt;
&lt;p&gt;The number of verified merchants has increased from 6,747 to 6,935 (+2.8%), reversing previous month-on-month decline. It looks like we&amp;rsquo;re able to keep ~7,000 merchants up-to-date, and we need more local maintainers if we want to bump those numbers.&lt;/p&gt;
&lt;p&gt;The total number of merchants has increased from 11,842 to 12,222 (+3.2%), which is ~x2 our long-term trend. The stream of new merchants is stronger than ever, but we&amp;rsquo;re just struggling to keep some of them up-to-date.&lt;/p&gt;
&lt;p&gt;The average number of days since the last verification has increased from 340 to 344 (+1.2%), which means that our data is slightly less reliable than it was a month ago. This is yet another confirmation that our main bottleneck is the lack of local maintainers.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Things are looking good overall, and I think that we need to focus on the following issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There are many outdated locations, we need more maintainers who can contact those merchants and verify that they are still in business and still accept sats&lt;/li&gt;
&lt;li&gt;Some merchants are just better than others, we need to make the best ones more discoverable. Comments is a good first step but there are many other things we can do to highlight our rockstar merchants!&lt;/li&gt;
&lt;li&gt;Our iOS and Web apps need some love, it would be cool to onboard more devs who can fill the feature gap and fix some known bugs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The best way to help us is to re-verify some outdated locations in your area, if you have any:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://btcmap.org/map?outdated&#34;&gt;https://btcmap.org/map?outdated&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map Monthly Recap - September 2024</title>
            <link>https://bubelov.com/blog/2024/btcmap-sep/</link>
            <pubDate>Tue, 01 Oct 2024 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2024/btcmap-sep/</guid>
            <description>&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#merchant-comments&#34;&gt;Merchant Comments&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#feed-reader-support&#34;&gt;Feed Reader Support&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#rpc-interface&#34;&gt;RPC Interface&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#trending-countries&#34;&gt;Trending Countries&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#trending-communities&#34;&gt;Trending Communities&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#global-metrics&#34;&gt;Global Metrics&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;merchant-comments&#34;&gt;Merchant Comments&lt;/h2&gt;
&lt;p&gt;I extracted about 900 valuable comments from our verification reports and I exposed them via BTC Map sync API. Comments turned out to be extremely valuable since they often add important context to certain Bitcoin merchants. The next steps are client app support and automating new comments.&lt;/p&gt;
&lt;h2 id=&#34;feed-reader-support&#34;&gt;Feed Reader Support&lt;/h2&gt;
&lt;p&gt;Some people are only interested in new places or comments in their areas, so they don&amp;rsquo;t want to install our apps and check them all the time. BTC Map data is open, and we never intended to lock users in, that&amp;rsquo;s why I created a few experimental Atom data feeds. Let&amp;rsquo;s say you want to get notified of new places and comments in the Netherlands, so now you can just add the following feeds to your feed reader of choice:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://api.btcmap.org/feeds/new-places/nl&#34;&gt;https://api.btcmap.org/feeds/new-places/nl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://api.btcmap.org/feeds/new-comments/nl&#34;&gt;https://api.btcmap.org/feeds/new-comments/nl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Of course, you can mix and match any number of BTC Map areas, communities and countries alike. Web feed links are always available on our website, in area activity section.&lt;/p&gt;
&lt;h2 id=&#34;rpc-interface&#34;&gt;RPC Interface&lt;/h2&gt;
&lt;p&gt;Most of our administrative tasks are now centralized, which means that processing new change requests might take a long time, depending on how busy we are. This model can&amp;rsquo;t scale, that&amp;rsquo;s why we&amp;rsquo;re building an admin API, alongside GUI and CLI tools which can be used to simplify access to many local administrative tasks. There is no ETA on that, but I think we&amp;rsquo;ll be able to delegate most tasks to local community managers pretty soon.&lt;/p&gt;
&lt;h2 id=&#34;trending-countries&#34;&gt;Trending Countries&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/nl&#34;&gt;Netherlands&lt;/a&gt; - 190 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/it&#34;&gt;Italy&lt;/a&gt; - 173 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/de&#34;&gt;Germany&lt;/a&gt; - 169 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/es&#34;&gt;Spain&lt;/a&gt; - 101 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/pt&#34;&gt;Portugal&lt;/a&gt; - 98 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/sv&#34;&gt;El Salvador&lt;/a&gt; - 95 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/gb&#34;&gt;United Kingdom&lt;/a&gt; - 83 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/br&#34;&gt;Brazil&lt;/a&gt; - 78 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/ch&#34;&gt;Switzerland&lt;/a&gt; - 77 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/cz&#34;&gt;Czechia&lt;/a&gt; - 74 events and comments&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Many merchants in the Netherlands were re-verified by &lt;a href=&#34;https://www.openstreetmap.org/user/Comino&#34;&gt;Comino&lt;/a&gt;, which shows that a single maintainer can keep the whole country up to date. Having a single maintainer per country would allow us to keep the whole world up to date, so if your country has some old and outdated merchants, we need your help!&lt;/p&gt;
&lt;p&gt;Italian re-verification effort can mostly be attributed to &lt;a href=&#34;https://www.openstreetmap.org/user/mpbin&#34;&gt;mpbin&lt;/a&gt;. This user not only re-verified many existing places but also added some missing general tags such as contact details and so on. Those tags are extremely valuable, so even if your area is up-to-date, you might want to check if you have enough contact details for every merchant. This account apparently belongs to &lt;a href=&#34;https://bitcoinitalianetwork.com/&#34;&gt;Bitcoin Italia Network&lt;/a&gt;, and it looks like they&amp;rsquo;re taking ownership over the whole region.&lt;/p&gt;
&lt;p&gt;Germany&amp;rsquo;s data was enhanced by many different accounts, but 65% of German locations are still outdated, so this country needs more love from local editors. Spain continues to be in a good shape, thanks to &lt;a href=&#34;https://www.openstreetmap.org/user/descubrebitcoin&#34;&gt;descubrebitcoin&lt;/a&gt; efforts, and Portugal data quality continues to improve, thanks to &lt;a href=&#34;https://www.openstreetmap.org/user/Sxajne&#34;&gt;Sxajne&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Big thanks to &lt;a href=&#34;https://btcmap.org/tagger/7522075&#34;&gt;Rockedf&lt;/a&gt; for contributing to almost every region!&lt;/p&gt;
&lt;h2 id=&#34;trending-communities&#34;&gt;Trending Communities&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/satoshi-spritz&#34;&gt;Satoshi Spritz&lt;/a&gt; - 176 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/einundzwanzig-deutschland&#34;&gt;Einundzwanzig Deutschlan&lt;/a&gt; - 169 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/einundzwanzig-portugal&#34;&gt;Einundzwanzig Portugal&lt;/a&gt; - 98 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/einundzwanzig-schweiz&#34;&gt;Einundzwanzig Schweiz&lt;/a&gt; - 78 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/bitcoin-association-switzerland&#34;&gt;Bitcoin Association Switzerland&lt;/a&gt; - 77 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/dezentralschweiz&#34;&gt;Dezentralschweiz&lt;/a&gt; - 77 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/bitcoin-berlin&#34;&gt;Bitcoin Berlin - El Salvador&lt;/a&gt; - 60 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/free-madeira&#34;&gt;Free Madeira&lt;/a&gt; - 51 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/berlin-2140&#34;&gt;Berlin 2140&lt;/a&gt; - 48 events and comments&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/einundzwanzig-berlin&#34;&gt;Einundzwanzig Berlin&lt;/a&gt; - 48 events and comments&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;global-metrics&#34;&gt;Global Metrics&lt;/h2&gt;
&lt;p&gt;The number of verified merchants has dropped from 6,867 to 6,734 (-2%), which means that we&amp;rsquo;re struggling to keep more than 5-7 thousands of places up-to-date, and we need more contributors who can re-verify outdated merchants.&lt;/p&gt;
&lt;p&gt;The total number of merchants has increased from 11,685 to 11,833 (+1.3%), which is in line with our long-term trend. The stream of new merchants has no signs of tapering, we&amp;rsquo;re just struggling to maintain the old ones in certain regions.&lt;/p&gt;
&lt;p&gt;The average number of days since the last verification has increased from 323 to 340 (+5.3%), which means that our data is now significantly less reliable than it was a month ago. This is yet another confirmation that our main bottleneck is the lack of local maintainers.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Our main issue is growing number of outdated locations, and getting more maintainers can take some time. It&amp;rsquo;s not the only way to improve BTC Map though, so we can focus on highlighting the best quality merchants, which I&amp;rsquo;m intending to be busy with during October. I have a few ideas on using different quality signals, and it might make sense to simply mark or hide outdated or unreliable merchants.&lt;/p&gt;
&lt;p&gt;The best way to help us is to re-verify some outdated locations in your area, if you have any:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://btcmap.org/map?outdated&#34;&gt;https://btcmap.org/map?outdated&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map Monthly Recap - August 2024</title>
            <link>https://bubelov.com/blog/2024/btcmap-aug/</link>
            <pubDate>Sun, 01 Sep 2024 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2024/btcmap-aug/</guid>
            <description>&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#merchant-reviews&#34;&gt;Merchant Reviews&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#trending-countries&#34;&gt;Trending Countries&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#trending-communities&#34;&gt;Trending Communities&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#global-metrics&#34;&gt;Global Metrics&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;merchant-reviews&#34;&gt;Merchant Reviews&lt;/h2&gt;
&lt;p&gt;I bet most bitcoiners are aware of the concept of &lt;a href=&#34;https://en.wikipedia.org/wiki/Revealed_preference&#34;&gt;revealed preferences&lt;/a&gt;, and we noticed that many BTC Map users are abusing our merchant verification form and leave place reviews instead of short notes on how they verified a merchant in question.&lt;/p&gt;
&lt;p&gt;Here is a couple of examples:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How did you verify this?&lt;/p&gt;
&lt;p&gt;I went and got my haircut after hearing about the adoption that was happening here in Arnhem. There was the business owner and one of his employees. The employee didn&amp;rsquo;t know that they accepted bitcoin but luckily since the owner was there - he assured him that they do. Mission success for a haircut and a shave.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;How did you verify this?&lt;/p&gt;
&lt;p&gt;The level of customer service of this restaurant is excellent 10/10&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We have hundreds of reviews like the ones above, and it&amp;rsquo;s clear that many bitcoiners want to share their experience and add some context to certain locations. Since those reviews aren&amp;rsquo;t properly organized, it will take some time to extract old reviews from our archives and make them public. As a next step, I think we should add a dedicated review button with a Lightning paywall in order to filter out spam reviews.&lt;/p&gt;
&lt;h2 id=&#34;trending-countries&#34;&gt;Trending Countries&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/br&#34;&gt;Brazil&lt;/a&gt; - 173 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/nl&#34;&gt;Netherlands&lt;/a&gt; - 101 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/it&#34;&gt;Italy&lt;/a&gt; - 84 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/au&#34;&gt;Australia&lt;/a&gt; - 67 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/cz&#34;&gt;Czechia&lt;/a&gt; - 52 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/de&#34;&gt;Germany&lt;/a&gt; - 50 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/pt&#34;&gt;Portugal&lt;/a&gt; - 45 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/sr&#34;&gt;Suriname&lt;/a&gt; - 42 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/us&#34;&gt;United States of America&lt;/a&gt; - 32 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/gb&#34;&gt;United Kingdom&lt;/a&gt; - 27 changes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Brazil is keeping its lead in Bitcoin adoption with 36 new and 121 re-verified places. It has 1,062 Bitcoin merchants in total, and 729 of them have been recently verified.&lt;/p&gt;
&lt;p&gt;Netherlands is one of the first centers of Bitcoin adoption, with a famous &lt;a href=&#34;http://www.arnhembitcoinstad.nl/&#34;&gt;Arnhem Bitcoin City&lt;/a&gt;, which have been boosting Bitcoin adoption since 2014. It looks like August was a busy month in the Netherlands, and now it has 50 more Bitcoin merchants.&lt;/p&gt;
&lt;p&gt;Italy is a big country with many Bitcoin-accepting merchants, but most of them are outdated, so we can&amp;rsquo;t be certain that all the data is reliable. Italian bitcoiners are working on solving this issue, and they were able to re-verify 71 merchant in August.&lt;/p&gt;
&lt;p&gt;Big thanks to &lt;a href=&#34;https://btcmap.org/tagger/7522075&#34;&gt;Rockedf&lt;/a&gt; for contributing to almost every region!&lt;/p&gt;
&lt;h2 id=&#34;trending-communities&#34;&gt;Trending Communities&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/bitcoin-island-philippines&#34;&gt;Bitcoin Island Philippines&lt;/a&gt; - 97 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/satoshi-spritz&#34;&gt;Satoshi Spritz&lt;/a&gt; - 87 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/bitcoin-e-aqui&#34;&gt;Bitcoin é aqui! Rolante/Riozinho-RS-BRASIL&lt;/a&gt; - 81 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/einundzwanzig-deutschland&#34;&gt;Einundzwanzig Deutschland&lt;/a&gt; - 51 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/einundzwanzig-portugal&#34;&gt;Einundzwanzig Portugal&lt;/a&gt; - 45 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/free-madeira&#34;&gt;Free Madeira&lt;/a&gt; - 29 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/einundzwanzig-schweiz&#34;&gt;Einundzwanzig Schweiz&lt;/a&gt; - 21 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/dezentralschweiz&#34;&gt;Dezentralschweiz&lt;/a&gt; - 21 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/bitcoin-association-switzerland&#34;&gt;Bitcoin Association Switzerland&lt;/a&gt; - 21 changes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/community/bitcoin-sydney&#34;&gt;Bitcoin Sydney&lt;/a&gt; - 17 changes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&#34;https://btcmap.org/community/bitcoin-island-philippines&#34;&gt;Bitcoin Island Philippines&lt;/a&gt; has many outdated locations, and most of them no longer accept bitcoins. Removing outdated merchants is very important, thanks &lt;a href=&#34;https://btcmap.org/tagger/7612177&#34;&gt;ctboss&lt;/a&gt; for cleaning this region in August!&lt;/p&gt;
&lt;p&gt;As you can see, we only have 10 communities with 17 or more changes during the last 30 days, which is concerning. We clearly need to find more ways to reach out to unmaintained communities and encourage them to keep their data up to date and onboard more merchants.&lt;/p&gt;
&lt;h2 id=&#34;global-metrics&#34;&gt;Global Metrics&lt;/h2&gt;
&lt;p&gt;The number of verified merchants has dropped from 6,900 to 6,879 (-0.3%), which means that we need more contributors if we want all the regions to stay up-to-date. We&amp;rsquo;re talking about ~20 additional verifications a month, which can be done even by a single dedicated contributor.&lt;/p&gt;
&lt;p&gt;The total number of merchants has increased from 11,532 to 11,687 (+1.3%), which is in line with our long-term trend. The stream of new merchants has no signs of tapering, we&amp;rsquo;re just struggling to maintain the old ones in certain regions.&lt;/p&gt;
&lt;p&gt;The average number of days since the last verification has increased from 309 to 322 (+4.2%), which means that our data is now significantly less reliable than it was a month ago. This is yet another confirmation that our main bottleneck is the lack of local maintainers.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Merchant adoption has no signs of slowing down, and we&amp;rsquo;re working on providing BTC Map users with all the relevant tools to discover and maintain their local Bitcoin merchant data. I believe that collecting and displaying place reviews can help us highlight the best places and give users more confidence in our data set.&lt;/p&gt;
&lt;p&gt;The best way to help us is to re-verify some outdated locations in your area, if you have any:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://btcmap.org/map?outdated&#34;&gt;https://btcmap.org/map?outdated&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map Monthly Recap - July 2024</title>
            <link>https://bubelov.com/blog/2024/btcmap-jul/</link>
            <pubDate>Tue, 13 Aug 2024 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2024/btcmap-jul/</guid>
            <description>&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#events--areas&#34;&gt;Events + Areas&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#trending-countries&#34;&gt;Trending Countries&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#trending-communities&#34;&gt;Trending Communities&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#global-metrics&#34;&gt;Global Metrics&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;p&gt;I didn&amp;rsquo;t post for a while due to an &lt;a href=&#34;https://bubelov.com/blog/2024/russia/&#34;&gt;unexpected trip to Russia&lt;/a&gt;, but now I&amp;rsquo;m back in Phuket and here are my thoughts on BTC Map progress in July.&lt;/p&gt;
&lt;h2 id=&#34;events--areas&#34;&gt;Events + Areas&lt;/h2&gt;
&lt;p&gt;There are a few important events which can happen to a BTC Map merchant, namely:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Creation&lt;/li&gt;
&lt;li&gt;Edit&lt;/li&gt;
&lt;li&gt;Boost&lt;/li&gt;
&lt;li&gt;Deletion&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s the basic lifecycle of any merchant. Unfortunately, it wasn&amp;rsquo;t possible to associate a specific event with a specific BTC Map area, which limited our analytics. I was busy with removing this limitation during the last couple of weeks, and now we can easily rank different areas such as countries and communities by the number of important events. I think it&amp;rsquo;s the best way to find trending areas for a specific time period.&lt;/p&gt;
&lt;p&gt;So, let&amp;rsquo;s use this new capability to see what was trending in July:&lt;/p&gt;
&lt;h2 id=&#34;trending-countries&#34;&gt;Trending Countries&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/it&#34;&gt;Italy&lt;/a&gt; 173&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/br&#34;&gt;Brazil&lt;/a&gt; 73&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/cz&#34;&gt;Czechia&lt;/a&gt; 69&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/de&#34;&gt;Germany&lt;/a&gt; 65&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/at&#34;&gt;Austria&lt;/a&gt; 57&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/gb&#34;&gt;United Kingdom&lt;/a&gt; 51&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/jp&#34;&gt;Japan&lt;/a&gt; 46&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/nl&#34;&gt;Netherlands&lt;/a&gt; 36&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/ge&#34;&gt;Georgia&lt;/a&gt; 34&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://btcmap.org/country/us&#34;&gt;United States of America&lt;/a&gt; 34&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It&amp;rsquo;s nice to see some good progress in Italy, and Brazil is still one of the most active countries on BTC Map. Most edits in Austria were authored by &lt;a href=&#34;https://btcmap.org/tagger/17565129&#34;&gt;descubrebitcoin&lt;/a&gt;, and they seem to be ATMs. There is also a notable re-verification effort by &lt;a href=&#34;https://btcmap.org/tagger/16990757&#34;&gt;Bitcoinshire&lt;/a&gt; in the United Kingdom.&lt;/p&gt;
&lt;p&gt;Most of the new places in Japan belong to &lt;a href=&#34;https://cocorotus.com/map/&#34;&gt;COCOROTUS FOODTRUCK&lt;/a&gt; and I have no idea what it actually is, but they &lt;a href=&#34;https://cocorotus.com/bitln/&#34;&gt;mentioned us&lt;/a&gt; on their website. Georgia is still exceptionally well-maintained, thanks to &lt;a href=&#34;https://btcmap.org/tagger/13256444&#34;&gt;empty_child&lt;/a&gt;, and United States is slowly picking up steam, which is long overdue.&lt;/p&gt;
&lt;p&gt;Big thanks to &lt;a href=&#34;https://btcmap.org/tagger/7522075&#34;&gt;Rockedf&lt;/a&gt; for contributing to almost every region!&lt;/p&gt;
&lt;h2 id=&#34;trending-communities&#34;&gt;Trending Communities&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Satoshi Spritz 176&lt;/li&gt;
&lt;li&gt;Einundzwanzig Deutschland 64&lt;/li&gt;
&lt;li&gt;Bitcoin Austria 57&lt;/li&gt;
&lt;li&gt;Tokyo Citadel 45&lt;/li&gt;
&lt;li&gt;Bitcoin Association Switzerland 33&lt;/li&gt;
&lt;li&gt;Einundzwanzig Schweiz 33&lt;/li&gt;
&lt;li&gt;Dezentralschweiz 33&lt;/li&gt;
&lt;li&gt;Porto Alegre Bitcoin 31&lt;/li&gt;
&lt;li&gt;Einundzwanzig Portugal 30&lt;/li&gt;
&lt;li&gt;Bitcoin Bulgaria 23&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;global-metrics&#34;&gt;Global Metrics&lt;/h2&gt;
&lt;p&gt;The number of verified merchants has dropped from 7,188 to 6,918 (-3.7%), which means that we need more contributors if we want all the regions to stay up-to-date. We&amp;rsquo;re talking about ~300 additional verifications a month, which can be done even by a single dedicated contributor.&lt;/p&gt;
&lt;p&gt;The total number of merchants has increased from 11,215 to 11,521 (+2.8%), which is in line with our long-term trend. The stream of new merchants has no signs of tapering, we&amp;rsquo;re just struggling to maintain the old ones in certain regions.&lt;/p&gt;
&lt;p&gt;The average number of days since the last verification has increased from 288 to 308 (+7%), which means that our data is now significantly less reliable than it was a month ago. This is yet another confirmation that our main bottleneck is the lack of local maintainers.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We were able to improve our analytics, and we have a better understanding of the current trends on BTC Map. While the total number of Bitcoin-accepting merchants keeps growing at a consistent pace, we&amp;rsquo;re struggling with re-verification of our existing merchants, which is supposed to be done at least once a year.&lt;/p&gt;
&lt;p&gt;The best way to help us is to re-verify some outdated locations in your area, if you have any:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://btcmap.org/map?outdated&#34;&gt;https://btcmap.org/map?outdated&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map Weekly Recap</title>
            <link>https://bubelov.com/blog/2024/btcmap-weekly-05-19/</link>
            <pubDate>Sun, 19 May 2024 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2024/btcmap-weekly-05-19/</guid>
            <description>&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#help-needed-delivery&#34;&gt;Help Needed: Delivery&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#key-metrics&#34;&gt;Key Metrics&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#whats-next-kotlin-multiplatform&#34;&gt;What&amp;rsquo;s Next: Kotlin Multiplatform&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;help-needed-delivery&#34;&gt;Help Needed: Delivery&lt;/h2&gt;
&lt;p&gt;Enabling you to spend sats in your local shops is our core mission, but it would be wrong to limit your shopping options while many remote shops offer nationwide and global delivery. The most important thing to understand about BTC Map, is that it&amp;rsquo;s only as good as its data and its community. So, let&amp;rsquo;s take a look at our delivery data:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://overpass-turbo.eu/s/1LH0&#34;&gt;https://overpass-turbo.eu/s/1LH0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are less than 100 places with a &lt;a href=&#34;https://wiki.openstreetmap.org/wiki/Key:delivery&#34;&gt;delivery&lt;/a&gt; tag, most of them being cafes and restaurants, so there is noting to show to BTC Map users yet. I&amp;rsquo;m pretty sure there are thousands of places which can send you all kinds of stuff for sats, we just need to find them and tag them, and we need your help. All you need to do is to add this tag to the places you know, and we&amp;rsquo;ll take care of showing those places in our web and mobile apps.&lt;/p&gt;
&lt;h2 id=&#34;key-metrics&#34;&gt;Key Metrics&lt;/h2&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-19/verified_hu_75d0ae4ee96ab289.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-19/verified_hu_ed0e8df2a6989e45.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The number of verified merchants has dropped by 54, which means we&amp;rsquo;re struggling to support more than ~7,000 up-to-date merchants globally. In order to stay reasonably up-to-date and reliable, a place needs to be re-verified at least once a year, so let&amp;rsquo;s do some simple math.&lt;/p&gt;
&lt;p&gt;How many places do we need to verify daily in order to have 7,000 verified places every year? 7,000 / 365 ~= 20. If the number of verified places is dropping, it means we don&amp;rsquo;t have enough contributors to verify at least 20 places daily, on average. Let&amp;rsquo;s hope that this situation will improve in the near future.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-19/total_hu_6e3a2071d0449e3d.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-19/total_hu_d1b0af619f070a67.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The total number of merchants has increased by 73, which is in line with our long-term trend. The stream of new merchants has no signs of tapering, we&amp;rsquo;re just struggling to maintain the old ones.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-19/days-since-verified_hu_160fa74181a3df0d.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-19/days-since-verified_hu_cd445e4dd835a6b1.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The average number of days since the last verification increased from 268 to 270, which means that our data is now slightly less reliable than it was a week ago. This is yet another confirmation that our main bottleneck is the lack of local maintainers.&lt;/p&gt;
&lt;h2 id=&#34;whats-next-kotlin-multiplatform&#34;&gt;What&amp;rsquo;s Next: Kotlin Multiplatform&lt;/h2&gt;
&lt;p&gt;While BTC Map is available on iOS, our iPhone app lacks many important features and performance updates, and this feature gap will only widen with time. The reason is simple: we don&amp;rsquo;t have any permanent iOS devs, and we can&amp;rsquo;t be certain that this issue will be resolved any time soon.&lt;/p&gt;
&lt;p&gt;Luckily, we have a reasonably up-to-date web app, which works on every platform, but web apps are lacking certain features which are eiter very valuable or absolutely critical to us, namely:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;BTC Map should not require a server, centralization is both risky and expensive&lt;/li&gt;
&lt;li&gt;BTC Map should not require you to trust us, but you can&amp;rsquo;t avoid trusting us if you blindly fetch any HTML and JS which our server sends to your browser tab&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s not even our server, the web app is hosted on Netlify&lt;/li&gt;
&lt;li&gt;We need to minimize and tightly control any network transfers&lt;/li&gt;
&lt;li&gt;We want our code to be easily inspectable and digitally signed by the devs or third-party distributors such as F-Droid&lt;/li&gt;
&lt;li&gt;Native apps are closer to hardware, which leads to better performance, all else being equal, which is especially important on low-end hardware&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are many other reasons to have native apps, but there are also reasons to have a web app:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Not having enough contributors on certain platforms, our iOS situation is the latest example&lt;/li&gt;
&lt;li&gt;Our native apps are aimed at regular users, and they&amp;rsquo;re optimized for small screens. The web app can do that too, but power user / community admin features is where it stands out&lt;/li&gt;
&lt;li&gt;Redundancy is extremely important. It&amp;rsquo;s not too far-fetched to assume that our native apps can be banned by App Store and Google Play, so it&amp;rsquo;s important to have additional options&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We believe that the best way forward is to try merging our Android and iOS code bases as much as possible, which should make it easier to support them and even introduce new platforms such as desktop or PinePhone. &lt;a href=&#34;https://kotlinlang.org/docs/multiplatform.html&#34;&gt;Kotlin Multiplatform&lt;/a&gt; seems like our best bet since our Android code base is in a good shape, and it can be gradually refactored in a platform-agnostic way.&lt;/p&gt;
&lt;p&gt;Unlike many other cross-platform options, Kotlin Multiplatform doesn&amp;rsquo;t force us to sacrifice app performance, and we can keep using native UI components of every target platform in order to have the best look and feel and a responsive UI.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been busy building a multiplatform database layer recently, and I stumbled upon a few issues, but they aren&amp;rsquo;t critical, so we&amp;rsquo;ll continue with this effort, and hopefully we&amp;rsquo;ll be able to have feature parity between all the native platforms in the long run.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map Weekly Recap</title>
            <link>https://bubelov.com/blog/2024/btcmap-weekly-05-12/</link>
            <pubDate>Sun, 12 May 2024 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2024/btcmap-weekly-05-12/</guid>
            <description>&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#api-v3&#34;&gt;API V3&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#key-metrics&#34;&gt;Key Metrics&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#whats-next-delivery&#34;&gt;What&amp;rsquo;s Next: Delivery&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#whats-next-improving-resilience&#34;&gt;What&amp;rsquo;s Next: Improving Resilience&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;api-v3&#34;&gt;API V3&lt;/h2&gt;
&lt;p&gt;BTC Map always had an offline-first architecture, meaning that you don&amp;rsquo;t need an Internet connection in order to see all the bitcoin-accepting merchants in your area or even globally. Our users are the only real owners of their apps and their copies of BTC Map data, they can keep it forever and there is nothing we can do to change that.&lt;/p&gt;
&lt;p&gt;That said, fetching the recent changes and updates is often desirable, as well as downloading new map tiles to cover more regions. BTC Map API is strictly read only, and it&amp;rsquo;s sole purpose is to provide the most recent changes to all the interested users. Keeping all the data locally has its price, and the storage and transfer requirements are growing together with global Bitcoin adoption.&lt;/p&gt;
&lt;p&gt;API V3 is our latest attempt to optimize the size of the data which needs to be transferred in order to keep your data snapshot up to date. My tests are showing 30% reduction in data transfers, so you only need to fetch ~3 KB a day in order to stay up to date. It shouldn&amp;rsquo;t be a big deal even if you&amp;rsquo;re using Tor or a chain of VPN servers.&lt;/p&gt;
&lt;h2 id=&#34;key-metrics&#34;&gt;Key Metrics&lt;/h2&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-12/verified_hu_f6c020e6a05f11e5.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-12/verified_hu_496a65be0a68b99a.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The number of verified merchants has increased by 60, which is a significant improvement both in terms of quality and quantity. Most locations were verified by &lt;a href=&#34;https://twitter.com/RockeBTC&#34;&gt;Rockedf&lt;/a&gt; and the local mappers.&lt;/p&gt;
&lt;p&gt;Here are the top 5 countries by the number of new merchants:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Brazil&lt;/li&gt;
&lt;li&gt;Australia&lt;/li&gt;
&lt;li&gt;South Africa&lt;/li&gt;
&lt;li&gt;Switzerland&lt;/li&gt;
&lt;li&gt;El Salvador&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-12/total_hu_90c66f59eb3d3516.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-12/total_hu_555a4a98a8b7de68.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The total number of merchants has increased by 39, which is slightly below average. The main reason is Argentina data cleanup, it had many outdated merchants so their removal boosted our signal-to-noise ratio in that region.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-12/days-since-verified_hu_4948084d4837dbc0.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-12/days-since-verified_hu_c2d8fb3148c38616.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The average number of days since the last verification decreased from 269 to 267, which serves as another confirmation of our improving data reliability. I expected no change, so I once again underestimated the local mappers.&lt;/p&gt;
&lt;h2 id=&#34;whats-next-delivery&#34;&gt;What&amp;rsquo;s Next: Delivery&lt;/h2&gt;
&lt;p&gt;The problem: many users are living in areas with a low number of local bitcoin-accepting merchants. While this number is growing steadily, life is short, and people want to build circular economies and escape the fiat system ASAP.&lt;/p&gt;
&lt;p&gt;The solution: we need to identify all the merchants who offer either nationwide or global delivery, which would significantly expand the choice of goods and services available to an average BTC Map user. Of course, distance requires trust, and that&amp;rsquo;s one of the reasons we don&amp;rsquo;t support pure services with no physical location. If you made an order, and you aren&amp;rsquo;t happy with the result, it shouldn&amp;rsquo;t be possible for a merchant to avoid any responsibility. Please note that we can&amp;rsquo;t really guarantee that all locations are real, the final judgement call is on you, you should carefully investigate merchants before making remote orders and sending your sats God knows where.&lt;/p&gt;
&lt;h2 id=&#34;whats-next-improving-resilience&#34;&gt;What&amp;rsquo;s Next: Improving Resilience&lt;/h2&gt;
&lt;p&gt;BTC Map client apps are pretty resilient already, but they tend to depend heavily on the following components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tile servers (for rendering maps)&lt;/li&gt;
&lt;li&gt;BTC Map API (for merchant data updates)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In light mode, the app uses OSM tile servers, and we&amp;rsquo;re also hosting Stadia Maps tile server in case you&amp;rsquo;re joined the dark side. It would be cool to give the users more choices, as well as to allow setting their own tile server URLs. We can&amp;rsquo;t embed the tiles into the app, because a full tile set would require terabytes of storage, so the second-best thing is to let the users choose their own tile servers, in case the default options aren&amp;rsquo;t available or aren&amp;rsquo;t desirable for some reason. Some people may even prefer to self-host their own map tiles, self-hosting is not uncommon among hardcore bitcoiners who value their privacy and don&amp;rsquo;t want anyone to know which map regions they viewed.&lt;/p&gt;
&lt;p&gt;Our API is fully open source, so you can also self-host your own instance, if you feel like it. While you can do it by recompiling the app, it&amp;rsquo;s better to let users change their API URL in settings.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map Weekly Recap</title>
            <link>https://bubelov.com/blog/2024/btcmap-weekly-05-05/</link>
            <pubDate>Sun, 05 May 2024 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2024/btcmap-weekly-05-05/</guid>
            <description>&lt;div class=&#34;table-of-contents&#34;&gt;
    &lt;h2&gt;Table of Contents&lt;/h2&gt;
    &lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#new-feature-data-bundling&#34;&gt;New Feature: Data Bundling&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#new-feature-companion-app-warnings&#34;&gt;New Feature: Companion App Warnings&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#new-feature-navigate-to-merchant&#34;&gt;New Feature: Navigate to Merchant&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#new-feature-sharing-merchants&#34;&gt;New Feature: Sharing Merchants&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#key-metrics&#34;&gt;Key Metrics&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#whats-next-syncing-in-adverse-conditions&#34;&gt;What&amp;rsquo;s Next: Syncing in Adverse Conditions&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;/div&gt;
&lt;h2 id=&#34;new-feature-data-bundling&#34;&gt;New Feature: Data Bundling&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s hard not think about building resilient software in the light of the recent events, that&amp;rsquo;s why we decided to include the most recent data snapshots with every new BTC Map release. In short, if our servers go down, for whatever reason, you won&amp;rsquo;t be affected. It&amp;rsquo;s also impossible to censor us via Google Play, since the app is available on F-Droid, GitHub, and it can also be built from the source.&lt;/p&gt;
&lt;p&gt;Data bundling also speeds up the initial sync by an order of magnitude!&lt;/p&gt;
&lt;h2 id=&#34;new-feature-companion-app-warnings&#34;&gt;New Feature: Companion App Warnings&lt;/h2&gt;
&lt;p&gt;You only need a Lightning wallet in order to pay to the vast majority of our merchants, but there are two exceptions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Czech Republic (Querko restaurants)&lt;/li&gt;
&lt;li&gt;South Africa (Pick n Pay supermarkets)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some of the places do require a third party companion app in order to generate BOLT 11 invoices, so you need to install those apps if you want to pay with bitcoins. Usually, we don&amp;rsquo;t tolerate that, but perfect is the enemy of good, and we decided to accept them on the following conditions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The app should generate a real Lightning invoice, payable with any LN wallet of user&amp;rsquo;s choice&lt;/li&gt;
&lt;li&gt;KYC is not acceptable under any circumstances&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those places didn&amp;rsquo;t have proper warnings, so I fixed it in the latest release:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-05/warning_hu_bbb5219f751a743b.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-05/warning_hu_5c9c7325a6dc3431.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&#34;new-feature-navigate-to-merchant&#34;&gt;New Feature: Navigate to Merchant&lt;/h2&gt;
&lt;p&gt;Building routes is hard, that&amp;rsquo;s why we aren&amp;rsquo;t doing it. You need to know a lot of things, including traffic jams, accidents, planned roadworks and so on. I know it well because I used to work for a taxi company which operated in London. Still, many users want to be able to quickly navigate to a selected merchant, so I decided to delegate this task to an external app. Most of the solutions on StackOverflow were dependent on Google Maps, but there was an interesting solution which seems universal. It appears to be working, but we&amp;rsquo;ll need more testing and user feedback to confirm that.&lt;/p&gt;
&lt;h2 id=&#34;new-feature-sharing-merchants&#34;&gt;New Feature: Sharing Merchants&lt;/h2&gt;
&lt;p&gt;I don&amp;rsquo;t know why I waited so long, but it seems to be a must-have feature. As a power user, you don&amp;rsquo;t really miss it, since you can always open a place on OSM and see the nifty-gritty details, but it&amp;rsquo;s not a good way of sharing a bitcoin-accepting place with your friends.&lt;/p&gt;
&lt;h2 id=&#34;key-metrics&#34;&gt;Key Metrics&lt;/h2&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-05/verified_hu_aaf42c61dfc2ea11.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-05/verified_hu_55561e8f7e7abf32.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The number of verified merchants has increased by 41, half of the last week&amp;rsquo;s number. Most locations were verified by &lt;a href=&#34;https://twitter.com/RockeBTC&#34;&gt;Rockedf&lt;/a&gt; and the local mappers.&lt;/p&gt;
&lt;p&gt;Here are the top 5 countries by the number of new merchants:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Brazil&lt;/li&gt;
&lt;li&gt;Spain&lt;/li&gt;
&lt;li&gt;Germany&lt;/li&gt;
&lt;li&gt;Czech Republic&lt;/li&gt;
&lt;li&gt;The Netherlands&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-05/total_hu_75a721a546a45e1d.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-05/total_hu_5d422d52f8dacef9.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The total number of merchants has increased by 8, which is unusually small. The main reason is Boracay data cleanup which was done by a &lt;a href=&#34;https://pouch.ph/&#34;&gt;Pouch&lt;/a&gt; team. They had many outdated merchants so their removal boosted our signal-to-noise ratio in that region.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-05/days-since-verified_hu_8b3ccb6a113d13ba.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-05-05/days-since-verified_hu_cfc80fa90b9e97cc.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The average number of days since the last verification didn&amp;rsquo;t change, which means that our data is as reliable as it was a week ago. I expected a decline since I didn&amp;rsquo;t do any mapping, but it looks like the locals are finally starting to maintain their own data, which reduces our dependency on remote edits done by a few of our team members.&lt;/p&gt;
&lt;h2 id=&#34;whats-next-syncing-in-adverse-conditions&#34;&gt;What&amp;rsquo;s Next: Syncing in Adverse Conditions&lt;/h2&gt;
&lt;p&gt;Next week, I want to focus on our server software and infrastructure. The main goal is to release a v3 API, which is supposed to improve sync speed and lower the bandwidth requirements. Users like snappy software, but the real driving factor is the ability to make our API usable via TOR and other privacy preserving overlay networks. Even a normal VPN can slow down your network connection to the point where every byte counts, so it makes sense to make our API as lightweight as possible.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map Weekly Recap</title>
            <link>https://bubelov.com/blog/2024/btcmap-weekly-04-28/</link>
            <pubDate>Sun, 28 Apr 2024 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2024/btcmap-weekly-04-28/</guid>
            <description>&lt;h2 id=&#34;new-merchant-notifications&#34;&gt;New Merchant Notifications&lt;/h2&gt;
&lt;p&gt;Adding your shop to BTC Map will now notify all the users within a 100 km radius, so they&amp;rsquo;ll be able to discover your shop in no time. As a user, don&amp;rsquo;t forget to send us your feedback when you visit new places, it&amp;rsquo;s very important to us, and we often boost the most trusted and popular places for free, so your feedback is a good way to support BTC Map merchants. We also have a few shady and unreliable places, but we can&amp;rsquo;t remove them unless we have a report from a local user, so both positive and negative user feedback regarding our locations is the best way to support BTC Map and help your fellow bitcoiners.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-28/new-merchants_hu_9a6a9316892d7e6c.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-28/new-merchants_hu_b89e57bb3fc8d9be.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&#34;legacy-data-is-no-more&#34;&gt;Legacy Data Is No More&lt;/h2&gt;
&lt;p&gt;This week concludes the end of my ancient data verification push. My goal was to re-verify all the places which were added before the latest BTC Map restart (September 2022).&lt;/p&gt;
&lt;p&gt;Some users might not know that, but BTC Map existed since 2015, and it even featured a bunch of shitcoins. I stumbled upon coinmap.org back in 2015, and I really liked the idea. I think coinmap was made during some hackathon in Eastern Europe, so it was probably done in a rush, and then it was quickly abandoned. I did some basic reverse engineering and I figured out that coinmap just fetched the data from OSM, and then it got out of sync and started to rot. Lesson learned, it&amp;rsquo;s better not to fork OSM datasets, unless you want to maintain the whole world by yourself.&lt;/p&gt;
&lt;p&gt;Taking an &amp;ldquo;add whatever you want, I don&amp;rsquo;t care&amp;rdquo; stance on shitcoins was a mistake, and onchain Bitcoin transactions didn&amp;rsquo;t really fit the retail use cases, so the project was quickly abandoned, and it was also too boring to do that alone. I regained my interest in promoting Bitcoin as a medium of exchange in spring 2022, after some experimentation with the Lightning Network. This time it wasn&amp;rsquo;t just an Android app, there are many other components which are created and maintained by other bitcoiners from different parts of the world. Hopefully, I&amp;rsquo;ll be able to gradually disappear and focus on the other, more technical bottlenecks in Bitcoin infra, but I feel like our core team is still too small and fragile to do that safely, so I&amp;rsquo;m not going anywhere unless I&amp;rsquo;m confident that the project won&amp;rsquo;t fade away after losing a couple of active contributors.&lt;/p&gt;
&lt;h2 id=&#34;key-metrics&#34;&gt;Key Metrics&lt;/h2&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-28/verified_hu_76318108452ad0d9.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-28/verified_hu_7d3b2e62f31b0233.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The number of verified merchants has increased by 81, which is about the same as last week. Most locations were verified by &lt;a href=&#34;https://twitter.com/RockeBTC&#34;&gt;Rockedf&lt;/a&gt; and me, but we also had a significant number of verifications made by the locals.&lt;/p&gt;
&lt;p&gt;Here are the top 5 countries by the number of new merchants:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Italy&lt;/li&gt;
&lt;li&gt;Brazil&lt;/li&gt;
&lt;li&gt;United Kingdom&lt;/li&gt;
&lt;li&gt;Germany&lt;/li&gt;
&lt;li&gt;France&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-28/total_hu_edd81e52e1533a37.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-28/total_hu_13e63b8eeb277e64.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The total number of merchants has increased by 66, which is a healthy trend.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-28/days-since-verified_hu_ee6c53902dda02c3.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-28/days-since-verified_hu_6f9daa41646df790.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The average number of days since the last verification dropped from 271 to 268, which means that our data is slightly more reliable now. This is a global average, and regional data reliability can vary. You can always find your community or a country in order to check the local trends.&lt;/p&gt;
&lt;h2 id=&#34;whats-next-decentralized-data-ownership&#34;&gt;What&amp;rsquo;s Next: Decentralized Data Ownership&lt;/h2&gt;
&lt;p&gt;I believe we built enough tools to enable locals to take control of their regions. From now on, I will limit my global edits and focus on maintaining Thai merchants since I&amp;rsquo;ve been living here for 10 years, and it&amp;rsquo;s my current country of residence. Thai data is in a good shape already, but I want to learn more about all the merchants and there are many other useful tags except &lt;code&gt;currency:XBT&lt;/code&gt; which need to be surveyed.&lt;/p&gt;
&lt;p&gt;Since we still don&amp;rsquo;t have enough editors, I expect many regions to disappear from the map in the long run, and I don&amp;rsquo;t really see it as a problem. We gave them everything to kickstart their regions and get a feel of the future, now it&amp;rsquo;s up to them.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The future is already here – it&amp;rsquo;s just not evenly distributed. ― William Gibson&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map Weekly Recap</title>
            <link>https://bubelov.com/blog/2024/btcmap-weekly-04-21/</link>
            <pubDate>Sun, 21 Apr 2024 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2024/btcmap-weekly-04-21/</guid>
            <description>&lt;p&gt;Data quality remains the main bottleneck, followed by the discoverability of the new merchants.&lt;/p&gt;
&lt;h2 id=&#34;key-metrics&#34;&gt;Key Metrics&lt;/h2&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-21/verified_hu_e895ec2e0ecbc94a.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-21/verified_hu_fd97ef98b89ada1d.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;We added 93 verified merchants, which is about the same as last week. Most locations were verified by &lt;a href=&#34;https://twitter.com/RockeBTC&#34;&gt;Rockedf&lt;/a&gt; and me, but we also had a significant number of verifications made by the locals.&lt;/p&gt;
&lt;p&gt;Most of the new places are located in Brazil, Italy and Germany.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-21/total_hu_a1f0f668070a5aa0.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-21/total_hu_f0767dae7804c11c.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The total number of merchants dropped by 112, mostly due to my re-verification of extremely outdated merchants. It certainly boosted our signal-to-noise ratio.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-21/days-since-verified_hu_f782e5b1cc9e0dc5.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-21/days-since-verified_hu_cde3ef60875e13ed.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The average number of days since the last verification dropped from 307 to 272, which is a very significant improvement. In the long run, this metric will become our key data health indicator, but we need to deal with the remaining outliers first.&lt;/p&gt;
&lt;h2 id=&#34;extreme-outliers&#34;&gt;Extreme Outliers&lt;/h2&gt;
&lt;p&gt;We still have some ancient places, and it&amp;rsquo;s our biggest problem. The date of the oldest verification was December 2017 in the end of last week, and now it&amp;rsquo;s April 2021.&lt;/p&gt;
&lt;h2 id=&#34;android-app-background-sync&#34;&gt;Android App: Background Sync&lt;/h2&gt;
&lt;p&gt;Background sync is working reliably, and it will be included in the next Android app release. I hope the Web and iOS clients will follow. The app should always show you the latest data as fast as possible, no matter how long you were absent.&lt;/p&gt;
&lt;h2 id=&#34;whats-next-local-activity-notifications&#34;&gt;What&amp;rsquo;s Next: Local Activity Notifications&lt;/h2&gt;
&lt;p&gt;BTC Map doesn&amp;rsquo;t have any tracking capabilities, which is extremely rare for a modern app. We don&amp;rsquo;t know how many users we have, and we know nothing about our users. Our server is read-only, which means that we can send you new data if you ask us for it, but we never send any data back to the server.&lt;/p&gt;
&lt;p&gt;Most notifications are initiated by the server, but we can&amp;rsquo;t do it, since we aren&amp;rsquo;t using Google or Apple notification infrastructure, and we don&amp;rsquo;t even know where to send those notifications, because the recipient address is user data, and we don&amp;rsquo;t store user data.&lt;/p&gt;
&lt;p&gt;It is also possible to send a notification from the local app itself, so, while we don&amp;rsquo;t have your private data, the app on your phone can have it and can use it to notify you. If you granted BTC Map your GPS location access, it doesn&amp;rsquo;t mean our servers have it. In fact, your location will never leave your device, and you can verify it yourself by examining the source code. Since the app can know your location, it can notify you of new merchants nearby, if it finds them during the background sync. That&amp;rsquo;s what I&amp;rsquo;ll focus on next week.&lt;/p&gt;
</description>
        </item>
        
        <item>
            <title>BTC Map Weekly Recap</title>
            <link>https://bubelov.com/blog/2024/btcmap-weekly-04-14/</link>
            <pubDate>Sun, 14 Apr 2024 00:00:00 +0000</pubDate>
            <guid>https://bubelov.com/blog/2024/btcmap-weekly-04-14/</guid>
            <description>&lt;p&gt;I&amp;rsquo;m not a big fan of mapping, but some things just need to be done. Once we attract more local editors, I&amp;rsquo;ll be able to focus on a more technical stuff, but data quality is the main bottleneck at the moment.&lt;/p&gt;
&lt;h2 id=&#34;key-metrics&#34;&gt;Key Metrics&lt;/h2&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-14/verified_hu_ff9e8048ee6f5cda.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-14/verified_hu_a9dfc45dc0fb9473.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;We added 102 verified merchants, which is two times more than we added during the last week.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-14/total_hu_72782f7ed9eccd8.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-14/total_hu_b182ad2c5ed75205.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The total number of merchants dropped by 64, mostly due to my re-verification of extremely outdated merchants. It certainly boosted our signal-to-noise ratio.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    
        
        
        
            
            
            
            &lt;a href=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-14/days-since-verified_hu_519988885038a4b8.webp&#34;&gt;
                &lt;img src=&#34;https://bubelov.com/blog/2024/btcmap-weekly-04-14/days-since-verified_hu_29a861db78a3cceb.webp&#34; alt=&#34;&#34; /&gt;
            &lt;/a&gt;
        
    
    
    
&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;The average number of days since the last verification dropped from 354 to 315, which is a very significant improvement. In the long run, this metric will become our key data health indicator, but we need to deal with the remaining outliers first.&lt;/p&gt;
&lt;h2 id=&#34;extreme-outliers&#34;&gt;Extreme Outliers&lt;/h2&gt;
&lt;p&gt;We still have some ancient places, and it&amp;rsquo;s our biggest problem. The date of the oldest verification was April 2015 in the end of last week, and now it&amp;rsquo;s December 2017.&lt;/p&gt;
&lt;h2 id=&#34;outdated-merchants&#34;&gt;Outdated Merchants&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s a really nice feature introduced by secondl1ght:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://btcmap.org/map?outdated&#34;&gt;https://btcmap.org/map?outdated&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Opening this link allows you to see all the outdated merchants around you. It&amp;rsquo;s very handy for anyone who wants to verify their local merchants. We are trying to make it as easy as possible for people to take ownership of their local data.&lt;/p&gt;
&lt;h2 id=&#34;in-progress-background-sync&#34;&gt;In Progress: Background Sync&lt;/h2&gt;
&lt;p&gt;Every time you open BTC Map, it needs to download all the changes since your last visit. The overall sync performance depends on how long you were absent, and the quality of your Internet connection. That&amp;rsquo;s not really a big deal, but it doesn&amp;rsquo;t allow us to interact with the users asynchronously. Let&amp;rsquo;s say someone added a new bar in my area, but I won&amp;rsquo;t know about that until I open BTC Map again. Having a background sync would make sure that I will be able to see all the new places immediately after opening the app, but it also clears the patch to asynchronous notifications.&lt;/p&gt;
&lt;h2 id=&#34;in-progress-local-activity-notifications&#34;&gt;In Progress: Local Activity Notifications&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;ll start with notifying the users of any new bitcoin-accepting merchants nearby, but it&amp;rsquo;s just the beginning. We want to decentralize map editing, which means that the locals should be in charge of their data. For instance, we can create an opt-in notification channel which will notify local maintainers of any new issues with their data. It would also allow them to remove all the spam and scam promptly.&lt;/p&gt;
&lt;p&gt;We can also make boosts more appealing by notifying the users of newly boosted places. Boosts aren&amp;rsquo;t really a significant source of money for BTC Map, but they also act as a proof that a merchant is serious about accepting bitcoins and that it has a functional Lightning wallet.&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>