A minimal web app that tracks the current year's progress and sends push notifications when each percent is completed. Built with React PWA frontend and Azure Functions serverless backend.
Install as a Progressive Web App (PWA) for the best experience:
- Visit https://puneetk.dev in Brave or Chrome
- Tap the menu (⋮) → "Add to Home screen" or "Install app"
- Tap "Install" or "Add"
- Open the app from your home screen
- Enable notifications when prompted
- Visit https://puneetk.dev in Safari
- Tap the Share button (□↑)
- Scroll down and tap "Add to Home Screen"
- Tap "Add"
- Open the app from your home screen
- Enable notifications when prompted
Note: On iOS, notifications only work when the app is installed to the home screen (PWA mode), not in regular Safari.
Time passes irreversibly. This app tracks how much of the current year is already gone and notifies you only when another 1% is completed. No gamification, no social features—just cold, factual awareness.
- Real-time Progress: View current year completion percentage
- Smart Notifications: Get notified only when crossing whole percent thresholds
- Timezone-Aware: Accurate calculations based on your timezone
- Minimal Design: Black, white, grey—nothing more
- PWA: Works offline, installable on any device
- Privacy-First: No tracking, no unnecessary data collection
- React + Vite: Fast, modern build tooling
- Tailwind CSS: Minimal, utility-first styling
- PWA: Service worker, offline support, installable
- Web Push API: Native browser notifications
- Azure Functions: Serverless, pay-per-execution
- MongoDB Atlas: Free tier database (M0 cluster)
- Web Push (VAPID): Push notification delivery
- Node.js: Runtime environment
- Timer Trigger (
checkYearProgress): Runs hourly, checks all users, sends notifications - GET
/api/progress: Returns current year progress for any timezone - POST
/api/subscribe: Registers push subscription - PUT
/api/settings: Updates user preferences (timezone, notifications)
gone/
├── frontend/ # React PWA
│ ├── src/
│ │ ├── components/ # React components
│ │ ├── services/ # API & push notification services
│ │ ├── utils/ # Helper functions
│ │ ├── App.jsx # Main app component
│ │ └── main.jsx # Entry point
│ ├── public/
│ │ └── icons/ # PWA icons
│ ├── vite.config.js # Vite + PWA config
│ └── package.json
│
├── backend/ # Azure Functions
│ ├── checkYearProgress/ # Timer trigger function
│ ├── getCurrentProgress/ # HTTP: GET progress
│ ├── registerPushSubscription/ # HTTP: POST subscribe
│ ├── updateSettings/ # HTTP: PUT settings
│ ├── shared/ # Shared utilities
│ │ ├── database.js # MongoDB connection
│ │ ├── yearProgress.js # Progress calculations
│ │ └── pushService.js # Push notifications
│ ├── host.json
│ └── package.json
│
└── .github/workflows/ # CI/CD
└── deploy.yml
- Node.js 18+
- Azure Functions Core Tools (v4)
- MongoDB Atlas account (free tier)
- VAPID keys for push notifications
npx web-push generate-vapid-keysSave the output—you'll need both public and private keys.
- Create free M0 cluster at mongodb.com/cloud/atlas
- Create database user with read/write permissions
- Whitelist your IP address (or
0.0.0.0/0for development) - Get connection string (replace
<password>with your password)
cd backend
npm installCreate local.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "node",
"MONGODB_URI": "mongodb+srv://user:pass@cluster.mongodb.net/gone",
"VAPID_PUBLIC_KEY": "YOUR_PUBLIC_KEY",
"VAPID_PRIVATE_KEY": "YOUR_PRIVATE_KEY",
"VAPID_SUBJECT": "mailto:your-email@example.com"
}
}Start backend:
npm start
# Backend runs on http://localhost:7071cd frontend
npm installCreate .env:
VITE_API_BASE_URL=http://localhost:7071/api
VITE_VAPID_PUBLIC_KEY=YOUR_PUBLIC_KEYStart frontend:
npm run dev
# Frontend runs on http://localhost:3000# Login to Azure
az login
# Create resource group
az group create --name gone-rg --location eastus
# Create Function App (Consumption plan)
az functionapp create \
--resource-group gone-rg \
--consumption-plan-location eastus \
--runtime node \
--runtime-version 18 \
--functions-version 4 \
--name gone-functions \
--storage-account gonefunctionsstorage
# Create Static Web App
az staticwebapp create \
--name gone-app \
--resource-group gone-rg \
--location eastus \
--source https://github.com/YOUR_USERNAME/gone \
--branch main \
--app-location "/frontend" \
--output-location "dist"az functionapp config appsettings set \
--name gone-functions \
--resource-group gone-rg \
--settings \
MONGODB_URI="your_mongodb_connection_string" \
VAPID_PUBLIC_KEY="your_public_key" \
VAPID_PRIVATE_KEY="your_private_key" \
VAPID_SUBJECT="mailto:your-email@example.com"Add these secrets to your GitHub repository (Settings > Secrets and variables > Actions):
AZURE_STATIC_WEB_APPS_API_TOKEN: From Static Web App deployment tokenAZURE_FUNCTIONAPP_NAME:gone-functionsAZURE_FUNCTIONAPP_PUBLISH_PROFILE: Download from Azure PortalVITE_API_BASE_URL:https://gone-functions.azurewebsites.net/apiVITE_VAPID_PUBLIC_KEY: Your VAPID public key
Push to main branch—GitHub Actions will automatically deploy both frontend and backend.
cd backend
node -e "
const { getYearProgressData } = require('./shared/yearProgress.js');
console.log(getYearProgressData('Asia/Kolkata', 2026));
"Use a tool like Pushpad or curl to test the /api/subscribe endpoint.
- Landing page loads with correct copy
- "Enable Notifications" requests permission
- Permission granted → redirects to dashboard
- Dashboard shows correct progress percentage
- Progress bar fills to correct width
- All metrics display correctly (days passed/remaining, next notification %)
- Settings panel opens and closes
- Timezone can be updated
- Notifications can be toggled
- PWA can be installed
- App works offline
- Notification arrives when threshold crossed (wait or test with modified backend)
Azure Functions (Consumption Plan)
- ~3.65 million executions/year (1 user, hourly checks)
- First 1M executions free
- Cost: $0/month for <100 users
Azure Static Web Apps
- Free tier: 100GB bandwidth, custom domains
- Cost: $0/month
MongoDB Atlas
- M0 cluster: 512MB storage, shared CPU
- Cost: $0/month
Total: ~$0/month for MVP (scales affordably)
- CORS restricted to frontend domain only
- Rate limiting recommended (Azure API Management)
- VAPID keys stored in Azure Key Vault (production)
- MongoDB connection uses TLS encryption
- No PII collected beyond timezone and push subscription
- Application Insights for Azure Functions (included)
- Monitor notification delivery success rates
- Track expired subscriptions cleanup
- Alert on function failures
- Ensure HTTPS (use
localhostor ngrok) - Check browser console for service worker errors
- Verify VAPID keys match in frontend and backend
- Test with browser's push notification tester
- Check
checkYearProgress/function.jsoncron expression - Verify function app is running (not stopped)
- Check Application Insights for errors
- Ensure MongoDB connection is valid
- Verify timezone is valid IANA format
- Check leap year logic (2024, 2028, etc.)
- Test with known dates and timezones
This is a minimal, focused app. Contributions welcome for:
- Bug fixes
- Performance improvements
- Security enhancements
Not accepting:
- Gamification features
- Social features
- Motivational copy changes
- Unnecessary complexity
Got a random idea one day and decided to build it. Thought others might find it useful too.
MIT