Skip to content

Latest commit

Β 

History

History
1153 lines (926 loc) Β· 34.7 KB

File metadata and controls

1153 lines (926 loc) Β· 34.7 KB

OpenSpec Instructions

These instructions are for AI assistants working in this project.

Always open @/openspec/AGENTS.md when the request:

  • Mentions planning or proposals (words like proposal, spec, change, plan)
  • Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
  • Sounds ambiguous and you need the authoritative spec before coding

Use @/openspec/AGENTS.md to learn:

  • How to create and apply change proposals
  • Spec format and conventions
  • Project structure and guidelines

Keep this managed block so 'openspec update' can refresh the instructions.

ChaseApp Codebase Analysis & Strategic Development Guide

Executive Summary

ChaseApp is a sophisticated real-time notification and chat platform for live police chases, rocket launches, weather events, and disasters. The codebase represents a modern multi-platform application with three main components:

  1. Web Application (web/) - Nuxt.js/Vue.js frontend with TypeScript
  2. Mobile Application (mobile/) - Flutter cross-platform app
  3. Backend Services (api/) - Mixed Node.js and Go serverless functions

This document provides a comprehensive analysis of the current architecture, Bazel migration strategy, and recommendations for future development including the feasibility of an Elixir rewrite.


Repository Structure Analysis

Current Architecture

chaseapp/
β”œβ”€β”€ web/                        # Vue.js/Nuxt.js frontend
β”‚   β”œβ”€β”€ components/            # Vue components
β”‚   β”‚   β”œβ”€β”€ cards/            # Content cards
β”‚   β”‚   β”œβ”€β”€ chat/             # Chat functionality
β”‚   β”‚   β”œβ”€β”€ birds/            # Aircraft tracking
β”‚   β”‚   β”œβ”€β”€ firehose/         # Real-time data feeds
β”‚   β”‚   β”œβ”€β”€ events/           # Event management
β”‚   β”‚   └── utils/            # Utility components
β”‚   β”œβ”€β”€ store/                # Vuex state management
β”‚   β”œβ”€β”€ types/                # TypeScript definitions
β”‚   β”œβ”€β”€ utils/                # Utility functions
β”‚   β”œβ”€β”€ nuxt.config.js        # Nuxt configuration
β”‚   └── package.json          # Dependencies
β”‚
β”œβ”€β”€ mobile/                   # Flutter mobile app
β”‚   β”œβ”€β”€ lib/                  # Dart source code
β”‚   β”œβ”€β”€ android/              # Android-specific code
β”‚   β”œβ”€β”€ ios/                  # iOS-specific code
β”‚   └── pubspec.yaml          # Flutter dependencies
β”‚
└── api/                      # Backend services
    β”œβ”€β”€ JavaScript Functions/ # Node.js Cloud Functions
    β”‚   β”œβ”€β”€ addUser/          # User management
    β”‚   β”œβ”€β”€ algoliaIndex/     # Search indexing
    β”‚   β”œβ”€β”€ chaseStats/       # Statistics tracking
    β”‚   β”œβ”€β”€ fcmMessaging/     # Firebase Cloud Messaging
    β”‚   β”œβ”€β”€ pusher/           # Pusher notifications
    β”‚   β”œβ”€β”€ rocketAPI/        # Rocket launch data
    β”‚   β”œβ”€β”€ updateChase/      # Chase data updates
    β”‚   └── weatherAPI/       # Weather data
    β”‚
    └── Go Functions/         # Go Cloud Functions
        β”œβ”€β”€ API/              # Main API service
        β”œβ”€β”€ bofTS/            # Birds of a Feather tracking
        β”œβ”€β”€ getStreams/       # Stream management
        └── pusher/           # Pusher notifications (Go)

Technology Stack Summary

Frontend Technologies

  • Web: Nuxt.js 2 (Edge) + Vue.js 3 + TypeScript 4.6.2
  • Mobile: Flutter 2.17.1 + Dart
  • Styling: TailwindCSS + WindiCSS
  • State Management: Vuex (Web), Riverpod (Mobile)
  • Real-time: Firebase RTDB, Stream Chat SDK, Pusher WebSocket
  • Mapping: Mapbox GL JS
  • Authentication: Firebase Auth

Backend Technologies

  • Runtimes: Node.js 16, Go 1.19
  • Database: Firestore + Firebase Realtime Database
  • Messaging: FCM, Pusher Notifications, Stream Chat
  • Search: Algolia v4
  • Deployment: Google Cloud Functions, Cloud Run

Bazel Migration Strategy

Why Bazel for ChaseApp?

