Agile Inference Logo
Login
arrow_back Back to Blog
July 25, 2026By Agile

How We Built the Intelligence Monitor

A practical look at how we built the live dashboard on our site, including the data flow, map setup, and frontend timing choices.

How We Built the Intelligence Monitor

We built a live dashboard that pulls together geography, weather, and market data on our homepage. This article walks through the server-side proxy routes, the Leaflet map setup, and the state handling we used to keep the page responsive.

System Objectives

We aimed for three things:

  1. Visual density: Show live geography, charts, and data streams without crowding the page.
  2. Performance: Keep the page fast and avoid layout shifts.
  3. Resilience: Handle API rate limits and network delays without breaking the view.

Architectural Stack

We chose tools that keep the page light and simple to maintain:

  • Nuxt (Vue 3): Serves as the web framework. We use server-side rendering (SSR) for fast initial loads and page hydration.
  • Leaflet: Provides a lightweight open-source mapping engine. We styled the map using CartoDB Dark Matter tiles to match our dark aesthetic.
  • Vanilla CSS: Handles responsive layouts, grid systems, and animations.

Implementation Stages

1. Data Aggregation and Server-Side API Routing

To protect API keys and avoid client-side rate limits, we created dedicated server-side endpoints in Nuxt (/server/api/dashboard/*). These routes aggregate data from public sources:

  • Open-Meteo API: For local weather updates.
  • MarineTraffic: For interactive Strait of Hormuz vessel tracking.
  • Financial Indicators: Market indexes updated dynamically (subject to disclosures).
  • Dynamic Events: Simulated security incidents distributed globally.

2. Client-Side Rendering Strategy

Leaflet requires direct access to the browser window object. In Nuxt, we wrapped the initialization code inside onMounted and dynamically imported the library:

// DataDashboard.vue initialization pattern
onMounted(async () => {
  if (process.client) {
    const L = await import('leaflet')
    // Initialize map container and load CartoDB tile layer
  }
})

3. Transition Optimization

To match the dark visual style we wanted, we added a fade-in, zoom, and desaturation transition to the hero background with Nuxt state:

<img src="/images/bg.webp" 
     class="hero-video transition-all duration-1000 ease-out transform" 
     :class="showHeroCard ? 'opacity-100 scale-100 grayscale-0 blur-none' : 'opacity-0 scale-105 grayscale blur-md'" />

Lessons Learned

  • CORS & Proxying: Proxying external API calls through Nuxt server routes prevents client-side CORS issues.
  • Leaflet Hydration: Always initialize mapping tools inside browser-only hooks to prevent Nuxt build errors.
  • Polling Intervals: Adjusting update intervals (e.g. to 5 minutes) keeps data fresh without overloading backend resources.