692+
Source Files
65+
API Endpoints
22
Database Tables
604
Test Functions
40+
Event Types
10
Integrations
Every group trip starts the same way. Someone creates a WhatsApp group. Someone else shares a Google Sheet. A third person downloads Splitwise. Within 48 hours, the planning context is scattered across five apps, three time zones, and zero shared understanding.
The failure mode is not a lack of tools — it is a surplus of disconnected ones. Conversations happen in one app. Budgets live in another. Location sharing requires a third. No single surface holds the full picture, and decisions stall because context is always somewhere else.
Fragmented tooling — Chat in WhatsApp, budgets in Splitwise, itineraries in Google Sheets, maps via shared links. Every tool holds a fragment; none holds the truth.
Coordination across time zones — Asynchronous planning with no shared state means someone is always out of the loop.
Expense opacity — Who paid for what, who owes whom, and how to split unevenly across subgroups is a recurring source of friction.
No trip lifecycle — Existing tools treat a trip as a static document. In reality, a trip moves through phases: creation, invites, active planning, live coordination, and post-trip settlement.
Permission complexity — Group dynamics are not flat. Admins, members, and guests need different levels of access — and those permissions shift as the trip evolves.
Not a booking engine. Not a social feed. Not another travel planner. A structured, real-time workspace where every participant sees the same trip state, at all times, from any time zone.
A mobile-first experience across 12 feature modules — from trip creation through settlement.

Trip List
Every active, upcoming, and completed trip in one view. Status badges show trip phase at a glance.

Live Map
Real-time location sharing across all trip members on a single Google Maps integration.

Invite Member
Streamlined invite flow with role-based permissions assigned automatically on acceptance.

Welcome
Google and Apple Sign-In with secure token storage and preemptive refresh.

Onboarding
First-run experience that sets context before the first trip is created.

Setup
Identity setup that feeds into the permission and notification systems.
Two pillars: a Go backend optimized for concurrent, real-time workloads and a React Native + Expo client that ships to both platforms from one codebase. The architecture is deliberately opinionated.
Goroutines and channels handle thousands of simultaneous WebSocket connections with minimal overhead
Single codebase for iOS and Android with native performance where it matters
Enforces referential integrity across trips, members, expenses, and permissions at the schema level
Hot-path caching and real-time event distribution between service boundaries
Persistent connections for instant chat, location updates, and trip state synchronization
Object storage for trip media with HMAC-signed download URLs and magic-byte MIME detection
Matrix-based permission model mapping users, roles, trip phases, and resource types
Group coordination is a fundamentally concurrent problem. These are the engineering decisions that made it work.
Money stored in minor units (cents as BIGINT). The go-money library handles distribution, and a greedy debt simplification algorithm minimizes the number of settlement transactions. Three split types — EQUAL, EXACT, and PERCENTAGE — all resolve without rounding errors.
A PostgreSQL function round_coordinates() enforces three privacy levels — hidden, approximate (~1.1km), and precise. The application layer cannot bypass it. Privacy is not a feature flag; it is a schema constraint.
Each connection runs three goroutines (read, write, ping) coordinated via context cancellation. A sync.RWMutex guards the connection map. Buffered channels (256) with graceful overflow — drops events rather than blocking the hub.
iOS limits SecureStore entries to 2,048 bytes. JWT tokens exceed this. The frontend implements a chunking adapter that splits tokens across multiple entries and reassembles transparently — combined with preemptive refresh and a 401 queue for concurrent requests.
15 generated query files covering all domain entities. SQL injection and type mismatch bugs are caught at compile time, not runtime. The database is the authority, not the code.
Oracle Cloud free tier (4 OCPU, 24GB ARM), Coolify for orchestration, Supabase free tier for auth, Cloudflare R2 for storage. Production-grade deployment at near-zero operational cost.
The permission model evaluates access across four dimensions — user identity, trip phase, resource type, and relationship context. An admin’s permissions during planning differ from their permissions during an active trip, automatically.
Chat, location, expenses, and trip state all flow through the same WebSocket infrastructure. No polling. No stale reads. Every participant sees the same truth, at the same time.
Most travel apps focus on booking or during-trip features. NomadCrew treats the weeks of group coordination before departure as the primary use case — because that is where trips succeed or fail.
The backend was built in Go because group coordination is a fundamentally concurrent problem. Goroutines and channels handle this naturally, without thread-management overhead.
Not a chat app. Not a shared spreadsheet. Not another travel planner.