ChaseApp's multi-language, multi-service architecture makes it an ideal candidate for Bazel:

  1. Complex Dependencies: Mixed Node.js/Go/Flutter ecosystem
  2. Incremental Builds: Only rebuild changed components
  3. Parallel Execution: Build web, mobile, and backend simultaneously
  4. Cross-language Dependencies: Shared types and utilities
  5. Scalability: As codebase grows, Bazel's performance advantages increase

Proposed Monorepo Structure

chaseapp-bazel/
β”œβ”€β”€ WORKSPACE                 # Bazel workspace configuration
β”œβ”€β”€ .bazelrc                  # Bazel flags and settings
β”œβ”€β”€ deps.bzl                  # External dependencies
β”œβ”€β”€ tools/                    # Build tools and configurations
β”‚   β”œβ”€β”€ build_rules/         # Custom Bazel rules
β”‚   └── scripts/             # Migration utilities
β”‚
β”œβ”€β”€ web/                      # Frontend application
β”‚   β”œβ”€β”€ src/                 # Source files
β”‚   β”œβ”€β”€ BUILD.bazel          # Web build config
β”‚   └── package.json         # Dependencies
β”‚
β”œβ”€β”€ mobile/                   # Flutter application
β”‚   β”œβ”€β”€ lib/                 # Dart source
β”‚   β”œβ”€β”€ BUILD.bazel          # Flutter build config
β”‚   └── pubspec.yaml         # Dependencies
β”‚
β”œβ”€β”€ backend/                  # Backend services
β”‚   β”œβ”€β”€ functions/           # Cloud functions
β”‚   β”‚   β”œβ”€β”€ js_functions/    # Node.js functions
β”‚   β”‚   └── go_functions/    # Go functions
β”‚   β”œβ”€β”€ BUILD.bazel          # Backend build config
β”‚   └── go.mod               # Go modules
β”‚
β”œβ”€β”€ shared/                   # Shared libraries
β”‚   β”œβ”€β”€ types/               # TypeScript definitions
β”‚   β”œβ”€β”€ protos/              # Protocol buffers
β”‚   β”œβ”€β”€ utils/               # Shared utilities
β”‚   └── BUILD.bazel          # Shared libraries build
β”‚
└── infrastructure/           # Deployment configs
    β”œβ”€β”€ docker/              # Docker configurations
    β”œβ”€β”€ terraform/           # Infrastructure as code
    └── cloudbuild/          # Cloud Build configs

Bazel Configuration Files

WORKSPACE

workspace(name = "chaseapp")

# Node.js rules
http_archive(
    name = "build_bazel_rules_nodejs",
    url = "https://github.com/bazelbuild/rules_nodejs/releases/download/5.8.0/rules_nodejs-5.8.0.tar.gz",
    sha256 = "698d0fb1c5aaae6641e3bc0e0c7154459b21e65a5a65f4ce4d6b1df66b7c77a2",
)

load("@build_bazel_rules_nodejs//:index.bzl", "node_repositories", "npm_install")

# Go rules
http_archive(
    name = "io_bazel_rules_go",
    url = "https://github.com/bazelbuild/rules_go/releases/download/v0.39.1/rules_go-v0.39.1.zip",
    sha256 = "7a9f20ff3bbd9525449c412f0ed32f7251a0e0449b3935463466c2b8c09d06e0",
)

load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_repository")

go_register_toolchains(version = "1.19")

# Flutter rules (custom or community)
load("//tools/build_rules:flutter", "flutter_repositories")

flutter_repositories()

# Load dependencies
load("//:deps.bzl", "deps")
deps()

# Node.js dependencies
npm_install(
    name = "npm",
    package_json = "//web:package.json",
    package_json_path = "web/package.json",
)

Web Application BUILD.bazel

load("@build_bazel_rules_nodejs//:index.bzl", "js_library", "npm_package_bin")
load("@io_bazel_rules_docker//container:container.bzl", "container_image")

# Source library
js_library(
    name = "web_src",
    srcs = glob([
        "src/**/*",
        "nuxt.config.js",
        "package.json",
    ]),
    deps = [
        "//shared/types",
        "//shared/utils",
    ],
)

# Development server
npm_package_bin(
    name = "dev",
    tool = "@npm//:node_modules/nuxi-edge/dist/cli.js",
    args = ["dev"],
    data = [":web_src"],
)

# Production build
npm_package_bin(
    name = "build",
    tool = "@npm//:node_modules/nuxi-edge/dist/cli.js",
    args = ["build"],
    data = [":web_src"],
)

