Skip to content

Repository files navigation

🧭 Compass — Marker Edition

A posture-driven, zero-UI spatial compass. Set an anchor for home or your car, text a link into a group chat, and everyone who joins sees each other on the same dial — built for places like a crowded concert where the point-and-walk matters more than a map.

Built with Flutter, Material 3, and iOS-26 liquid-glass surfaces. iOS + Android.

The idea in one screen

The whole app is one continuous canvas that morphs by how you hold the phone (the "posture", derived live from the accelerometer):

Posture Pitch What you see
Flat 0–30° True-OLED-black dial. Markers ride a hairline rim at their real-world bearing; the blank center shows distance to the nearest one. Double-tap center to drop an anchor.
Tilt → AR 30–60° The dial cross-fades into a live camera window as you raise the phone.
AR 60–90° Camera passthrough; markers become glowing eye-level orbs (people) or sky-beams (anchors) with billboard distance tags.
Pocket screen-off guide The haptic engine is the interface — a 60→140 BPM heartbeat means on-course and closing in; a single cold click means wrong way.

Three marker types

  • Social — a friend in a shared session (neon cyan / magenta / lime dot + initials).
  • Anchor — a personal waypoint you drop (pure-white dot; 🏠 home, 🚗 car…). Persisted on-device, fully offline.
  • Lagging — derived: when a friend falls beyond 1.5× the group's median spread, their dot turns red and pins to 6 o'clock with a distance chip and an alert banner.

Why "no network" only goes so far

The compass, the distance/bearing math, and your anchors are 100% on-device and offline — GPS tells your phone where it is, and that's all the solo experience needs.

But "everyone sees each other" is different: for your phone to draw a friend's dot, their coordinates have to physically travel to you. GPS can't do that — it only ever reports your own position. So the sharing half needs some transport. The good news is a coordinate is ~16 bytes, so even a congested concert network carries it fine; this isn't a bandwidth problem.

That transport is fully implemented using a custom Node.js Socket.io backend. Most importantly, it features military-grade End-to-End Encryption (E2EE).

🔒 Zero-Knowledge Architecture (E2EE)

When a session is created, the Host generates a 256-bit AES GroupKey. When Guests join, they perform an Elliptic-Curve Diffie-Hellman (X25519) handshake to securely receive the GroupKey. Every location update (lat, lng) is encrypted using AES-GCM before leaving the device.

The backend routing server cannot read your location data, making this safe for open-source self-hosting and deployment on untrusted servers.

Open Source Ready

This repository comes fully equipped for open-source contribution and deployment:

  • CI/CD Built-In: GitHub Actions automatically run flutter analyze and flutter test on every PR.
  • Automated Releases: Pushing a new version tag automatically compiles the Android APK and creates a GitHub Release.

Architecture

lib/
  models/        geo math (haversine/bearing), markers, postures, sessions
  services/      location · heading · motion · haptics · anchors(persist)
                 session_service(⇐ the transport seam) · deep_links
  state/         compass_controller — fuses every stream into ResolvedMarkers
  theme/         Material 3 dark theme + liquid-glass surfaces
  ui/            root_shell (posture morph) · dial · ar · pocket · sheets
  • State: a single CompassController (ChangeNotifier + provider) is the only thing the UI reads. It fuses location + heading + motion, owns anchors and the active session, and resolves everything to ResolvedMarkers for the painters.
  • Sensors: geolocator (position), flutter_compass (heading), sensors_plus (pitch → posture), vibration (haptic patterns).
  • Deep links: app_links handles compass://ping?token=… (1-to-1 "find me") and compass://join?session=… (group), registered on both platforms.

Running the Backend

The signaling server requires Node.js.

cd backend
npm install
npm start

The server runs on port 8080 by default.

Running the App

flutter pub get
# Inject your backend URL at compile time
flutter run --dart-define=COMPASS_API_URL=http://localhost:8080
flutter test         # geo + posture unit tests
flutter analyze

Deep-link test: adb shell am start -a android.intent.action.VIEW -d "compass://join?session=DEMO42" (Android) xcrun simctl openurl booted "compass://ping?token=xyz&name=AK" (iOS sim)

About

modern compass

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages