No Backend, By Design
map.ping has zero servers. Everything - import, storage, scanning, and notifications -
happens on the device. That is the architecture: the privacy guarantee and the operating cost ($0) both
fall out of the same decision. The only network calls the app ever makes are an optional fetch of a
public Google My Map's KML and, for Pro users, an OAuth round-trip to read their own Drive
maps.
map.ping/
├── src/
│ ├── background/ # Engine: geolocation.ts, scanRunner.ts,
│ │ # headlessTask.ts, BackgroundScanController.tsx
│ ├── import/ # kmlParse.ts (pure), kmlImport.ts (file/URL/Drive IO)
│ ├── utils/ # backgroundTaskLogic.ts (gates), geo, proximity,
│ │ # scanLogic, quietHours, notificationSetup, secureStorage
│ ├── storage/ # mapStore.ts — AsyncStorage CRUD + snooze
│ ├── context/ # DataContext, SettingsContext (local state)
│ ├── monetization/ # RevenueCat entitlements (Free / Pro)
│ ├── screens/ # Maps, MapView, ImportMap, Settings, Paywall, Onboarding
│ ├── components/ # MapCard, ErrorBoundary, Toast, modals
│ ├── share/ # iOS Share Extension sheet
│ └── i18n/ # en / he / fr / ru / ar (strict-typed)
├── index.ts # registers the Android headless task
├── index.share.js # Share Extension entry
└── app.config.js # dev/prod variants, plugins, privacy manifest
On-Device Data Flow
Map Sources
📄 .kml / .kmz File
🔗 Public My Maps Link
☁️ Google Drive (Pro)
📲 iOS Share Extension
▼
Import Pipeline (on-device)
🧩 KML / KMZ Parser
fflate + fast-xml-parser
▼
Local Storage
🗂️ AsyncStorage
maps + pins
🔐 SecureStore
background_maps bridge
▼
Background Proximity Engine
🛰️ bg-geolocation
motion-aware GPS
🔁 scanRunner
per-fix scan
🚦 Gate Pipeline
▼
Output
🔔 Local Notification
deep-links to the pin
Two JS contexts, one engine. The same runScan() executes from the foreground
onLocation handler and from the Android headless task (which runs with the app
killed, in a separate JS VM). Because the headless context has no React state, the scanner reads pins and
settings straight from storage - which is why a SecureStore background_maps bridge exists.