# Docker image
container_image(
    name = "web_image",
    base = "//infrastructure/docker:node_base",
    files = [":build"],
    cmd = ["yarn", "start"],
)

Backend Functions BUILD.bazel

load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_binary")
load("@build_bazel_rules_nodejs//:index.bzl", "js_library", "js_binary")

# Go API function
go_library(
    name = "api_lib",
    srcs = glob(["go_functions/API/*.go"]),
    importpath = "chaseapp.tv/backend/api",
    deps = [
        "//shared/types",
        "@com_google_cloud_firestore//:go_default_library",
        "@com_firebase_google_go//:go_default_library",
    ],
)

go_binary(
    name = "api",
    embed = [":api_lib"],
    visibility = ["//visibility:public"],
)

# Node.js function
js_library(
    name = "add_user_lib",
    srcs = glob(["js_functions/addUser/**/*.js"]),
    deps = [
        "//shared/types",
        "@npm//:node_modules/firebase-admin",
    ],
)

js_binary(
    name = "add_user",
    entry_point = "js_functions/addUser/index.js",
    deps = [":add_user_lib"],
)

Migration Benefits

Performance Improvements

  • Incremental Builds: Only rebuild changed Cloud Functions
  • Parallel Execution: Build web, mobile, and backend simultaneously
  • Remote Caching: Share build artifacts across development team
  • Deterministic Builds: Reproducible builds for deployment

Developer Experience

  • Cross-language Development: Seamless work with TypeScript, Go, and Dart
  • IDE Integration: Better IntelliSense and refactoring support
  • Testing: Unified test execution across all components
  • Dependency Management: Centralized version control

Migration Process

Phase 1: Foundation (Week 1-2)

  1. Initialize Bazel Workspace

    mkdir chaseapp-bazel
    cd chaseapp-bazel
    touch WORKSPACE
  2. Set Up Basic Rules

    • Install rules_nodejs, rules_go, Flutter rules
    • Create initial .bazelrc configuration
    • Set up dependency management
  3. Migrate Shared Libraries

    • Extract common TypeScript types
    • Create protocol buffer definitions
    • Set up shared utilities

Phase 2: Web Application (Week 3-4)

  1. Configure Nuxt.js Build

    • Set up TypeScript compilation
    • Configure TailwindCSS processing
    • Create Docker containerization rules
  2. Development Workflow

    • Configure hot reloading for development
    • Set up testing with Jest
    • Create deployment targets

Phase 3: Backend Services (Week 5-6)

  1. Migrate Go Functions

    • Set up Go build rules
    • Configure deployment to Cloud Functions
    • Add integration testing
  2. Migrate Node.js Functions

    • Configure TypeScript compilation
    • Set up Firebase Functions deployment
    • Add unit and integration tests

Phase 4: Mobile Application (Week 7-8)

  1. Flutter Integration

    • Set up Flutter build rules
    • Configure Android/iOS builds
    • Create deployment packages
  2. Cross-platform Testing

    • Integration testing across platforms
    • End-to-end testing setup
    • Performance testing

Phase 5: CI/CD Migration (Week 9-10)

  1. GitHub Actions Integration

    name: Build and Test
    on: [push, pull_request]
    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - uses: bazelbuild/setup-bazelisk@v2
          - run: bazel test //...
          - run: bazel build //...
  2. Cloud Build Integration

    • Create Bazel-based build configurations
    • Set up artifact caching
    • Configure deployment triggers

Elixir Rewrite Analysis

Current Technology Assessment

ChaseApp's current stack performs well for its use case, but has specific challenges:

Strengths of Current Stack

  • Real-time Performance: Already handles WebSocket connections effectively
  • Familiar Technologies: JavaScript/TypeScript and Go have large talent pools
  • Firebase Integration: Deep integration with Google Cloud services
  • Mobile Performance: Flutter provides excellent cross-platform performance

Pain Points

  • Language Fragmentation: Context switching between Node.js, Go, and Dart
  • Real-time Scaling: Pusher and Stream Chat costs increase with usage
  • Service Coordination: Complex coordination between multiple cloud functions
  • Deployment Complexity: Multiple deployment targets and configurations

Elixir/Phoenix Benefits for ChaseApp

1. Superior Real-time Performance

  • Phoenix Channels: 1M+ concurrent WebSocket connections on single instance
  • BEAM VM: Automatic load balancing across CPU cores
  • Fault Tolerance: Supervision trees prevent cascade failures
  • Hot Code Reloading: Zero-downtime deployments

