The Palos Publishing Company

Follow Us On The X Platform @PalosPublishing
Categories We Write About

Build a location-based reminder app

Here’s a complete implementation guide for a Location-Based Reminder App using React Native with Expo, Firebase, and background location tracking.


Overview

The app allows users to:

  • Set reminders based on location.

  • Get notified when they enter or exit a specific area.

  • View, edit, and delete saved reminders.


Tech Stack

  • Frontend: React Native (with Expo)

  • Database: Firebase Firestore

  • Notifications & Location: Expo SDK


1. Setup Project

bash
npx create-expo-app location-reminder-app cd location-reminder-app npx expo install expo-location expo-notifications firebase react-native-maps

2. Firebase Configuration

js
// firebaseConfig.js import { initializeApp } from 'firebase/app'; import { getFirestore } from 'firebase/firestore'; const firebaseConfig = { apiKey: "YOUR-API-KEY", authDomain: "YOUR-AUTH-DOMAIN", projectId: "YOUR-PROJECT-ID", storageBucket: "YOUR-STORAGE-BUCKET", messagingSenderId: "YOUR-MESSAGE-SENDER-ID", appId: "YOUR-APP-ID" }; const app = initializeApp(firebaseConfig); export const db = getFirestore(app);

3. Permissions Utility

js
// utils/permissions.js import * as Location from 'expo-location'; import * as Notifications from 'expo-notifications'; export async function requestPermissions() { const { status: locationStatus } = await Location.requestForegroundPermissionsAsync(); const { status: backgroundStatus } = await Location.requestBackgroundPermissionsAsync(); const { status: notifStatus } = await Notifications.requestPermissionsAsync(); return locationStatus === 'granted' && backgroundStatus === 'granted' && notifStatus === 'granted'; }

4. Reminder Data Structure

js
// types/Reminder.js export const Reminder = { id: String, title: String, latitude: Number, longitude: Number, radius: Number, triggerOn: 'enter' | 'exit', };

5. Add Reminder Component

js
// components/AddReminder.js import React, { useState } from 'react'; import { View, TextInput, Button, StyleSheet } from 'react-native'; import { db } from '../firebaseConfig'; import { collection, addDoc } from 'firebase/firestore'; export default function AddReminder({ location }) { const [title, setTitle] = useState(''); const addReminder = async () => { await addDoc(collection(db, 'reminders'), { title, latitude: location.latitude, longitude: location.longitude, radius: 100, triggerOn: 'enter', }); setTitle(''); }; return ( <View style={styles.container}> <TextInput placeholder="Reminder title" value={title} onChangeText={setTitle} style={styles.input} /> <Button title="Add Reminder" onPress={addReminder} /> </View> ); } const styles = StyleSheet.create({ container: { padding: 10 }, input: { borderBottomWidth: 1, marginBottom: 10, padding: 8, }, });

6. Background Location Task

js
// background/LocationTask.js import * as TaskManager from 'expo-task-manager'; import * as Location from 'expo-location'; import * as Notifications from 'expo-notifications'; import { db } from '../firebaseConfig'; import { collection, getDocs } from 'firebase/firestore'; const LOCATION_TASK = 'background-location-task'; TaskManager.defineTask(LOCATION_TASK, async ({ data, error }) => { if (error) return; const { locations } = data; const location = locations[0]; const snapshot = await getDocs(collection(db, 'reminders')); snapshot.forEach(async (doc) => { const reminder = doc.data(); const distance = getDistanceFromLatLonInMeters( location.coords.latitude, location.coords.longitude, reminder.latitude, reminder.longitude ); if (distance <= reminder.radius) { await Notifications.scheduleNotificationAsync({ content: { title: 'Location Reminder', body: reminder.title, }, trigger: null, }); } }); }); export async function startLocationTask() { const hasStarted = await Location.hasStartedLocationUpdatesAsync(LOCATION_TASK); if (!hasStarted) { await Location.startLocationUpdatesAsync(LOCATION_TASK, { accuracy: Location.Accuracy.Highest, timeInterval: 60000, distanceInterval: 50, showsBackgroundLocationIndicator: true, foregroundService: { notificationTitle: "Location Reminder", notificationBody: "Tracking your location in the background.", }, }); } } function getDistanceFromLatLonInMeters(lat1, lon1, lat2, lon2) { const R = 6371e3; const φ1 = lat1 * (Math.PI / 180); const φ2 = lat2 * (Math.PI / 180); const Δφ = (lat2 - lat1) * (Math.PI / 180); const Δλ = (lon2 - lon1) * (Math.PI / 180); const a = Math.sin(Δφ / 2) ** 2 + Math.cos1) * Math.cos2) * Math.sin(Δλ / 2) ** 2; const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); return R * c; }

7. Home Screen

js
// App.js import React, { useEffect, useState } from 'react'; import { View, StyleSheet, Alert } from 'react-native'; import MapView, { Marker } from 'react-native-maps'; import * as Location from 'expo-location'; import AddReminder from './components/AddReminder'; import { requestPermissions } from './utils/permissions'; import { startLocationTask } from './background/LocationTask'; export default function App() { const [location, setLocation] = useState(null); useEffect(() => { (async () => { const granted = await requestPermissions(); if (!granted) { Alert.alert('Permissions not granted'); return; } const loc = await Location.getCurrentPositionAsync({}); setLocation(loc.coords); await startLocationTask(); })(); }, []); if (!location) return null; return ( <View style={styles.container}> <MapView style={styles.map} initialRegion={{ latitude: location.latitude, longitude: location.longitude, latitudeDelta: 0.01, longitudeDelta: 0.01, }} > <Marker coordinate={location} /> </MapView> <AddReminder location={location} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1 }, map: { flex: 1 }, });

8. Final Notes

  • Background Tasks require production builds on iOS and Android (use Expo Dev Client or eject to bare workflow).

  • Be sure to set appropriate permissions in app.json or AndroidManifest.xml.

  • Fine-tune notification frequency and distance sensitivity to optimize battery usage.


This basic implementation can be extended with:

  • User authentication

  • Repeating reminders

  • Custom trigger radius

  • Push notification scheduling

Let me know if you want advanced features like geofencing using native modules.

Share this Page your favorite way: Click any app below to share.

Enter your email below to join The Palos Publishing Company Email List

We respect your email privacy

Categories We Write About