Skip to content

ayushanand293/MeetUp

Repository files navigation

MeetUp ๐Ÿ“

Real-time location sharing โ€” privacy-first, built to scale.

MeetUp is a full-stack mobile + backend platform that lets two people share their live location with each other and automatically detect when they've met. It combines a FastAPI WebSocket backend with a React Native mobile client, using Redis pub/sub for multi-instance broadcasting and PostgreSQL with PostGIS for persistent geospatial data.


Table of Contents


What It Does

MeetUp solves a simple but surprisingly hard problem: "I'm on my way โ€” where are you?"

Instead of sending a static pin, both users share live GPS location in a private session. The app:

  1. Shows real-time positions on a map as each person moves
  2. Calculates live distance between the two users
  3. Detects proximity (โ‰ค 50m) and triggers an "I'm Here" confirmation flow
  4. Automatically ends the session and celebrates once both confirm they've met

The session is ephemeral โ€” no location history is stored after it ends. Privacy is built in by design.


Tech Stack

Layer Technology
Mobile React Native (Expo), React Navigation
Backend API Python 3.11, FastAPI
Realtime WebSockets (FastAPI native), Redis Pub/Sub
Database PostgreSQL 15 + PostGIS extension
Cache / Broker Redis
Auth Supabase JWT (verified server-side via pyjwt)
Migrations Alembic
Containerisation Docker + Docker Compose
Linting Ruff (Python), ESLint + Prettier (JS)
Testing Pytest (backend), manual E2E (mobile)

Project Structure

MeetUp/
โ”œโ”€โ”€ backend/                  # FastAPI service
โ”‚   โ”œโ”€โ”€ app/
โ”‚   โ”‚   โ”œโ”€โ”€ api/              # REST route handlers
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ endpoints/    # users, sessions, requests, metrics, realtime
โ”‚   โ”‚   โ”œโ”€โ”€ core/             # Config, database, auth helpers
โ”‚   โ”‚   โ”œโ”€โ”€ models/           # SQLAlchemy ORM models
โ”‚   โ”‚   โ”œโ”€โ”€ realtime/         # WebSocket gateway & ConnectionManager
โ”‚   โ”‚   โ””โ”€โ”€ worker/           # Background workers (e.g. session cleanup)
โ”‚   โ”œโ”€โ”€ alembic/              # Database migration scripts
โ”‚   โ”œโ”€โ”€ tests/                # Pytest test suite
โ”‚   โ”œโ”€โ”€ seed.py               # Creates test users + session for local dev
โ”‚   โ”œโ”€โ”€ Dockerfile
โ”‚   โ””โ”€โ”€ requirements.txt
โ”‚
โ”œโ”€โ”€ mobile/                   # React Native (Expo) app
โ”‚   โ””โ”€โ”€ src/
โ”‚       โ”œโ”€โ”€ screens/          # All app screens (Home, Session, Auth, etc.)
โ”‚       โ”œโ”€โ”€ components/       # Reusable UI components
โ”‚       โ”œโ”€โ”€ services/         # locationService, realtimeService, analyticsService
โ”‚       โ”œโ”€โ”€ context/          # AuthContext (JWT, deep-link handling)
โ”‚       โ”œโ”€โ”€ navigation/       # AppNavigator (tab + stack navigation)
โ”‚       โ””โ”€โ”€ api/              # HTTP API client wrappers
โ”‚
โ”œโ”€โ”€ web/
โ”‚   โ””โ”€โ”€ client.html           # Standalone WebSocket debug client
โ”‚
โ”œโ”€โ”€ scripts/                  # lint.sh, setup_hooks.sh
โ”œโ”€โ”€ docker-compose.yml
โ”œโ”€โ”€ ARCHITECTURE.md           # Deep-dive into multi-instance design
โ”œโ”€โ”€ PROTOCOL.md               # WebSocket message specification
โ””โ”€โ”€ QUICK_START.md            # Setup for new contributors

Architecture Overview