2. Simplified Architecture

  • Unified Language: Single language for backend services
  • Phoenix LiveView: Real-time UI updates without complex JavaScript
  • Built-in Pub/Sub: Eliminates need for external messaging services
  • Ecto: Powerful database ORM with migrations and query optimization

3. Operational Benefits

  • VM Hot-swapping: Update code without restarting servers
  • Distribution: Native clustering and load balancing
  • Observability: Built-in metrics and telemetry
  • Concurrency: Lightweight processes for handling thousands of connections

2025 Performance Comparison

Based on current industry benchmarks:

Real-time Capabilities

  • Phoenix (Elixir): 1M+ concurrent WebSocket connections
  • Go: 500K-750K concurrent connections
  • Node.js: 200K-400K concurrent connections

Request Throughput

  • Go: ~45K requests/second (highest raw performance)
  • Phoenix: ~38K requests/second (competitive)
  • Node.js: ~22K requests/second (lowest)

Memory Efficiency

  • Go: Most memory efficient (~50MB base, linear growth)
  • Phoenix: Higher base memory (~200MB) but stable under load
  • Node.js: Variable usage, potential memory leaks

Rewrite vs Evolution Analysis

Arguments for Elixir Rewrite

Technical Benefits:

  1. Real-time Superiority: Phoenix is designed for ChaseApp's exact use case
  2. Simplified Architecture: Single language reduces complexity
  3. Cost Efficiency: Eliminate Pusher/Stream Chat licensing costs
  4. Fault Tolerance: BEAM VM's "let it crash" philosophy improves uptime
  5. Scalability: Linear scaling for concurrent users

Business Benefits:

  1. Performance Gains: Better user experience during high-traffic events
  2. Operational Savings: Reduced infrastructure and third-party costs
  3. Developer Productivity: Unified stack reduces context switching
  4. Future-Proofing: Better positioned for scaling to millions of users

Arguments Against Elixir Rewrite

Risks and Costs:

  1. Team Transition: Learning curve for Elixir/Phoenix
  2. Talent Market: Smaller pool of experienced Elixir developers
  3. Migration Risk: Potential downtime during transition
  4. Ecosystem Maturity: Smaller ecosystem compared to Node.js
  5. Firebase Integration: Need to re-establish Firebase integrations

Current System Adequacy:

  1. Working Solution: Current system meets requirements
  2. Incremental Improvements: Can optimize existing stack
  3. Team Expertise: Current team proficient in existing technologies
  4. Risk Aversion: Rewrite introduces significant project risk

Recommended Approach: Hybrid Strategy

Rather than a complete rewrite, I recommend a phased hybrid approach:

Phase 1: Pilot Elixir Service (3 months)

  • Target Service: Rewrite pusher and getStreams functions in Phoenix
  • Goal: Validate Elixir performance for real-time features
  • Team: Small team of 2-3 developers dedicated to pilot
  • Success Metrics:
    • Performance improvements (latency, concurrent connections)
    • Development velocity metrics
    • Operational cost savings

Phase 2: Gradual Migration (6-12 months)

Based on pilot success:

  • Migrate Real-time Services: Move chat, notifications, and live tracking to Phoenix
  • Keep High-performance APIs: Maintain Go services for CPU-intensive tasks
  • Preserve Web/Mobile: No changes to frontend applications
  • Hybrid Architecture: Phoenix for real-time, Go for data processing, Node.js for legacy services

Phase 3: Full Evaluation (12+ months)

  • Performance Analysis: Compare hybrid vs. current performance
  • Cost-Benefit Analysis: Evaluate operational savings vs. migration costs
  • Decision Point: Determine if full Elixir migration is justified

Implementation Timeline

Immediate Actions (Next 3 months)

  1. Set up Bazel monorepo with current technologies
  2. Start Elixir pilot with real-time notification service
  3. Performance benchmarking of current stack
  4. Team training on Elixir/Phoenix fundamentals

Medium-term Goals (3-12 months)

  1. Bazel migration completion for all services
  2. Elixir pilot evaluation and results analysis
  3. Gradual service migration based on pilot success
  4. Infrastructure optimization using Bazel's caching

Long-term Vision (12+ months)

  1. Optimized hybrid architecture leveraging strengths of each technology
  2. Improved developer productivity through unified build system
  3. Enhanced performance for real-time features
  4. Reduced operational costs through architecture optimization

Immediate Recommendations

1. Bazel Migration Priority: HIGH

  • Timeline: 2-3 months
  • Effort: Medium
  • Impact: High
  • ROI: Significant long-term productivity gains

Actions:

  • Start with Bazel workspace setup this week
  • Migrate shared libraries first
  • Focus on build performance improvements
  • Gradual migration of individual services

