A civic public-awareness React Native (Expo + TypeScript) app focused on nearby ICE enforcement activity. The UI is map-centric with a Luma-style immersive map and an Uber-style bottom sliding panel.
- Map-centric home screen: Full-screen map with user location, incident markers (color-coded by danger level), heatmap overlay, recenter button, and alert count badge.
- Bottom sliding panel: Draggable panel with three snap states (collapsed / mid / expanded). Collapsed shows a short summary and nearest danger badge; expanded shows a circular radar and a closest-incident list. Tap an incident to open its detail screen.
- Incident detail: Map preview, summary, timestamp, distance, danger score, “What should I do?” placeholder, and Share (stub).
- Real-time updates: Incidents are derived from the Supabase table
raid_flags(video_id, flagged, updated_at). The app fetches flagged rows on load and subscribes to Supabase Realtime for insert/update/delete; display data (location, title, coordinates) comes from a static map insrc/data/video_metadata.ts. Alerts stay in sync with the web app that marks “ice raid” videos.
- Expo (SDK 54), TypeScript
- Expo Router (file-based), React Navigation (native stack)
- react-native-maps (map, markers, heatmap)
- expo-location, expo-notifications
- Supabase for
raid_flagstable and Realtime subscription - Context API for state (
IncidentContext) - react-native-reanimated + react-native-gesture-handler for the bottom panel
/src
/components Reusable UI (DangerBadge, BottomPanel, Radar, ClosestIncidentList, MapScreen, etc.)
/context IncidentContext (incidents, userLocation, setIncidents, addIncident, removeIncident, setUserLocation)
/data video_metadata.ts (video_id → locationName, lat/lng, title, etc.)
/lib supabase.ts (Supabase client)
/services raidFlags.ts (fetch raid_flags, transform to Incident[], Realtime subscription)
/hooks useLocation, useRealtimeIncidents, usePushNotificationSetup
/types incident.ts (Incident, getDangerLevel)
/navigation (types for routes; navigation is Expo Router)
/screens (optional; main UI lives in app/ routes that use src/components)
/app
_layout.tsx Root layout: ThemeProvider, IncidentProvider, RaidFlagsSync, Stack, PushNotificationSetup
(tabs)/ Tab layout; index.tsx = MapScreen
incident/[id].tsx Incident detail screen
/constants theme.ts (light theme, DangerColors, ICEAlertColors)
The app reads alerts from a Supabase project:
- Table
raid_flags:video_id(text, PK),flagged(boolean),updated_at(timestamptz). Only rows withflagged = trueare shown as incidents. Enable Realtime for this table in the Supabase dashboard (Table → Replication). - Metadata:
src/data/video_metadata.tsmaps eachvideo_id(e.g.ice-raid-1.mp4) to display info:locationName,latitude,longitude,title, and optionalyoutube_url,date,duration_seconds. Incidents are derived from flagged rows plus this map; distance and severity are computed from the user’s location.
Required env vars (see .env.example):
EXPO_PUBLIC_SUPABASE_URL– your Supabase project URL (e.g.https://xxxx.supabase.co).EXPO_PUBLIC_SUPABASE_ANON_KEY– the anon/public key for the project.
Optional:
EXPO_PUBLIC_PROJECT_ID– used when requesting an Expo push token (for notifications stub).
If these Supabase vars are not set, the app shows no incidents (empty list).
The app uses a red / yellow / green proximity model: distance from the user to a raid determines the tier (red < 0.2 km, yellow 0.2–1 km, green 1+ km). Tracked ice raid cities are grouped below by concentration (multiple incidents in the same metro = higher tier).
🔴 Red (high concentration — multiple raids in same metro)
- Cypress Park, California
- Los Angeles, California
🟡 Yellow (medium concentration — two raids in same metro)
- Minneapolis, Minnesota
- Burnsville, Minnesota
🟢 Green (single raid in metro)
- San Antonio, Texas
- Copy
.env.exampleto.envand setEXPO_PUBLIC_SUPABASE_URLandEXPO_PUBLIC_SUPABASE_ANON_KEY. - Install dependencies:
npm install - Start:
npx expo start - Open in a development build, simulator, or Expo Go as usual.
- Theme: Light only. Soft off-white background, charcoal text, danger colors (green / amber / red for low / medium / high).
- Principles: Generous padding, rounded cards, subtle shadow, smooth animations, no harsh borders.
- App behavior and structure are described in this README and in code comments under
src/. - For Expo, React Navigation, and react-native-maps, see their official docs.