Edge · LoRa · offline-first
A water-sports centre that sees every student on the water, even without internet
LoRa GPS trackers, an edge server on the beach, safety zones with alarms and a full booking system with OTA channels. Safety runs locally; the cloud helps when there is a link.
- Status
- Deployed: a base on Mykonos and a demo in Poland
- Period
- April – October 2026
- LoRa range over water measured in a field test, straight to the gateway
- 2,5 kmLoRa range over water measured in a field test, straight to the gateway
- with a solar repeater on the roof: design range, line of sight over water
- up to 8 kmwith a solar repeater on the roof: design range, line of sight over water
- open ports: internet access only through Cloudflare Tunnel
- 0open ports: internet access only through Cloudflare Tunnel
- FastAPI endpoints
- 198FastAPI endpoints
The problem
A beach has no reliable internet, yet the instructor has to know where every student is: who drifted too far, who hasn't moved for fifteen minutes, whose kit is coming back. On top of that come bookings, waivers, rentals and OTA channels, all of which usually live in a spreadsheet and three apps.
What I built
- Meshtastic GPS trackers (SenseCAP T1000-E) send positions over 868 MHz LoRa to a WIO L1 Pro gateway next to the server. A solar repeater extends the range.
- A NucBox (mini PC) on the beach: FastAPI, PostgreSQL, InfluxDB, nginx, its own DNS and DHCP on the LAN, HTTPS with a Let's Encrypt certificate. Tablets run the PWA without internet too, with an offline map.
- Geofencing in the packet receiver: leaving the safe zone or entering a no-go zone raises the same alarm as SOS. Zones are drawn in a map editor, per skill level.
- Water sessions with timer, pause and automatic splitting. A tracker belongs to a session, not to a customer. Rentals with a QR scanner and label printing on a Niimbot printer over Bluetooth, straight from the browser.
- Multi-tenant cloud panel: Google calendars, Stripe, Bókun (Viator and other OTAs: push, availability, webhooks), waivers with eIDAS e-signature via firma.dev and offline signing.
- An “Ask AI” agent in the owner's panel reads sessions, kit and telemetry, answers by voice (ElevenLabs) and reports on the mesh. A demo factory builds a booking site for a new school from its URL alone.
Architecture
The interesting part is underneath
Pick a flow to see data move through the system. Click any part for details.
← swipe the diagram →
Flows
The alarm reaches the instructor without the internet.
Click a part of the diagram for details.
- hardware
- edge / network
- service
- data
- AI
- third party
- people / apps
- radio
- tunnel
- HTTPS
- local
- event
Every element, described
- T1000-E · GPS tracker + SOS
- A Meshtastic tracker on the student's arm. Sends a position every 30 s (shorter intervals clogged the channel and lost telemetry) and has an SOS button. The whole fleet is configured by one script, about a minute per tracker.
- Solar P1-Pro · solar repeater
- A SenseCAP Solar repeater on a mast. Monitored: no signal for 3 h shows as a fault in the “Mesh health” panel.
- WIO L1 Pro · LoRa gateway → USB
- A gateway permanently plugged into the NucBox over USB. In a field test it received trackers 2.5 km away over water, with zero mesh hops. With a SenseCAP P1-Pro solar repeater on the roof (5.8 dBi antenna, self-powered) the design range grows to 3–8 km line of sight.
- receive.py · receiver + geofence
- A separate systemd service. Decodes packets, matches nodes to trackers in the database, checks every position with point-in-polygon against the zones and raises events: SOS, zone breach, GPS silence.
- InfluxDB · telemetry and tracks
- Time series of positions and telemetry. Session history and analytics are built from it.
- FastAPI · sessions, kit, alarms
- The core: customers, sessions, rentals, zones, events. Base configuration (brand, currency, map) comes from one file, so the same install serves Mykonos, Hel or a demo.
- PostgreSQL · operational data
- Customers, sessions, kit (79 items in a season), bookings synced from the cloud. Backups from a timer.
- nginx · dnsmasq · LAN, HTTPS, DNS
- The beach router hands out addresses and dnsmasq points the domain at the NucBox, so tablets open the same domain with a valid certificate even with no internet.
- Live · CMS · PWA on a tablet
- Live map with zones, alarms, registration, a customer card with QR, check-in. Installed as a PWA, with an offline map downloaded by one button.
- Niimbot B1 · QR labels (BLE)
- A label printer driven from the browser over Web Bluetooth: kit labels and customer cards, in bulk too.
- Cloudflare Tunnel · outbound, no open ports
- The NucBox dials out to Cloudflare, so the beach router has no port forwarding and no open ports. The admin panel sits behind Cloudflare Access.
- book. · panel. · Droplet, multi-tenant
- Online booking and the owner's panel, multi-tenant. Bookings sync to the NucBox when there is a link; the beach never waits for the cloud.
- Stripe · payments
- Deposit or full payment at booking. Plan: Stripe Connect Express, so each school connects its own account in 5 minutes.
- Bókun · OTA, Viator
- OAuth and REST v2 integration: pushing products, prices, availability, photos and the booking webhook.
- firma.dev · eIDAS waivers
- Waivers signed electronically before going on the water, with an offline version on the tablet.
- Claude · Ask AI agent
- An agent with read-only tools: sessions, kit, telemetry, mesh health. It has a cost budget and shows anything that needs approval for confirmation.
- ElevenLabs · voice
- Agent answers and “read the situation” on the map, spoken aloud. Fixed phrases are cached on the NucBox, so they play offline too.
- Agent fleet · oversight (plan)
- Design: a cheap model watches 20+ sites continuously, a stronger one steps in on anomalies, and fixes arrive as PRs for approval.
Decisions that make the difference
Safety does not depend on the cloud
The whole tracker → alarm path runs on the LAN. The cloud provides bookings and the agent, but its failure never switches off SOS.
A tracker belongs to a session, not a customer
One tracker passes through many students a day. Binding it to a session keeps history correct and avoids mix-ups at hand-out.
Air-time capacity is physics, not config
Meshtastic channels don't add capacity. Scaling means separate frequencies on several gateways, and beyond that TDMA timed by GPS on custom firmware.
One codebase, many sites
Brand, currency, map and contact live in config. A demo for a new school is scraped from its website in minutes.
How it works
Four apps, one system
Most centres juggle a booking tool, a spreadsheet, paper waivers and a WhatsApp group. SurfCenter replaces all of it with four connected apps and one source of truth.
CMS: check-in for rentals and lessons, customer cards, QR equipment and analytics.




Every client on the water on one GPS map. Works on the beach, offline, on any tablet.




book.: 24/7 booking of lessons, courses and rentals, under the school's brand.



Panel: hours, team, catalogue and the OTA channel manager. One closure blocks the site and every channel.




Data on the screens is fictional.
Stack
Service lines
Got a process that should run itself?
30 minutes, free. I'll tell you if it makes sense, how I'd build it and what it would cost to run.