A location-based anonymous matchmaking app for "missed connections"
Backtrack is a cross-platform mobile application for iOS and Android that enables anonymous "missed connection" style matchmaking tied to physical locations.
Have you ever noticed someone interesting at a coffee shop, gym, or bookstore but didn't have the chance to say hello? Backtrack creates a digital ledger for each location where you can leave an anonymous note describing that person - and if they're on the app, they might just find your message.
You see someone Create an avatar They browse the
interesting at a ────► describing them ────► location's ledger
physical location + leave a note & find your post
│ │ │
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────────┐ ┌───────────────┐
│ 📍 Visit │ │ 👤 Build Avatar │ │ 📖 Browse & │
│ Location │ │ + Write Note │ │ Match │
└─────────────┘ └─────────────────┘ └───────────────┘
│
▼
┌───────────────┐
│ 💬 Start │
│ Anonymous │
│ Chat │
└───────────────┘
- Location Discovery - Find venues using Google Maps integration
- Selfie Verification - Take a photo to verify you were actually there
- Avatar Builder - Create a customizable Bitmoji-style avatar describing the person you noticed
- Anonymous Notes - Write a message about your missed connection
- Location-Based Browsing - Browse posts at specific venues
- Description Matching - Create your own avatar and get matched with posts describing you
- Anonymous Conversations - Connect through real-time messaging without revealing identities
| Feature | Description |
|---|---|
| Cross-Platform | Runs natively on both iOS and Android |
| Real-Time Chat | Instant messaging powered by Supabase Realtime |
| Privacy First | Anonymous interactions with no personal data exposed |
| Content Moderation | Reporting and blocking for a safe community |
| Secure Authentication | Sign up and login with email/password via Supabase Auth |
Coming soon - Screenshots will be added as the app is developed
Backtrack is built with modern, production-ready technologies designed for cross-platform mobile development.
| Technology | Purpose | Documentation |
|---|---|---|
| Expo SDK | React Native framework with managed workflow | Expo Docs |
| React Native | Cross-platform native mobile development | RN Docs |
| TypeScript | Type-safe JavaScript for reliability | TS Docs |
| Expo Router | File-based navigation for React Native | Router Docs |
| Zustand | Lightweight state management | Zustand Docs |
| Technology | Purpose | Documentation |
|---|---|---|
| Supabase | Backend-as-a-Service (BaaS) platform | Supabase Docs |
| PostgreSQL | Relational database (via Supabase) | PostgreSQL Docs |
| Supabase Auth | Authentication and user management | Auth Docs |
| Supabase Realtime | Real-time subscriptions for live chat | Realtime Docs |
| Supabase Storage | File storage for images and media | Storage Docs |
| Integration | Purpose | Documentation |
|---|---|---|
| Google Maps | Location discovery and venue selection | Maps SDK Docs |
| react-native-maps | Native map component for React Native | RN Maps Docs |
| Avataaars | Customizable avatar builder library | Avataaars Docs |
| Feature | Expo Module | Purpose |
|---|---|---|
| Camera | expo-camera |
Selfie verification for post creation |
| Image Picker | expo-image-picker |
Gallery access for profile images |
| Location | expo-location |
GPS for proximity-based features |
| SVG Rendering | react-native-svg |
Vector graphics for avatars |
┌─────────────────────────────────────────────────────────────────────────┐
│ Mobile App │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ Expo / React Native │ │
│ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │
│ │ │ Screens │ │ Components │ │ Hooks │ │ Store │ │ │
│ │ │ (Expo │ │ (UI, Map, │ │ (Auth, │ │ (Zustand) │ │ │
│ │ │ Router) │ │ Avatar) │ │ Location) │ │ │ │ │
│ │ └────────────┘ └────────────┘ └────────────┘ └────────────┘ │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ Supabase Client │ │
│ └──────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ Supabase Cloud │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │
│ │ Auth │ │ PostgreSQL │ │ Realtime │ │ Storage │ │
│ │ (Users & │ │ (Database) │ │ (WebSocket) │ │ (Files) │ │
│ │ Sessions) │ │ │ │ │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ External Services │
│ ┌────────────────────────────────┐ ┌───────────────────────────────┐ │
│ │ Google Maps API │ │ Avataaars Library │ │
│ │ (Venue Search & Display) │ │ (Avatar Customization) │ │
│ └────────────────────────────────┘ └───────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
| Choice | Rationale |
|---|---|
| Expo | Simplifies React Native development with managed workflow, OTA updates, and easy deployment |
| TypeScript | Catches bugs at compile-time and improves code maintainability |
| Supabase | Open-source Firebase alternative with PostgreSQL, real-time, and auth out of the box |
| Google Maps | Industry-standard location services with excellent POI data |
| Avataaars | Privacy-preserving visual descriptions without requiring actual photos |
Before you begin, ensure you have the following installed on your development machine:
| Requirement | Minimum Version | Recommended | Check Command |
|---|---|---|---|
| Node.js | 18.x | 20.x LTS | node --version |
| npm | 9.x | 10.x | npm --version |
| Git | 2.x | Latest | git --version |
| Platform | Requirement | Notes |
|---|---|---|
| iOS | macOS + Xcode | Required for iOS simulator and builds |
| Android | Android Studio | Required for Android emulator and builds |
| Physical Device | Expo Go app | Scan QR code to run on device |
💡 Tip: For the fastest setup, use the Expo Go app on your physical device - no simulator setup required!
Get up and running in minutes with these essential steps:
- Node.js 18.0.0 or higher (download)
- npm or pnpm package manager
- Git for version control
- Supabase account (sign up free)
- Google Cloud account with Maps API (get started)
- Clone the repository
git clone https://github.com/shortforge/backtrack.git
cd backtrack- Install dependencies
npm installThis installs all required dependencies including:
- React Native / Expo SDK
- Supabase client
- Navigation libraries
- Map and avatar components
- Set Up Environment Variables
Create a .env.local file in the project root:
# Copy the example file
cp .env.example .env.localThen add your API keys:
# Supabase Configuration
EXPO_PUBLIC_SUPABASE_URL=https://your-project-id.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key
# Google Maps Configuration
EXPO_PUBLIC_GOOGLE_MAPS_API_KEY=your-google-maps-api-keyFor detailed setup instructions, see our Contributing Guide.
- Start the Development Server
npx expo startThis will start the Expo development server and display a QR code.
- Run on Your Device or Simulator
| Method | Command/Action |
|---|---|
| Physical Device | Scan the QR code with Expo Go app |
| iOS Simulator | Press i in terminal (macOS only) |
| Android Emulator | Press a in terminal |
| Web Browser | Press w in terminal |
Here's a quick reference for common development commands:
# Start development server
npx expo start
# Start with tunnel (for devices on different networks)
npx expo start --tunnel
# Start with cache cleared
npx expo start --clear
# Run on iOS simulator
npx expo run:ios
# Run on Android emulator
npx expo run:android
# Install a new Expo-compatible package
npx expo install <package-name>
# Check for Expo SDK compatibility issues
npx expo-doctor
# Build for production (requires EAS)
npx eas build --platform allFor detailed setup instructions and guides, see:
-
Contributing Guide - Complete developer setup with step-by-step instructions for:
- Supabase project configuration
- Google Maps API setup
- Environment variables
- Development workflow
- Troubleshooting
-
Database Guide - Database setup and management:
- Schema overview
- Running migrations
- PostGIS configuration
- Row Level Security (RLS) policies
The project follows an Expo Router file-based routing pattern with organized folders for components, hooks, and utilities.
backtrack/
├── app/ # 📱 Expo Router app directory (screens/routes)
│ ├── (auth)/ # Authentication routes (login, signup)
│ │ ├── login.tsx
│ │ ├── signup.tsx
│ │ └── _layout.tsx
│ ├── (tabs)/ # Main tabbed navigation
│ │ ├── home.tsx # Home/Feed screen
│ │ ├── explore.tsx # Location exploration/map
│ │ ├── create.tsx # Create post screen
│ │ ├── messages.tsx # Conversations list
│ │ ├── profile.tsx # User profile
│ │ └── _layout.tsx
│ ├── chat/ # Chat screens
│ │ └── [id].tsx # Dynamic chat view
│ ├── post/ # Post detail screens
│ │ └── [id].tsx # Dynamic post view
│ ├── _layout.tsx # Root layout
│ └── index.tsx # Entry point
│
├── components/ # 🧩 Reusable React components
│ ├── ui/ # Generic UI components
│ │ ├── Button.tsx
│ │ ├── Input.tsx
│ │ ├── Card.tsx
│ │ └── Avatar.tsx
│ ├── avatar/ # Avataaars-related components
│ │ ├── AvatarBuilder.tsx
│ │ └── AvatarPreview.tsx
│ ├── map/ # Map-related components
│ │ ├── MapView.tsx
│ │ └── LocationPicker.tsx
│ ├── post/ # Post-related components
│ │ ├── PostCard.tsx
│ │ └── PostForm.tsx
│ └── chat/ # Chat-related components
│ ├── MessageBubble.tsx
│ └── ChatInput.tsx
│
├── hooks/ # 🪝 Custom React hooks
│ ├── useAuth.ts # Authentication hook
│ ├── useLocation.ts # Location services hook
│ ├── usePosts.ts # Posts data hook
│ ├── useChat.ts # Real-time chat hook
│ └── useProfile.ts # Profile management hook
│
├── lib/ # 📚 Core libraries and utilities
│ ├── supabase.ts # Supabase client configuration
│ ├── api/ # API functions
│ │ ├── auth.ts
│ │ ├── posts.ts
│ │ ├── messages.ts
│ │ └── profiles.ts
│ └── utils/ # Utility functions
│ ├── formatting.ts
│ └── validation.ts
│
├── store/ # 🗄️ State management (Zustand)
│ ├── auth.ts # Auth state store
│ ├── posts.ts # Posts state store
│ ├── chat.ts # Chat state store
│ └── ui.ts # UI state store
│
├── types/ # 📘 TypeScript type definitions
│ ├── index.ts # Shared types
│ ├── database.ts # Database schema types
│ ├── api.ts # API response types
│ └── ui.ts # Component prop types
│
├── app.json # Expo configuration
├── tsconfig.json # TypeScript configuration
├── .env.example # Environment variable template
├── .gitignore # Git ignore rules
├── package.json # Project dependencies
├── eas.json # EAS Build configuration
├── CONTRIBUTING.md # Developer setup guide
└── LICENSE # MIT License
Backtrack uses Vitest as its testing framework, providing fast, modern testing with excellent TypeScript support.
| Command | Description |
|---|---|
npm test |
Run all tests in watch mode |
npm run test:run |
Run all tests once |
npm run test:watch |
Run tests in watch mode (alias for npm test) |
npm run test:coverage |
Run tests with coverage report |
npm run test:e2e |
Run end-to-end tests |
npm run test:unit |
Run unit tests only |
npm run test:components |
Run component tests only |
Tests are organized in two locations:
backtrack/
├── __tests__/ # Centralized test files
│ └── lib/ # Tests for library code
│ └── utils/
│ └── geo.test.ts # Example: geo utility tests
│
├── components/ # Component tests (co-located)
│ └── chat/
│ └── __tests__/
│ └── ChatInput.test.tsx
│
└── hooks/ # Hook tests (co-located)
└── __tests__/
└── useAuth.test.ts
Tests use Vitest's API which is compatible with Jest. Import test functions explicitly:
import { describe, it, expect, vi, beforeEach } from 'vitest'
describe('Feature Name', () => {
beforeEach(() => {
vi.clearAllMocks()
})
it('should do something', () => {
expect(result).toBe(expected)
})
it('should mock dependencies', () => {
const mockFn = vi.fn().mockReturnValue('mocked')
expect(mockFn()).toBe('mocked')
})
})Use vi instead of jest for mocking:
| Jest | Vitest |
|---|---|
jest.fn() |
vi.fn() |
jest.mock('./module') |
vi.mock('./module') |
jest.spyOn(obj, 'method') |
vi.spyOn(obj, 'method') |
Tests automatically run in the appropriate environment based on file patterns:
| Pattern | Environment | Use Case |
|---|---|---|
components/**/*.test.tsx |
jsdom |
React component testing |
hooks/**/*.test.tsx |
jsdom |
React hook testing |
lib/**/*.test.ts |
node |
Utility/server-side testing |
*.happy.test.tsx |
happy-dom |
Performance-optimized DOM testing |
Generate coverage reports with:
npm run test:coverageCoverage reports are generated in multiple formats:
- Terminal: Summary displayed after tests
- HTML: Open
coverage/index.htmlfor detailed view - JSON: Machine-readable format for CI integration
Current coverage thresholds:
- Branches: 50%
- Functions: 50%
- Lines: 50%
- Statements: 50%
We welcome contributions! Please read our Contributing Guide for details on setting up your development environment and our coding standards.