2. Elixir Evaluation Priority: MEDIUM

  • Timeline: 3-6 months for pilot
  • Effort: High
  • Impact: Potentially transformative
  • ROI: High but with significant upfront investment

Actions:

  • Begin team training on Elixir/Phoenix
  • Start pilot project with real-time notification service
  • Establish performance benchmarks
  • Evaluate based on pilot results

3. Architecture Modernization Priority: MEDIUM

  • Timeline: 6-12 months
  • Effort: Medium
  • Impact: Medium
  • ROI: Moderate

Actions:

  • Consolidate duplicate functionality
  • Implement better service boundaries
  • Add comprehensive monitoring and observability
  • Optimize Firebase usage patterns

4. Team Development Priority: HIGH

  • Timeline: Ongoing
  • Effort: Low to Medium
  • Impact: High
  • ROI: Significant

Actions:

  • Cross-training on different parts of the stack
  • Documentation and knowledge sharing
  • Best practices establishment
  • Tooling and workflow improvements

🚨 CRITICAL: Immediate Cost Optimization Required

Current Monthly Cost Analysis

ChaseApp currently has massive cost inefficiencies that can be reduced by 60-90%:

Current Monthly Expenses (Estimated)

  • Stream Chat: $200-800/month (pay-per-message)
  • Pusher WebSocket: $150-600/month (pay-per-active-user)
  • Pusher Beams: $100-400/month (push notifications)
  • Mapbox: $100-500/month (pay-per-map-request)
  • Algolia Search: $50-300/month (pay-per-search-operation)
  • Firebase Usage: $200-800/month (Firestore, Storage, Functions)
  • Sentry Error Monitoring: $50-200/month

Total Estimated Monthly Cost: $850-3600

Optimized Monthly Cost: $150-800 (60-90% reduction)


🎯 Priority Implementation: Cost Savings (Week 1-2)

1. ELIMINATE REAL-TIME MESSAGING REDUNDANCY (Save $350-1400/month)

Problem: Using BOTH Stream Chat AND Pusher simultaneously Solution: Choose ONE service and migrate the other

Option A: Keep Stream Chat, Remove Pusher (Recommended)

# Edit web/package.json - Remove these lines:
"pusher-js": "^7.0.6",
"pusher-js-react": "^1.0.0"

# Edit mobile/pubspec.yaml - Remove these lines:
"pusher_channels_flutter": ^2.0.2,
"pusher_beams": ^1.1.1

# Remove Pusher environment variables from:
# api/API/.env.yaml-SAMPLE
# api/pusher/functions/index.js
# api/getStreams/functions/index.js

Implementation Steps:

  1. Week 1: Update package.json files, remove dependencies
  2. Week 1: Update all components using Pusher to use Stream Chat instead
  3. Week 2: Remove Pusher Cloud Functions and API endpoints
  4. Week 2: Deploy and test

Files to modify:

  • web/components/chat/ - All chat components
  • web/plugins/pusher.client.js - Remove this plugin
  • mobile/lib/src/modules/chat/ - Update Flutter chat modules
  • api/pusher/ - Delete entire directory
  • api/getStreams/ - Update to use Stream Chat SDK

2. CONSOLIDATE ANALYTICS (Save $20-100/month)

Problem: Running 3 separate Google Analytics implementations Solution: Keep only GA4, remove Universal Analytics

// Edit web/nuxt.config.js
export default {
  // REMOVE these lines:
  'UA-87374124-3',  // Universal Analytics (deprecated)
  'G-V87EKNP10J',  // Duplicate Firebase Analytics

  // KEEP only GA4:
  googleAnalytics: {
    id: 'G-BYC6KDR1PM'  // Primary GA4 property
  }
}

// Remove web/plugins/firebaseAnalytics.client.ts (duplicate)

πŸ”„ Medium-term Replacements (Month 1-2)

3. REPLACE MAPBOX WITH MAPLIBRE GL JS (Save $100-500/month)

MapLibre is open-source fork of Mapbox GL - completely FREE

# Install MapLibre
cd web
npm install maplibre-gl @maplibre/maplibre-gl-geocoder

# Remove Mapbox dependencies
npm uninstall mapbox-gl @mapbox/mapbox-gl-geocoder @mapbox/mapbox-gl-traffic

Code Migration:

<!-- components/Map.vue - Update imports -->
<script>
// REMOVE:
import mapboxgl from 'mapbox-gl'
import 'mapbox-gl/dist/mapbox-gl.css'

// REPLACE with:
import maplibregl from 'maplibre-gl'
import 'maplibre-gl/dist/maplibre-gl.css'

