Geo-Harbor

Documentation

Technical description of how Geo-Harbor works — architecture, GPS logic, data flow and API. For those who want to understand the app in depth before trying it.

Architecture & tech stack

The app consists of an Android client written in Flutter/Dart and a backend server written in Node.js with TypeScript. The client communicates with the server via both REST (HTTP) and WebSocket. REST is used for one-time operations like creating a group, adding a marker or fetching history. WebSocket is used for the real-time data stream — positions, alarms and group notifications.

All positions are stored in a SQLite database with a device-centric schema: each GPS point is saved once per device and timestamp regardless of how many groups the user belongs to. A join table (location_visibility) determines which group members see which points. Markers, groups and email verification are stored in separate tables.

Flutter / DartAndroid client app
Node.js + TypeScriptREST API + WebSocket server
WebSocket (ws)Real-time communication
SQLiteLocal database on server
OpenStreetMapMap display (flutter_map)
Yr.no / MET NorwayWeather data (yr.no, CC BY 4.0)

GPS modes

⚡ Standard Mode (Balanced & Smart)

Standard Mode combines GPS, Wi-Fi, and cell towers (PRIORITY_BALANCED_POWER_ACCURACY) for low battery consumption. Position updates every 60 seconds on movement exceeding 30 meters. If the app detects you are driving (via Android activity recognition), it automatically switches to vehicle priority, updating every 15 seconds on movement exceeding 50 meters. The GPS stream is automatically paused when stationary. This mode is recommended for most situations.

⚡⚡ Exact Mode (High Accuracy)

Exact Mode utilizes pure GPS with maximum priority (PRIORITY_HIGH_ACCURACY). Position updates every 5 seconds on movement exceeding 5 meters to draw a highly precise track on the map. This mode consumes significantly more battery power and is best suited for shorter periods where absolute precision is necessary.

Real-time communication via WebSocket

The client connects to the server via WebSocket on login and keeps the connection open in the background (using a background service). Each position update is sent as a JSON message and forwarded immediately to all other connected group members. Latency is typically under 100 ms within Europe.

WebSocket messages include: position updates (lat/lng, heading, speed, activity type), marker events (new/updated/deleted/moved), alarm signals (triggered/resolved), group events (approved, removed, ownership transfer). If the connection drops, the app automatically tries to reconnect every five seconds.

Groups and permissions

A group is created with a random 6-character invite code. The creator automatically becomes the owner. The owner can: approve or decline requests, remove members, invite via email link, transfer ownership and change the group code. Regular members can see all approved group members and their positions, add markers and trigger alarms.

A user can be in multiple groups simultaneously and switch active group from the menu. Each group has a separate WebSocket channel and position data is kept isolated per group. Email verification is required when joining a group to prevent abuse.

Data and privacy

All data is stored on the server geo-harbor.se. No data is shared with third parties. Position history is stored with the device's device ID linked to the group membership — there is no global user account. If you uninstall and reinstall the app, you can recover your membership via email.

Markers with associated photos are stored on the server for as long as the group exists. Photos are accessed via authenticated URLs and are not visible to outsiders. If you leave a group your membership is removed, but markers you created retain your nickname as creator.

Property boundaries and GPX import

The app supports importing property boundaries and land areas as a GPX file — a feature especially useful for hunting parties who need to track which land they have access to. The boundary is drawn on the map and shared directly with everyone in the group via WebSocket. All group members see the same boundary in real time without having to import the file individually.

The GPX parser supports three point formats: track points (trkpt), route points (rtept) and waypoints (wpt). The file must contain at least 3 points. GPX files with land boundaries can be exported from e.g. the Swedish land registry map service, hunting map apps or other mapping tools. It is also possible to draw the boundary manually directly on the map point by point and save it in the same way.

API overview

The server exposes a REST API under /api/groups/. All calls require a valid groupId and memberId.

Groups

Position & history

Markers

Alarm & other