CafeQuest is a location-based cafe discovery web application that helps coffee lovers find nearby cafes using real-time data from OpenStreetMap. Built with Next.js 15 and Firebase, it features an interactive Mapbox map, smart filtering options, and the ability to save favorite cafes to a personal dashboard.
- πΊοΈ Interactive Mapbox Map with custom cafe markers and real-time user location
- π Google Places Autocomplete for intelligent location search
- π― Smart Filtering - Hide chains (Tim Hortons, Starbucks) and find late-night cafes (open β₯ 9pm)
- πΎ Personal Dashboard with Firebase Firestore to save and manage favorite cafes
- π Secure Authentication with Firebase Auth and protected routes
- π± Responsive Design with mobile-optimized navigation
- β‘ Performance Optimized with API request caching and rate limiting
- π Location Search β Google Places autocomplete with fallback to Nominatim API
- πΊοΈ Mapbox Integration β Interactive map powered by Mapbox GL JS and react-map-gl
- π GPS Location β Automatic user location detection with geolocation API
- β Real-time Cafe Data β Fetches cafes from OpenStreetMap via Overpass API (5km radius)
- π Smart Filters:
- Hide Tim Hortons
- Hide Starbucks
- Show only late-night cafes (open β₯ 9pm)
- πΎ Save Cafes β Bookmark cafes with name, address, and opening hours
- ποΈ Manage Favorites β Delete cafes from your saved list
- π Cafe Details β View address, opening hours, and link to Google Maps
- π Protected Routes β Dashboard and profile require authentication
- π¨ Chakra UI β Modern component library with dark mode support
- β‘ API Optimization:
- Request caching (30-minute expiration)
- Rate limiting (1 request/second)
- Debounced search input (400ms)
- π Toast Notifications β User feedback for all actions
- π± Responsive UI β Mobile menu with Avatar dropdown
- π Loading States β Spinners for async operations
- π₯ Firebase Integration:
- Email/password authentication
- Firestore for user data and saved cafes
- Security rules for data protection
- π Vercel Analytics β Built-in analytics tracking
- Next.js 15 β React framework with App Router
- React 18 β UI library
- Chakra UI β Component library with built-in dark mode
- Mapbox GL JS + react-map-gl β Interactive maps
- react-icons β Icon library (FaHeart for save button)
- Custom Fonts β Geist Sans & Geist Mono (local fonts)
- Firebase Auth β User authentication (email/password)
- Firestore β NoSQL database for user profiles and saved cafes
- Google Places API β Location autocomplete
- Nominatim API β Fallback geocoding service
- Overpass API β Query OpenStreetMap for cafe data
- Mapbox API β Map tiles and rendering
- Vercel Analytics β Usage tracking
- axios β HTTP client for API requests
- lodash.debounce β Debounce search input
- use-places-autocomplete β Google Places autocomplete hook
- Jest β Testing framework
- @testing-library/react β Component testing
- Babel β JavaScript compiler for tests
- ESLint β Code linting
- Node.js 18+ (Download)
- Firebase Project with Firestore and Authentication enabled (Setup Guide)
- Google Maps API Key with Places API enabled (Get API Key)
- Mapbox Access Token (Sign up)
- Clone the repository
git clone https://github.com/imRanDan/cafequest.git
cd cafequest- Install dependencies
npm install- Configure environment variables
Create a .env.local file in the root directory:
# Firebase Configuration
NEXT_PUBLIC_FIREBASE_API_KEY=your_firebase_api_key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_project_id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_project.appspot.com
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=your_measurement_id
# Google Maps API Key
NEXT_PUBLIC_GOOGLE_API_KEY=your_google_maps_api_key
# Mapbox Access Token
NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN=your_mapbox_token- Set up Firebase Firestore Security Rules
In your Firebase Console, navigate to Firestore Database > Rules and add:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// User documents
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
// Saved cafes subcollection
match /savedCafes/{cafeId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
// Visited cafes subcollection (passport)
match /visitedCafes/{cafeId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
// Cafe votes collection - community voting system
match /cafeVotes/{cafeId} {
// Allow anyone to read votes (for displaying aggregated results)
allow read: if true;
// Votes subcollection
match /votes/{userId} {
// Users can read all votes (for aggregation)
allow read: if true;
// Users can only write their own vote
allow create, update: if request.auth != null && request.auth.uid == userId;
// Users can delete their own vote
allow delete: if request.auth != null && request.auth.uid == userId;
}
}
}
}-
Enable Authentication in Firebase
- Go to Firebase Console > Authentication
- Enable "Email/Password" sign-in method
-
Run the development server
npm run devOpen http://localhost:3000 in your browser.
Run the test suite:
npm testCurrent test coverage includes:
Map.test.jsxβ Map component rendering and interactionsSearchBar.test.jsxβ Search functionality
cafequest/
βββ src/
β βββ app/ # Next.js App Router pages
β β βββ dashboard/ # User dashboard (protected)
β β β βββ page.jsx # Displays saved cafes as cards
β β βββ profile/ # User profile (protected)
β β β βββ page.jsx # User info and logout
β β βββ login/ # Login page
β β β βββ page.jsx # Email/password login
β β βββ signup/ # Sign up page
β β β βββ page.jsx # User registration with Firestore
β β βββ layout.js # Root layout with Navbar, Footer, Providers
β β βββ page.js # Homepage with map and filters
β β βββ globals.css # Global styles
β βββ components/ # React components
β β βββ Map.jsx # Mapbox map with markers & popups
β β βββ CafeCard.jsx # Cafe card for dashboard
β β βββ LocationSearchInput.jsx # Google Places autocomplete
β β βββ Navbar.jsx # Navigation with auth state
β β βββ Footer.jsx # Footer component
β β βββ LoadingSpinner.jsx # Loading indicator
β β βββ ... # Other UI components
β βββ config/ # Configuration files
β β βββ firebase.js # Firebase initialization
β βββ utils/ # Utility functions
β β βββ AuthProvider.js # Auth context provider
β β βββ ThemeProvider.js # Theme context provider
β βββ providers/ # Context providers
β β βββ Providers.jsx # Combines all providers
β βββ styles/ # Additional styles
βββ images/ # Screenshots
βββ jest.config.js # Jest configuration
βββ jest.setup.js # Jest setup file
βββ package.json # Dependencies
βββ README.md
- User types in the search box (powered by Google Places autocomplete)
- User selects a location or clicks "Search"
- Location is geocoded to latitude/longitude
- Overpass API fetches cafes within 5km radius
- Results are cached for 30 minutes
- Markers appear on the Mapbox map
- Hide Tim Hortons/Starbucks: Filters by cafe name
- Open Late: Parses
opening_hourstag from OSM data, excludes cafes closing before 9pm
- User clicks marker on map β popup appears
- User clicks "Save" button
- Checks if user is logged in (Firebase Auth)
- Saves to Firestore:
users/{userId}/savedCafes/{cafeId} - Toast notification confirms save
- Cafe appears on dashboard
-
Browse Cafes
- Visit homepage
- Allow location access or search for a city/postal code
- Click "Show cafes near me" or use the search bar
-
Filter Results
- Toggle switches to hide Tim Hortons or Starbucks
- Enable "Open late" to find cafes open past 9pm
-
Create Account
- Click "Sign Up"
- Enter full name, email, and password
- Account is created in Firebase
-
Save Cafes
- Click any cafe marker on the map
- View details in the popup
- Click "Save" (requires login)
- Access saved cafes from Dashboard
-
Manage Favorites
- Navigate to Dashboard
- View all saved cafes as cards
- Click "Delete" to remove
- Mapbox integration with custom markers
- Google Places autocomplete search
- GPS location detection
- Smart filters (chains, late-night)
- User authentication with Firebase
- Save cafes to Firestore
- User dashboard with cafe cards
- Delete saved cafes
- Responsive mobile design
- API caching and rate limiting
- Search/filter within saved cafes
- Cafe photos from Google Places API
- User reviews and ratings
- Share cafes with friends
- PWA support for offline access
- Email verification
- Password reset functionality
Contributions are welcome! Please follow these steps:
- Fork the project
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Distributed under the MIT License. See LICENSE for more information.
Danyal Imran
- Portfolio: danyalimran.com
- GitHub: @imRanDan
- LinkedIn: Danyal Imran
- Next.js β React framework
- Chakra UI β Component library
- Mapbox β Map tiles and API
- OpenStreetMap β Cafe data source
- Firebase β Authentication and database
- Google Maps Platform β Places API
- Vercel β Deployment and hosting
This project implements several optimizations:
- Caching: API responses cached for 30 minutes
- Rate Limiting: Max 1 request per second to Overpass API
- Debouncing: Search input debounced to 400ms
- Request Limiting: Display limit of 10 markers initially, loads more on map movement
Made with β by Danyal Imran
β Star this repo if you found it helpful!