export default {
  mounted() {
    // REMOVE:
    // mapboxgl.accessToken = process.env.MAPBOX_TOKEN

    // REPLACE with:
    this.map = new maplibregl.Map({
      container: this.$refs.mapContainer,
      style: 'https://demotiles.maplibre.org/style.json', // Free tiles
      center: [-74.5, 40],
      zoom: 9
    })
  }
}
</script>

<style>
/* UPDATE CSS classes */
.mapboxgl-map β†’ .maplibregl-map
.mapboxgl-popup β†’ .maplibregl-popup
/* Update all mapbox CSS classes to maplibregl */
</style>

4. REPLACE ALGOLIA WITH TYPESENSE (Save $50-300/month)

Typesense is open-source, typo-tolerant search - completely FREE

# Install Typesense
cd web
npm install typesense

# Remove Algolia
npm uninstall algoliasearch

Docker Setup (add to project root):

# docker-compose.yml
version: '3.8'
services:
  typesense:
    image: typesense/typesense:26.0
    ports:
      - "8108:8108"
    environment:
      - TYPESENSE_API_KEY=your-secure-api-key-here
      - TYPESENSE_DATA_DIR=/data
    volumes:
      - ./typesense-data:/data
    restart: unless-stopped

Search Integration:

// plugins/typesense.client.js
import Typesense from 'typesense'

export default ({ app }, inject) => {
  const typesenseClient = new Typesense.Client({
    nodes: [{
      host: 'localhost',
      port: '8108',
      protocol: 'http'
    }],
    apiKey: process.env.TYPESENSE_API_KEY,
    connectionTimeoutSeconds: 2
  })

  inject('typesense', typesenseClient)
}

// Replace Algolia calls in components:
// BEFORE:
// const index = algoliaClient.initIndex('chases')
// const results = await index.search(query)

// AFTER:
// const results = await app.$typesense.collections('chases').documents().search({
//   q: query,
//   query_by: 'title,description'
// })

5. SELF-HOST PUSH NOTIFICATIONS (Save $100-400/month)

Replace Pusher Beams with Firebase Cloud Messaging (already included)

// api/fcmMessaging/functions/index.js - Already exists, expand usage

// web/composables/useNotifications.js
import { getMessaging, getToken, onMessage } from 'firebase/messaging'

export const useNotifications = () => {
  const requestPermission = async () => {
    try {
      const permission = await Notification.requestPermission()
      if (permission === 'granted') {
        const messaging = getMessaging()
        const token = await getToken(messaging, {
          vapidKey: process.env.VAPID_PUBLIC_KEY
        })

        // Send token to backend
        await $fetch('/api/register-fcm-token', {
          method: 'POST',
          body: { token }
        })

        return token
      }
    } catch (error) {
      console.error('Notification permission error:', error)
    }
  }

  const setupMessageListener = () => {
    const messaging = getMessaging()
    onMessage(messaging, (payload) => {
      console.log('Received foreground message:', payload)
      // Handle notification display
    })
  }

  return { requestPermission, setupMessageListener }
}

πŸ—οΈ Long-term Architecture Optimizations (Month 2-3)

6. CONSOLIDATE FIREBASE FUNCTIONS

Problem: 25+ separate Cloud Functions causing unnecessary costs Solution: Merge similar functions into microservices

// Create consolidated services:

// NEW: api/services/userService/index.js
// Consolidates: addUser, updateUser, getUser, deleteUser
export const userService = async (req, res) => {
  const { action, data } = req.body

  switch (action) {
    case 'CREATE':
      return await createUser(data)
    case 'UPDATE':
      return await updateUser(data)
    case 'GET':
      return await getUser(data.id)
    case 'DELETE':
      return await deleteUser(data.id)
    default:
      throw new Error('Invalid action')
  }
}

// NEW: api/services/notificationService/index.js
// Consolidates: fcmMessaging, pusher notifications
export const notificationService = async (req, res) => {
  const { type, recipients, message } = req.body

  switch (type) {
    case 'PUSH':
      return await sendPushNotification(recipients, message)
    case 'EMAIL':
      return await sendEmail(recipients, message)
    case 'IN_APP':
      return await sendInAppNotification(recipients, message)
  }
}

7. IMPLEMENT REDIS CACHING

Reduce Firebase database reads by 70-90%

# Add Redis dependency
cd api
npm install ioredis
// api/middleware/cache.js
import Redis from 'ioredis'

const redis = new Redis(process.env.REDIS_URL)

