# Time Safari Push Notification Middleware Server A custom-built push notification middleware service designed specifically for the Time Safari application. This server acts as an intermediary layer between the Time Safari client applications and various push notification providers, providing a unified interface for managing push subscriptions and delivering notifications. ## Project Intent The primary goal of this project was to build our own middleware service for push notifications rather than relying on third-party services. This approach provides several benefits: - **Complete Control**: Full ownership over the notification delivery pipeline - **Customization**: Ability to implement Time Safari-specific notification logic - **Privacy**: No dependency on external services that might collect user data - **Cost Efficiency**: Eliminates per-notification costs from third-party providers - **Reliability**: Direct control over uptime and performance ## Architecture Overview The server is built using Node.js with TypeScript and follows a modular architecture: ``` ┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐ │ Client Apps │───▶│ Push Server │───▶│ Push Providers │ │ (Time Safari) │ │ (Middleware) │ │ (FCM, etc.) │ └─────────────────┘ └──────────────────┘ └─────────────────┘ │ ▼ ┌──────────────────┐ │ SQLite DB │ │ (Subscriptions) │ └──────────────────┘ ``` ### Core Components - **Subscription Management**: Handles client subscription registration and storage - **VAPID Key Management**: Generates and manages VAPID keys for secure push delivery - **Notification Service**: Encrypts and delivers push notifications to subscribed clients - **Worker Thread**: Handles periodic tasks (currently sends daily notifications) - **Database Layer**: SQLite-based storage for subscriptions and VAPID keys ## Features ### 🔐 Secure Push Delivery - VAPID (Voluntary Application Server Identification) key generation and management - End-to-end encryption using AES-128-GCM - JWT-based authentication headers ### 📱 Subscription Management - Client subscription registration via `/subscribe` endpoint - Subscription storage in SQLite database - Support for subscription muting (planned) - Subscription removal (planned) ### ⚡ Real-time Notifications - Broadcast notifications to all subscribed clients - Individual client notification delivery - Automatic daily notification scheduling via worker thread ### 🛠️ Developer-Friendly - TypeScript for type safety - Comprehensive logging - Modular service architecture - Docker support for containerization ## Technology Stack - **Runtime**: Node.js 18.12+ - **Language**: TypeScript - **Framework**: Express.js - **Database**: SQLite with TypeORM - **Encryption**: http_ece, elliptic, crypto - **Authentication**: JWT (JSON Web Tokens) - **Containerization**: Docker ## Setup and Installation ### Prerequisites - Node.js 18.12 or higher - npm 8.0 or higher ### Quick Start with Tea (Recommended) ```bash # Install Tea package manager sh <(curl tea.xyz) -E sh # Install dependencies npm install # Build the project npm run build # Start the server npm run start ``` ### Manual Setup ```bash # Clone the repository git clone cd pwa-push-server # Install dependencies npm install # Build TypeScript npm run build # Start the server npm run start ``` The server will start on `http://localhost:3000` ### Docker Setup ```bash # Build the Docker image docker build -t timesafari-push-server . # Run the container docker run -p 3000:3000 timesafari-push-server ``` ## API Endpoints ### POST `/subscribe` Register a new push subscription. **Request Body:** ```json { "endpoint": "https://fcm.googleapis.com/fcm/send/...", "keys": { "p256dh": "base64-encoded-public-key", "auth": "base64-encoded-auth-secret" } } ``` **Response:** `201 Created` ### GET `/vapid` Retrieve the public VAPID key for client-side subscription. **Response:** ```json { "vapidKey": "base64-encoded-public-vapid-key" } ``` ### POST `/unsubscribe` (Planned) Remove a push subscription. ### POST `/mute` (Planned) Toggle notification muting for a subscription. ## Client Integration ### 1. Request VAPID Key ```javascript const response = await fetch('/vapid'); const { vapidKey } = await response.json(); ``` ### 2. Subscribe to Push Notifications ```javascript const registration = await navigator.serviceWorker.ready; const subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: vapidKey }); await fetch('/subscribe', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(subscription) }); ``` ### 3. Handle Push Notifications ```javascript // In your service worker self.addEventListener('push', (event) => { const data = event.data.json(); const options = { title: data.title, body: data.body, icon: '/icon.png', badge: '/badge.png' }; event.waitUntil( self.registration.showNotification(data.title, options) ); }); ``` ## Development ### Available Scripts - `npm run build` - Build the TypeScript project - `npm run start` - Start the production server - `npm run test` - Run tests with coverage - `npm run lint` - Run ESLint - `npm run prettier` - Format code with Prettier ### Project Structure ``` src/ ├── main.ts # Server entry point and Express setup ├── notificationService.ts # Push notification delivery logic ├── subscriptionService.ts # Subscription management ├── vapidService.ts # VAPID key generation and management ├── db.ts # Database service and TypeORM setup ├── worker.ts # Background worker for periodic tasks ├── Subscription.ts # Subscription entity model └── VapidKeys.ts # VAPID keys entity model ``` ## Security Considerations - **VAPID Keys**: Automatically generated and securely stored - **Encryption**: All push payloads are encrypted using AES-128-GCM - **Authentication**: JWT-based VAPID authentication headers - **Database**: SQLite with proper entity validation - **Input Validation**: TypeScript provides compile-time type safety ## Monitoring and Logging The server includes comprehensive logging for: - Subscription events (add/remove) - Notification delivery attempts - VAPID key operations - Database operations - Worker thread activities ## Future Enhancements - [ ] Subscription muting functionality - [ ] Subscription removal endpoint - [ ] Notification templates - [ ] Delivery analytics and metrics - [ ] Rate limiting and throttling - [ ] Multi-tenant support - [ ] Webhook support for external integrations ## Contributing 1. Fork the repository 2. Create a feature branch 3. Make your changes following the coding standards 4. Add tests for new functionality 5. Submit a pull request ## License Apache-2.0 License - see [LICENSE](LICENSE) file for details. ## Author **Matthew Raymer** - Lead Developer --- *This middleware service was built specifically for Time Safari to provide reliable, secure, and cost-effective push notification delivery without dependency on third-party services.* **Last Updated:** 2025-07-23 **Project Started:** 2023-09-06