A web application that sends daily sunrise notifications with weather conditions and a confidence score for optimal sunrise watching at Lamai Beach, Koh Samui, Thailand.
- Daily Notifications: Automated alerts at 4:45 AM Thailand time
- Weather Integration: Real-time weather data from OpenWeatherMap API
- Sunrise Scoring: Intelligent algorithm scoring sunrise quality (0-100) based on:
- Cloud coverage (ideal: 20-40% for dramatic sunrises)
- Visibility conditions
- Weather patterns
- Google Authentication: Simple sign-in with Google
- Progressive Web App: Installable on mobile devices
- Minimalist UI: Clean, focused user experience
- Frontend: Next.js 14 (React) + TypeScript
- Backend: Firebase Cloud Functions (Node.js 20)
- Database: Cloud Firestore
- Authentication: Firebase Auth (Google provider)
- Notifications: Firebase Cloud Messaging (FCM)
- Hosting: Firebase Hosting
- Weather API: OpenWeatherMap
sunrise_alarm/
├── functions/ # Firebase Cloud Functions
│ ├── src/
│ │ ├── index.ts # Main entry point & scheduled function
│ │ ├── weather.ts # Weather fetching & scoring logic
│ │ └── notifications.ts # FCM notification handling
│ └── package.json
├── frontend/ # Next.js web application
│ ├── app/
│ │ ├── page.tsx # Main page component
│ │ ├── layout.tsx # Root layout
│ │ └── globals.css # Global styles
│ ├── lib/
│ │ ├── firebase.ts # Firebase initialization
│ │ └── notifications.ts # FCM token management
│ └── public/ # Static assets
├── firebase.json # Firebase configuration
├── firestore.rules # Firestore security rules
└── package.json # Root workspace config
- Node.js 20 or higher
- npm or yarn
- Firebase CLI (
npm install -g firebase-tools) - Firebase project with Blaze (pay-as-you-go) plan for Cloud Functions
- OpenWeatherMap API key (free tier available)
-
Create a new Firebase project at Firebase Console
-
Enable the following services:
- Authentication: Enable Google sign-in provider
- Firestore Database: Create in production mode
- Cloud Functions: Upgrade to Blaze plan
- Hosting: Enable Firebase Hosting
- Cloud Messaging: Enable FCM
-
Generate a web app configuration:
- Go to Project Settings > General
- Under "Your apps", click "Add app" and select Web
- Register your app and copy the config object
-
Generate VAPID key for FCM:
- Go to Project Settings > Cloud Messaging
- Under "Web Push certificates", click "Generate key pair"
- Copy the key pair value
- Sign up at OpenWeatherMap
- Subscribe to the free tier (60 calls/minute)
- Copy your API key from the API keys section
- Clone and install dependencies:
git clone <your-repo-url>
cd sunrise_alarm
npm install- Login to Firebase:
firebase login
firebase initSelect your Firebase project when prompted.
- Configure environment variables:
Frontend (frontend/.env.local):
cp frontend/.env.local.example frontend/.env.localEdit frontend/.env.local with your Firebase config:
NEXT_PUBLIC_FIREBASE_API_KEY=your-api-key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your-project-id.firebaseapp.com
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your-project-id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your-project-id.appspot.com
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your-sender-id
NEXT_PUBLIC_FIREBASE_APP_ID=your-app-id
NEXT_PUBLIC_FIREBASE_VAPID_KEY=your-vapid-keyFunctions (functions/.env):
cp functions/.env.example functions/.envEdit functions/.env:
OPENWEATHER_API_KEY=your-openweather-api-key
LATITUDE=9.4631
LONGITUDE=100.0569
LOCATION_NAME=Lamai Beach, Koh SamuiSet Firebase Functions environment variables:
firebase functions:config:set \
openweather.api_key="your-api-key" \
location.latitude="9.4631" \
location.longitude="100.0569" \
location.name="Lamai Beach, Koh Samui"- Update Service Worker config:
Edit frontend/public/firebase-messaging-sw.js with your Firebase config.
firebase deploy --only firestore:rulesRun frontend locally:
cd frontend
npm run devVisit http://localhost:3000
Test Cloud Functions locally:
cd functions
npm run serveManual trigger for testing:
# After deploying functions
curl https://asia-southeast1-<your-project-id>.cloudfunctions.net/triggerSunriseNotificationDeploy everything:
npm run deployOr deploy individually:
# Deploy functions only
firebase deploy --only functions
# Deploy frontend only
cd frontend && npm run build && cd ..
firebase deploy --only hosting- Scheduled Trigger: Cloud Scheduler triggers the function daily at 4:45 AM Thailand time
- Weather Fetch: Function calls OpenWeatherMap API for current conditions
- Score Calculation: Algorithm evaluates:
- Cloud coverage (20-40% is ideal for dramatic sunrises)
- Visibility (higher is better)
- Weather conditions (clear/cloudy preferred over rain)
- User Retrieval: Fetches all users with notifications enabled from Firestore
- Notification Dispatch: Sends FCM messages to all registered devices
- Token Cleanup: Removes invalid/expired FCM tokens
The algorithm calculates a 0-100 score weighted as follows:
- 50% Cloud coverage (ideal: 20-40% for colorful sunrises)
- 30% Visibility conditions
- 20% Weather type (clear/cloudy vs rain/fog)
Ratings:
- Excellent (85-100): Perfect conditions
- Good (70-84): Great viewing conditions
- Fair (50-69): Decent sunrise possible
- Poor (<50): Likely obscured
users/{userId}
- fcmToken: string
- notificationsEnabled: boolean
- updatedAt: timestampweather/{documentId}
- timestamp: timestamp
- weather: {
temperature: number,
cloudCoverage: number,
visibility: number,
...
}
- sunriseScore: {
score: number,
rating: string,
factors: {...}
}Edit functions/src/index.ts:
.schedule("45 4 * * *") // Format: "minute hour * * *"
.timeZone("Asia/Bangkok")Edit functions/.env or Firebase Functions config:
LATITUDE=your-latitude
LONGITUDE=your-longitude
LOCATION_NAME=Your LocationEdit functions/src/weather.ts in the calculateSunriseScore() function to adjust weights and thresholds.
- Check browser notification permissions
- Verify VAPID key is correct in frontend config
- Check FCM token is saved in Firestore
- Verify service worker is registered (
firebase-messaging-sw.js) - Check Cloud Functions logs:
firebase functions:log
- Ensure Blaze plan is enabled
- Check Node.js version is 20
- Verify all environment variables are set
- Run
cd functions && npm run buildto check for TypeScript errors
- Verify OpenWeatherMap API key is valid
- Check you haven't exceeded API rate limits (60 calls/min free tier)
- Review Cloud Functions logs for API errors
With typical usage (1-100 users):
- Firebase Hosting: Free tier sufficient
- Cloud Functions: ~$0.10/month (1 invocation/day)
- Firestore: Free tier sufficient
- FCM: Free (unlimited notifications)
- OpenWeatherMap: Free tier (60 calls/min)
Total: Essentially free for small user base
Contributions are welcome! Please feel free to submit issues or pull requests.
MIT License - feel free to use this project for your own sunrise notifications!
- Weather data provided by OpenWeatherMap
- Built with Firebase
- Designed for the beautiful sunrises at Lamai Beach, Koh Samui, Thailand