export const cacheMiddleware = async (req, res, next) => {
  // Only cache GET requests
  if (req.method !== 'GET') return next()

  const cacheKey = `cache:${req.path}:${JSON.stringify(req.query)}`
  const cached = await redis.get(cacheKey)

  if (cached) {
    res.setHeader('X-Cache', 'HIT')
    return res.json(JSON.parse(cached))
  }

  // Intercept response to cache it
  const originalJson = res.json
  res.json = function(data) {
    // Cache for 5 minutes
    redis.setex(cacheKey, 300, JSON.stringify(data))
    res.setHeader('X-Cache', 'MISS')
    return originalJson.call(this, data)
  }

  next()
}

// Apply to functions:
export const chaseAPI = async (req, res) => {
  await cacheMiddleware(req, res, async () => {
    // Your function logic here
  })
}

8. SELF-HOST STATIC ASSETS

Replace external CDN dependencies

// web/nuxt.config.js
export default {
  // BEFORE:
  // script: [
  //   { src: 'https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.7.11/lottie.min.js' }
  // ]

  // AFTER:
  script: [
    { src: '/js/lottie.min.js' }  // Local file
  ]
}

// Download and place in web/static/js/lottie.min.js

πŸ“‹ Complete Implementation Timeline

Week 1: Critical Cost Savings

  • Day 1: Remove duplicate analytics (save $20-100/month)
  • Day 2-3: Choose real-time service (keep Stream Chat, remove Pusher)
  • Day 4-5: Update web dependencies (remove Pusher packages)
  • Day 6-7: Update mobile dependencies and rebuild app
  • Week 1 Savings: $400-1000/month

Week 2: Migration Completion

  • Day 8-10: Update all Pusher references to use Stream Chat
  • Day 11-12: Remove Pusher Cloud Functions and APIs
  • Day 13-14: Deploy and test real-time functionality
  • Week 2 Savings: $350-1400/month

Week 3-4: Service Replacements

  • Week 3: Replace Mapbox with MapLibre (save $100-500/month)
  • Week 4: Deploy Typesense for search (save $50-300/month)
  • Week 4: Set up FCM push notifications (save $100-400/month)
  • Month 1 Total Savings: $600-2300/month

Month 2: Architecture Optimization

  • Week 5-6: Consolidate Firebase Functions (save $100-300/month)
  • Week 7-8: Implement Redis caching (save $150-400/month)
  • Month 2 Additional Savings: $250-700/month

Month 3: Final Optimizations

  • Week 9-10: Self-host static assets
  • Week 11-12: Performance monitoring and optimization
  • Month 3 Additional Savings: $50-200/month

πŸ’° Expected Monthly Cost Reduction

Timeline Current Cost Optimized Cost Monthly Savings
Week 1-2 $850-3600 $450-2200 $400-1400 (40-50%)
Month 1 $850-3600 $250-1200 $600-2400 (70-80%)
Month 2 $850-3600 $200-900 $650-2700 (75-85%)
Month 3+ $850-3600 $150-800 $700-2800 (80-90%)

πŸ› οΈ Migration Commands & Scripts

Quick Start Script (Week 1)

#!/bin/bash
# cost_optimization_week1.sh

echo "πŸš€ Starting ChaseApp Cost Optimization - Week 1"

# Remove duplicate analytics
echo "πŸ“Š Removing duplicate analytics..."
sed -i 's/"UA-87374124-3"//g' web/nuxt.config.js
sed -i 's/"G-V87EKNP10J"//g' web/nuxt.config.js

# Remove Pusher from web
echo "πŸ”„ Removing Pusher from web..."
cd web
npm uninstall pusher-js pusher-js-react
rm -f plugins/pusher.client.js

# Remove Pusher from mobile
echo "πŸ“± Removing Pusher from mobile..."
cd ../mobile
flutter pub remove pusher_channels_flutter pusher_beams

# Install updated dependencies
echo "πŸ“¦ Installing updated dependencies..."
cd ../web
npm install
cd ../mobile
flutter pub get

echo "βœ… Week 1 cost optimization complete!"
echo "πŸ’° Expected savings: $400-1000/month"

Service Replacement Script (Month 1)

#!/bin/bash
# service_replacements_month1.sh

echo "πŸ”„ Starting Service Replacements - Month 1"

# Replace Mapbox with MapLibre
echo "πŸ—ΊοΈ Replacing Mapbox with MapLibre..."
cd web
npm install maplibre-gl @maplibre/maplibre-gl-geocoder
npm uninstall mapbox-gl @mapbox/mapbox-gl-geocoder @mapbox/mapbox-gl-traffic

