north-star / files / readme.md
readme.md
e790982a 2026-03-16 Pavel Safronov | 1 | # Friend Compass |
fb3b6f32 2026-03-14 Pavel Safronov | 2 | |
e70d53bd 2026-03-15 Pavel Safronov | 3 | ## What is it? |
| 4 | ||
a3080daf 2026-03-17 Pavel Safronov | 5 | Friend Compass is a web application that lets users share location in |
| 6 | real-time with others. It provides a simple interface to see where everyone | |
| 7 | is relative to themselves, and does not require any accounts or | |
| 8 | authentication. Just share the room link or QR code, and everyone can join | |
| 9 | and see each other's location on a map. | |
| 10 | ||
| 11 | ## Features | |
| 12 | ||
| 13 | - Real-time location sharing with multiple friends | |
| 14 | - No authentication required, just share the room link or QR code to join | |
| 15 | - No app to install, works on mobile browsers with geolocation support | |
| 16 | - Relative location markers on a map showing direction and distance to each | |
| 17 | friend | |
| 18 | - Customizable markers with names and colors | |
| 19 | - A special "North" marker that always points north and can be used to | |
| 20 | calibrate the app for better accuracy | |
| 21 | - Works on iOS and Android devices with modern browsers (Safari, Chrome, | |
| 22 | etc.) | |
| 23 | - Privacy-focused design with encrypted location data and no personally | |
| 24 | identifiable information stored in the database | |
| 25 | - Open source and free to use for anyone with a compatible device and | |
| 26 | internet connection | |
| 27 | ||
| 28 | > FYI: The app is free to use, but hosting is not always free. It relies on | |
| 29 | > Firebase Realtime Database, which has a generous free tier but may incur | |
| 30 | > costs if usage exceeds those limits. | |
| 31 | ||
| 32 | ## Requirements | |
| 33 | ||
| 34 | - A smartphone with a modern browser that supports geolocation (for example, | |
| 35 | Safari on iOS or Chrome on Android) | |
| 36 | - An internet connection to sync location data in real-time | |
| 37 | - Location permissions granted to the browser for the app to access your | |
| 38 | location | |
| 39 | - Camera to scan QR codes (optional, but helps users join rooms faster) | |
| 40 | - For best results, use the app outdoors or in areas with good GPS signal, | |
| 41 | since indoor locations may have reduced accuracy | |
e70d53bd 2026-03-15 Pavel Safronov | 42 | |
| 43 | ## How to use it? | |
| 44 | ||
a3080daf 2026-03-17 Pavel Safronov | 45 | 1. Open [Friend Compass][app-link]. |
| 46 | 2. Share the room QR code or room link with your friends so they can join the | |
| 47 | same "room". | |
| 48 | 3. Everyone who joins the room can see each other's relative location as an arrow. | |
fb27ecb3 2026-03-15 Pavel Safronov | 49 | 4. Everyone can set a custom name and color for their marker. |
a3080daf 2026-03-17 Pavel Safronov | 50 | 5. You can hide or reorder friends. |
| 51 | 6. The North participant is a special marker that always points north. | |
| 52 | 7. If North is not pointing to true north, orient your phone so "up" on the | |
| 53 | screen faces north, then click "Calibrate North". This sets the current | |
| 54 | orientation as north. | |
| 55 | 8. A misaligned north is only a visual issue and does not affect actual | |
| 56 | location sharing. | |
e70d53bd 2026-03-15 Pavel Safronov | 57 | |
| 58 | ## How does it work? | |
| 59 | ||
a3080daf 2026-03-17 Pavel Safronov | 60 | The app uses Firebase Realtime Database to store and sync location data of all |
| 61 | friends in real-time. When a user joins a room, they are added to the database | |
| 62 | with location and profile info. The app listens for database changes and | |
| 63 | updates the map accordingly. | |
e70d53bd 2026-03-15 Pavel Safronov | 64 | |
ec059e03 2026-03-15 Pavel Safronov | 65 | ## Is it secure? |
| 66 | ||
a3080daf 2026-03-17 Pavel Safronov | 67 | The app does not require authentication, so anyone with the room information |
| 68 | can join and see locations of all their friends. | |
ec059e03 2026-03-15 Pavel Safronov | 69 | |
a3080daf 2026-03-17 Pavel Safronov | 70 | The room link/QR code contains a unique room id and encryption key. Even if |
| 71 | someone gained database access (including myself), they could not read | |
| 72 | location data without the room link. | |
ec059e03 2026-03-15 Pavel Safronov | 73 | |
a3080daf 2026-03-17 Pavel Safronov | 74 | Share the room QR code/link only with trusted people to protect your privacy. |
ec059e03 2026-03-15 Pavel Safronov | 75 | |
a3080daf 2026-03-17 Pavel Safronov | 76 | If a link is leaked or compromised, create a new room and share the new QR |
| 77 | code/link with your friends. | |
ec059e03 2026-03-15 Pavel Safronov | 78 | |
a3080daf 2026-03-17 Pavel Safronov | 79 | Here is a screenshot of database info currently stored (March 2026) for test |
| 80 | rooms. Room and friend ids are random strings, and friend info is encrypted. | |
| 81 | Without the room link, data in the database cannot be tied to real-world | |
| 82 | identities or locations. | |
1e2e4bc1 2026-03-15 Pavel Safronov | 83 | |
a3080daf 2026-03-17 Pavel Safronov | 84 | ![Firebase Realtime Database view (March 2026) with encrypted participant |
| 85 | information][firebase-db-screenshot] | |
1e2e4bc1 2026-03-15 Pavel Safronov | 86 | |
ec059e03 2026-03-15 Pavel Safronov | 87 | ## Links |
| 88 | ||
a3080daf 2026-03-17 Pavel Safronov | 89 | - Repo: [GitLab repository][repo-link] |
| 90 | - App: [Friend Compass app][app-link] | |
ec059e03 2026-03-15 Pavel Safronov | 91 | |
a3080daf 2026-03-17 Pavel Safronov | 92 | ## Inspiration |
ec059e03 2026-03-15 Pavel Safronov | 93 | |
a3080daf 2026-03-17 Pavel Safronov | 94 | [Totem Compass](https://totemlabs.com/) and |
| 95 | [Crowd Compass](https://www.crowdcompass.io/) provide similar functionality, | |
| 96 | but they are physical products made for off-the-grid use cases such as hiking | |
| 97 | or festivals where cellular connectivity may be limited. | |
a402f607 2026-03-15 Pavel Safronov | 98 | |
a3080daf 2026-03-17 Pavel Safronov | 99 | This app is designed for phone-first scenarios where people want to share |
| 100 | location with friends (or strangers) in real-time and have internet | |
| 101 | connectivity. | |
a402f607 2026-03-15 Pavel Safronov | 102 | |
a3080daf 2026-03-17 Pavel Safronov | 103 | ## Development |
ec059e03 2026-03-15 Pavel Safronov | 104 | |
4e701dc7 2026-03-16 Pavel Safronov | 105 | ### Local development |
| 106 | ||
| 107 | 1. Install dependencies: | |
| 108 | ||
a3080daf 2026-03-17 Pavel Safronov | 109 | ```bash |
| 110 | npm install | |
| 111 | ``` | |
4e701dc7 2026-03-16 Pavel Safronov | 112 | |
| 113 | 2. Run the dev server: | |
| 114 | ||
a3080daf 2026-03-17 Pavel Safronov | 115 | ```bash |
| 116 | npm run dev | |
| 117 | ``` | |
4e701dc7 2026-03-16 Pavel Safronov | 118 | |
| 119 | 3. Build production artifacts into `./public`: | |
| 120 | ||
a3080daf 2026-03-17 Pavel Safronov | 121 | ```bash |
| 122 | npm run build | |
| 123 | ``` | |
4e701dc7 2026-03-16 Pavel Safronov | 124 | |
| 125 | 4. Preview the production build locally: | |
| 126 | ||
a3080daf 2026-03-17 Pavel Safronov | 127 | ```bash |
| 128 | npm run preview | |
| 129 | ``` | |
4e701dc7 2026-03-16 Pavel Safronov | 130 | |
32796e53 2026-03-16 Pavel Safronov | 131 | ### Features Implemented |
0a0cb749 2026-03-15 Pavel Safronov | 132 | |
32796e53 2026-03-16 Pavel Safronov | 133 | #### User-Facing Features |
| 134 | ||
a3080daf 2026-03-17 Pavel Safronov | 135 | - **Wake-Lock (Stay-Awake Mode)** - Emoji toggle button (💤/🔆) keeps device |
| 136 | screen active during tracking | |
| 137 | - **Toast Notifications** - Contextual feedback for compass events, | |
| 138 | calibration status, and wake-lock actions | |
| 139 | - **Compass Calibration Feedback** - Toast messages for permission denied, | |
| 140 | enabled, unavailable, and calibrated states | |
| 141 | - **User Profile Persistence** - Custom name and color saved locally and | |
| 142 | restored on app reload | |
| 143 | - **Dark Mode Support** - Toggle dark mode with persistent preference storage | |
| 144 | - **Accessibility Improvements** - ARIA labels, semantic HTML, and keyboard | |
| 145 | navigation support | |
32796e53 2026-03-16 Pavel Safronov | 146 | |
| 147 | #### Technical Improvements | |
| 148 | ||
a3080daf 2026-03-17 Pavel Safronov | 149 | - **Strict TypeScript Mode** - All ~40 files migrated; zero type errors |
| 150 | - **Domain-Driven Folder Structure** - Organized into `src/core`, | |
| 151 | `src/features`, and `src/platform` with domain subfolders | |
| 152 | - **Barrel Index Files** - Simplified imports across feature modules | |
| 153 | - **Naming Convention Standardization** - All filenames use underscores, not | |
| 154 | dashes | |
32796e53 2026-03-16 Pavel Safronov | 155 | |
| 156 | ### Future Work | |
| 157 | ||
| 158 | #### Planned Features | |
0a0cb749 2026-03-15 Pavel Safronov | 159 | |
a3080daf 2026-03-17 Pavel Safronov | 160 | - Optional user-facing low-power tracking mode toggle (battery saver style |
| 161 | control) | |
| 162 | - Friend stale-state UX polish (for example: clearer badges, subtle icons, | |
| 163 | better wording) | |
| 164 | - Export/share diagnostics mode for easier field testing (sensor | |
| 165 | availability, last sync times, etc.) | |
| 166 | - Continue migrating behavior-tuning constants into public settings (for | |
| 167 | example initial seed position and other non-sensitive runtime defaults) | |
0a0cb749 2026-03-15 Pavel Safronov | 168 | |
32796e53 2026-03-16 Pavel Safronov | 169 | #### Mobile Platform Support |
| 170 | ||
a3080daf 2026-03-17 Pavel Safronov | 171 | - **React Native + Expo Migration** - Reuse ~80% of TypeScript logic (crypto, |
| 172 | utils, Firebase sync) while rebuilding the UI layer for iOS/Android native | |
| 173 | support with background geolocation | |
| 174 | - **Background Geolocation** - Continuous location tracking even when the app | |
| 175 | is in the background (requires native implementation) | |
| 176 | - **Battery Optimization** - Configurable tracking intervals and geofencing so | |
| 177 | users can define regions where they care about updates (or where they do | |
| 178 | not) | |
32796e53 2026-03-16 Pavel Safronov | 179 | |
ec059e03 2026-03-15 Pavel Safronov | 180 | ### Firebase database rules |
2ba7a9cc 2026-03-15 Pavel Safronov | 181 | |
a3080daf 2026-03-17 Pavel Safronov | 182 | This repo includes Realtime Database security rules in |
| 183 | [config/firebase/database.rules.json](config/firebase/database.rules.json). | |
2ba7a9cc 2026-03-15 Pavel Safronov | 184 | |
a3080daf 2026-03-17 Pavel Safronov | 185 | The rules can be deployed using the Firebase CLI, with |
2ba7a9cc 2026-03-15 Pavel Safronov | 186 | |
a3080daf 2026-03-17 Pavel Safronov | 187 | ```bash |
| 188 | npm run firebase:deploy-rules | |
| 189 | ``` | |
2ba7a9cc 2026-03-15 Pavel Safronov | 190 | |
| 191 | Without these rules, your database may allow unsafe writes. | |
| 192 | ||
a3080daf 2026-03-17 Pavel Safronov | 193 | ### Firebase stale room cleanup |
| 194 | ||
| 195 | The app does not currently implement any automatic cleanup of stale rooms or | |
| 196 | participants. This means that if a room is created and then abandoned, its | |
| 197 | data will remain in the database indefinitely. | |
| 198 | ||
| 199 | To clean up stale rooms, we're using GitLab's scheduled pipelines to run a | |
| 200 | cleanup script every week. | |
| 201 | ||
| 202 | The script can be called manually in preview mode with | |
| 203 | ||
| 204 | ```bash | |
| 205 | npm run clean-old-firebase:preview-30d | |
| 206 | ``` | |
| 207 | ||
| 208 | and actually executed with | |
| 209 | ||
| 210 | ```bash | |
| 211 | npm run clean-old-firebase:run-30d | |
| 212 | ``` | |
| 213 | ||
32796e53 2026-03-16 Pavel Safronov | 214 | ### Absolute location |
| 215 | ||
a3080daf 2026-03-17 Pavel Safronov | 216 | I explicitly chose not to expose direct map deep links in the UI, and this |
| 217 | feature will **not** be added. | |
| 218 | ||
| 219 | The app keeps precise coordinates internally for relative-arrow calculations, | |
| 220 | but intentionally shows only relative directions. | |
32796e53 2026-03-16 Pavel Safronov | 221 | |
a3080daf 2026-03-17 Pavel Safronov | 222 | This is a current design choice. Feel free to bring this up in an issue if |
| 223 | you have strong feelings about it. | |
32796e53 2026-03-16 Pavel Safronov | 224 | |
a3080daf 2026-03-17 Pavel Safronov | 225 | ### Testing |
| 226 | ||
| 227 | - BrowserStack test link: [Open BrowserStack session][browserstack-link] | |
| 228 | - Firebase console: [North Star Firebase console][firebase-console-link] | |
32796e53 2026-03-16 Pavel Safronov | 229 | |
ec059e03 2026-03-15 Pavel Safronov | 230 | ### Is it open source? |
e70d53bd 2026-03-15 Pavel Safronov | 231 | |
| 232 | You're looking at it. | |
| 233 | ||
| 234 | ### License | |
| 235 | ||
| 236 | This project is licensed under the MIT License. | |
1a128926 2026-03-15 Pavel Safronov | 237 | |
| 238 | #### Why MIT for this project? | |
| 239 | ||
| 240 | Short version: emotional simplicity and momentum. | |
| 241 | ||
a3080daf 2026-03-17 Pavel Safronov | 242 | - This is a weekend project, and I want low-friction freedom to build, share, |
| 243 | and potentially monetize my own work without overthinking legal structure | |
| 244 | - I considered stricter licenses (for example AGPL) to make clone | |
| 245 | monetization harder, but that adds policy/process overhead I do not want | |
| 246 | right now | |
| 247 | - MIT is the simplest path to keep shipping and enjoying the project | |
1a128926 2026-03-15 Pavel Safronov | 248 | |
| 249 | Tradeoff accepted: | |
| 250 | ||
a3080daf 2026-03-17 Pavel Safronov | 251 | - MIT allows others to clone and monetize too, including with better |
| 252 | marketing | |
| 253 | - For this project, that risk is acceptable compared to the cost (time + | |
| 254 | mental load) of managing a more restrictive licensing setup | |
| 255 | ||
| 256 | If priorities change later (for example, stronger anti-closed-clone goals), | |
| 257 | future versions can be relicensed with a different strategy. | |
1a128926 2026-03-15 Pavel Safronov | 258 | |
b10cf38c 2026-10-27 Pavel Safronov | 259 | [repo-link]: https://code.fuzzyworld.net/north-star/ |
| 260 | [app-link]: https://apps.fuzzyworld.net/north-star/ | |
a3080daf 2026-03-17 Pavel Safronov | 261 | [firebase-db-screenshot]: ./firebase-realtime-database-view.png |
| 262 | [browserstack-link]: https://live.browserstack.com/dashboard#os=iOS&os_version=26.0&device_browser=safari&zoom_to_fit=true&full_screen=true&url=https%3A%2F%2Fpavelsafronov.gitlab.io%2Fnorth-star&speed=1 | |
| 263 | [firebase-console-link]: https://console.firebase.google.com/project/north-star-e5dee/overview |