The backend is designed for horizontal scaling from day one. Multiple API instances run behind a load balancer; they never share in-process memory. All cross-instance communication goes through Redis.

         Mobile / Web clients
               โ”‚
        HTTP + WebSocket
               โ”‚
     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
     โ”‚   Load Balancer   โ”‚  (nginx / cloud LB)
     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
               โ”‚
  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  โ”‚            โ”‚            โ”‚
API-1        API-2        API-N      โ† Stateless FastAPI instances
  โ”‚            โ”‚            โ”‚
  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
               โ”‚
         โ”Œโ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”
         โ”‚   Redis   โ”‚  โ† Pub/Sub (session:*), rate-limit keys, presence TTLs
         โ””โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜
               โ”‚
         โ”Œโ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
         โ”‚  PostgreSQL    โ”‚  โ† Persistent storage (users, sessions, requests, audit)
         โ”‚  + PostGIS     โ”‚
         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

When User A (connected to API-1) sends a location update:

  1. API-1 validates the message (coordinates, accuracy, timestamp, jump detection)
  2. API-1 publishes the event to session:{uuid} on Redis
  3. All API instances subscribed to that channel receive it
  4. Each instance forwards the payload to any local WebSocket connections in that session
  5. User B (connected to API-2) receives the location update in real time

Full design docs โ†’ ARCHITECTURE.md


Key Features

๐Ÿ” Auth & Identity

  • JWT-based auth, issued by Supabase, verified server-side on every request and WebSocket upgrade
  • User registration and login handled on the mobile client; backend is stateless

๐Ÿค Meet Requests

  • Users can search friends and send a meet request
  • Deep-link support: meetup://request/{requestId} opens the request inbox directly
  • Accept/reject flow with inline status feedback and WhatsApp-friendly invite sharing

๐Ÿ“ก Live Location Session

  • Both users join a shared session by ID (or via deep-link meetup://session/{sessionId})
  • Location updates stream over WebSocket at up to 10 updates/sec per user (rate-limited server-side)
  • Server validates every location packet:
    • Coordinates within valid bounds (lat: ยฑ90, lon: ยฑ180)
    • Accuracy between 0.1m โ€“ 100m
    • Timestamp within ยฑ5 minutes of server time
    • Speed check: rejects jumps > 300 km/h (impossible movement detection)

๐Ÿ—บ๏ธ Distance Intelligence

  • Live distance bar shows current separation
  • Status changes as users approach: Far away โ†’ Getting close โ†’ Nearly there
  • "I'm Here" CTA unlocks at โ‰ค 50m with a pulse animation

โœ… Proximity End Flow

  • User taps "I'm Here" โ†’ 60-second confirmation timer starts
  • Both users must confirm within the window
  • Session auto-ends; a celebration animation plays
  • Fallback: manual confirm path if timer edge-cases occur

๐Ÿ”’ Privacy Controls

  • Pause Sharing: stops broadcasting GPS while keeping the session alive
  • App automatically pauses on background and resumes on foreground
  • Stale/expired peer location states shown clearly in UI (TTL-aware)

๐Ÿ” Reconnect Resilience (Week 6)

  • Grace-window countdown before exponential retry kicks in
  • Status badge updates through grace โ†’ reconnect โ†’ live states
  • Snapshot re-sync automatically on reconnect
  • URL continuity: retries always use the original backend base URL

๐Ÿ“Š Observability

  • GET /api/v1/metrics returns per-instance counters and gauges (WS connections, messages, rate-limit hits, validation errors)
  • Alerting thresholds documented in ARCHITECTURE.md

WebSocket Protocol

Connection URL

ws://<host>/api/v1/ws/meetup?token=<JWT>&session_id=<UUID>

Client โ†’ Server

Message Description
location_update Broadcast current GPS position
end_session Manually close the session
// location_update
{
  "type": "location_update",
  "payload": {
    "lat": 12.9716,
    "lon": 77.5946,
    "accuracy_m": 5.0,
    "timestamp": "2026-04-10T09:00:00Z"
  }
}

Server โ†’ Client

Message Description
peer_location Another participant's updated position
presence_update A user joined or left the session
session_ended Session closed (user action or proximity)
error Validation failure, rate limit, etc.
// error example
{
  "type": "error",
  "payload": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many updates"
  }
}

