You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
Matthew Raymer ecc2f809bc docs: Add comprehensive JSDoc documentation to all source files 1 week ago
src docs: Add comprehensive JSDoc documentation to all source files 1 week ago
.eslintrc.json Updates but not quite ready to test 2 years ago
.gitignore Updates but not quite ready to test 2 years ago
Dockerfile Successful build but does it run? 2 years ago
LICENSE Add Typescript boilerplate 2 years ago
README.md docs: Add comprehensive JSDoc documentation to all source files 1 week ago
jest.config.js Add Typescript boilerplate 2 years ago
package-lock.json Checkpoint: Problem with worker metdata for VapidKeys 2 years ago
package.json TypeORM instead of direct Sqlite 2 years ago
push_server Resolve problem with creating a VAPID at initial startup 2 years ago
tsconfig.json Rewrite reducing crypto complexity 2 years ago
tsconfig.release.json Rewrite reducing crypto complexity 2 years ago

README.md

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
# 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

# Clone the repository
git clone <repository-url>
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

# 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:

{
  "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:

{
  "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

const response = await fetch('/vapid');
const { vapidKey } = await response.json();

2. Subscribe to Push Notifications

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

// 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 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