# Replace Algolia with Typesense
echo "πŸ” Replacing Algolia with Typesense..."
npm install typesense
npm uninstall algoliasearch

# Start Typesense Docker container
echo "🐳 Starting Typesense..."
cd ..
docker-compose up -d typesense

echo "βœ… Service replacements complete!"
echo "πŸ’° Expected additional savings: $250-700/month"

🎯 Success Metrics & Validation

Performance Metrics to Monitor

// Add to web/plugins/analytics.client.js
export default ({ app }, inject) => {
  const performanceMonitor = {
    trackPageLoad: () => {
      const navigation = performance.getEntriesByType('navigation')[0]
      console.log('Page load time:', navigation.loadEventEnd - navigation.fetchStart, 'ms')
    },

    trackAPIPerformance: (url, duration) => {
      console.log(`API call to ${url} took ${duration}ms`)
      // Send to analytics for monitoring
    }
  }

  inject('performanceMonitor', performanceMonitor)
}

Cost Tracking Dashboard

// Create web/components/admin/CostDashboard.vue
<template>
  <div class="cost-dashboard">
    <h2>Monthly Cost Tracking</h2>
    <div class="metrics-grid">
      <div class="metric">
        <h3>Current Month</h3>
        <p class="cost">${{ currentMonthCost }}</p>
        <p class="savings">Saved: ${{ monthlySavings }}</p>
      </div>
      <div class="metric">
        <h3>API Calls</h3>
        <p>{{ apiCalls.toLocaleString() }}</p>
        <p class="reduction">{{ apiCallReduction }}% reduction</p>
      </div>
      <div class="metric">
        <h3>Database Reads</h3>
        <p>{{ dbReads.toLocaleString() }}</p>
        <p class="reduction">{{ dbReadReduction }}% reduction</p>
      </div>
    </div>
  </div>
</template>

⚠️ Migration Risks & Rollback Plan

Risk Mitigation

# Create feature flags for gradual rollout
# api/config/featureFlags.js
export const featureFlags = {
  USE_TYPESENSE: process.env.USE_TYPESENSE === 'true',
  USE_MAPLIBRE: process.env.USE_MAPLIBRE === 'true',
  USE_REDIS_CACHE: process.env.USE_REDIS_CACHE === 'true',
  CONSOLIDATED_FUNCTIONS: process.env.CONSOLIDATED_FUNCTIONS === 'true'
}

Rollback Commands

# If issues occur, rollback with:
git checkout HEAD~1 -- web/package.json mobile/pubspec.yaml
npm install  # web
flutter pub get  # mobile

# Restore old services
docker-compose down typesense  # if Typesense issues
# Keep old Algolia/Search functions temporarily

πŸ“Š Implementation Checklist

Pre-Migration

  • Full application backup
  • Performance baseline measurements
  • Cost analysis of current services
  • Team training on new tools
  • Staging environment testing

Migration Execution

  • Week 1: Remove duplicates, consolidate analytics
  • Week 2: Remove Pusher, finalize real-time service
  • Week 3: Replace Mapbox with MapLibre
  • Week 4: Replace Algolia with Typesense
  • Week 5-6: Implement FCM push notifications
  • Week 7-8: Consolidate Firebase Functions
  • Week 9-10: Implement Redis caching
  • Week 11-12: Final optimizations and monitoring

Post-Migration

  • Performance validation
  • Cost verification
  • User acceptance testing
  • Documentation updates
  • Monthly cost tracking setup

Conclusion

ChaseApp currently has significant cost inefficiencies that can be immediately addressed:

Primary Recommendation (Do This Week):

  1. Eliminate Pusher/Stream Chat redundancy - Save $350-1400/month
  2. Consolidate analytics - Save $20-100/month
  3. Expected immediate savings: $400-1000/month

Secondary Recommendations (Next Month):

  1. Replace Mapbox with MapLibre - Save $100-500/month
  2. Replace Algolia with Typesense - Save $50-300/month
  3. Self-host push notifications - Save $100-400/month

Long-term Optimizations:

  1. Consolidate Firebase Functions - Save $100-300/month
  2. Implement Redis caching - Save $150-400/month

Total Potential Savings: $700-2800/month (80-90% cost reduction)

This cost optimization plan provides immediate financial benefits while improving application performance and reducing technical debt. All recommended replacements use mature, open-source alternatives that have proven track records and active communities.

Next Steps:

  1. Start with Week 1 optimizations immediately
  2. Set up cost tracking dashboard
  3. Monitor performance metrics
  4. Execute gradual rollout plan

Updated: December 2025 - Added comprehensive cost optimization guide Next Review: January 2026