Full payload schemas โ†’ PROTOCOL.md


REST API Endpoints

Method Path Description
POST /api/v1/users/register Register a new user
GET /api/v1/users/{id} Fetch user profile
POST /api/v1/requests Send a meet request
GET /api/v1/requests List incoming / outgoing requests
POST /api/v1/requests/{id}/accept Accept a meet request
POST /api/v1/sessions Create a new session
GET /api/v1/sessions/{id} Get session details
DELETE /api/v1/sessions/{id} End a session
POST /api/v1/sessions/{id}/im-here Confirm proximity ("I'm Here")
POST /api/v1/invite/redeem Redeem a deep-link invite token
GET /api/v1/metrics Per-instance observability counters
WS /api/v1/ws/meetup Realtime location WebSocket

Getting Started

Prerequisites

  • Docker & Docker Compose
  • Node.js โ‰ฅ 18 (for mobile development)
  • A Supabase project (for JWT secret)

1 โ€” Environment Setup

cp .env.example .env

Open .env and fill in:

  • SUPABASE_URL โ€” your Supabase project URL
  • SUPABASE_KEY โ€” your Supabase JWT Secret (used for server-side token verification)

2 โ€” Start the Stack

docker-compose up -d --build

This starts PostgreSQL (with PostGIS), Redis, and the FastAPI backend.

3 โ€” Run Migrations & Seed Data

# Apply DB schema (first run only)
docker-compose exec backend alembic upgrade head

# Create test users (Alice & Bob) + an active session
docker-compose exec backend python seed.py

Save the output! It contains the Session ID and JWT tokens for Alice and Bob โ€” you'll need these to test the WebSocket.

4 โ€” Verify with the Web Debugger

  1. Open web/client.html in your browser (no server needed โ€” it's a plain HTML file)
  2. Paste Alice's JWT token and the Session ID
  3. Click Connect
  4. Open a second tab for Bob and do the same
  5. Move Alice's location โ€” Bob's tab should update in real time

5 โ€” Run the Mobile App

cd mobile
npm install
npx expo start

Scan the QR code with Expo Go or run on a simulator.


Testing

Backend

# All tests
docker-compose exec backend pytest

# With output
docker-compose exec backend pytest -v

# Specific file
docker-compose exec backend pytest tests/test_realtime.py

Quick Validation (from project root)

python quick_validation_test.py

Runs a lightweight connectivity check without Docker.


Code Quality

Run All Linters

./scripts/lint.sh

Backend (Python โ€” Ruff)

docker-compose exec backend ruff check .
docker-compose exec backend ruff format .

Mobile (JavaScript โ€” ESLint + Prettier)

cd mobile
npm run lint        # check
npm run lint:fix    # auto-fix
npm run format      # prettier

Pre-commit Hooks (Recommended)

./scripts/setup_hooks.sh

Installs git hooks that automatically lint and format on every commit:

  • โœ… Python (Ruff check + format)
  • โœ… JavaScript (ESLint + Prettier)
  • โœ… Trailing whitespace & large file checks

Manual run:

pre-commit run --all-files

Skip (not recommended):

git commit --no-verify

Deployment

The system is designed for multi-instance deployment. A reference docker-compose.yml runs 3 backend instances behind nginx for local load-balancer testing:

# Scale to N instances (with external nginx)
docker-compose up -d --scale backend=3

Each instance is fully stateless โ€” scale up or down without downtime. Redis handles all cross-instance coordination.

Scalability estimates (per instance, 4 CPU / 8 GB RAM):

Metric Limit
WebSocket connections ~1,000
Concurrent sessions ~500
Location updates / sec ~5,000
Broadcast latency < 50ms

Additional Documentation

Document Contents
ARCHITECTURE.md Full multi-instance design, failure modes, scaling strategy
PROTOCOL.md Complete WebSocket message specification
QUICK_START.md Condensed onboarding for new contributors
FRONTEND_PROGRESS_README.md Week-by-week mobile feature tracker

License

Private project. All rights reserved.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

โšก