# How to Extend gods-eye-view Functionality: A Complete Guide for Customizing the Cesium-Based Visualization Platform

> Learn how to extend gods-eye-view functionality by adding custom modules for policies, scenes, data loaders, and overlays. This guide provides a complete walkthrough for customizing the Cesium visualization platform.

- Repository: [Bilawal Sidhu/gods-eye-view](https://github.com/bilawalsidhu/gods-eye-view)
- Tags: how-to-guide
- Published: 2026-09-05

---

**The most effective way to extend gods-eye-view is by adding new modules in the appropriate directory layer—policies for behavior, scenes for views, data loaders for sources, or overlays for visual elements—then registering them in the host file.**

[gods-eye-view](https://github.com/bilawalsidhu/gods-eye-view) is a modular, browser-based geospatial visualization platform built on **Cesium** and a custom rendering pipeline. Its layered architecture makes it straightforward to add new capabilities without modifying core rendering code. This guide walks through each extension point with concrete examples from the source.

## Understanding the Architecture Layers

The codebase is organized into logical layers that separate concerns and provide clear extension points:

| Layer | Purpose | Extension Point |
|-------|---------|---------------|
| **Core App** | Boots the Cesium viewer and drives the render loop | Add startup routines or modify [`main.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/main.js) |
| **Policies** | Composable objects that encapsulate behavior | Create new policy objects or extend existing ones |
| **Scenes / Recipes** | Collections of layers and styles forming a view | Add new scene definitions |
| **Data Modules** | Load and cache external data sources | Introduce new data loaders |
| **Overlays** | Render UI-level graphics and annotations | Write new overlay modules |
| **Pinokio Engine** | Lightweight plugin system for session scripts | Add new Pinokio scripts |
| **Utilities** | Helper libraries for math and UI operations | Extend utility modules |

Each layer is implemented as a set of focused JavaScript modules in the `src/` directory, making it easy to locate relevant code.

## Extending via Policies

Policies are small, pure-function objects that receive the current state and return updated state. This design makes them ideal for extending behavior.

In [[`src/cockpitVisionPolicy.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/cockpitVisionPolicy.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/cockpitVisionPolicy.js), policies control cockpit UI and visual effects. The same pattern appears in [[`src/scenes/scenePolicy.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/scenes/scenePolicy.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/scenes/scenePolicy.js), which drives scene selection.

### Example: Adding Night Vision Mode

```javascript
// src/cockpitVisionPolicy.js
export const cockpitVisionPolicy = {
  // Existing methods...
  
  nightVision: (state) => ({
    ...state,
    postProcess: { ...state.postProcess, nightVision: true },
  }),
  
  dayVision: (state) => ({
    ...state,
    postProcess: { ...state.postProcess, nightVision: false },
  }),
};

```

Activate via UI in [[`src/ui.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/ui.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/ui.js):

```javascript
import { cockpitVisionPolicy } from './cockpitVisionPolicy.js';

document.getElementById('nightBtn').addEventListener('click', () => {
  appState = cockpitVisionPolicy.nightVision(appState);
});

```

## Adding New Data Sources

Data modules in `src/data/` handle loading and caching for external feeds. Use [[`src/data/traffic.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/traffic.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/traffic.js) as a template.

### Example: Weather Stations Loader

```javascript
// src/data/weatherStations.js
import { fetchJson } from '../utils/network.js';

export const loadWeatherStations = async (viewer) => {
  const data = await fetchJson('https://api.example.com/weather-stations');
  
  data.forEach((station) => {
    viewer.entities.add({
      name: station.name,
      position: Cesium.Cartesian3.fromDegrees(station.lon, station.lat),
      point: { pixelSize: 8, color: Cesium.Color.CYAN },
      description: `<b>Temperature:</b> ${station.temp}°C`,
    });
  });
};

```

Register in [[`src/main.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/main.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/main.js):

```javascript
import { loadWeatherStations } from './data/weatherStations.js';

// In initialization sequence
await loadWeatherStations(viewer);

```

## Creating Custom Scenes

Scenes define complete views combining layers, styles, and data sources. The [[`src/scenes/recipes.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/scenes/recipes.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/scenes/recipes.js) file contains the scene registry.

### Example: Night City Scene with Heat Map

```javascript
// src/overlays/customHeatMap.js
export const renderHeatMap = (viewer, heatData) => {
  const heatmap = new CesiumHeatmap(viewer.scene, {
    radius: 20,
    maxOpacity: 0.6,
  });
  
  heatmap.setData({
    max: 100,
    data: heatData.map(p => ({ 
      x: p.lon, 
      y: p.lat, 
      value: p.intensity 
    })),
  });
  
  return heatmap;
};

```

```javascript
// src/scenes/recipes.js
import { renderHeatMap } from '../overlays/customHeatMap.js';
import { loadTraffic } from '../data/traffic.js';

export const nightCityScene = {
  name: 'Night City',
  
  onEnter: async (viewer) => {
    // Base layers
    viewer.scene.skyBox.show = false;
    viewer.scene.globe.enableLighting = true;
    
    // Data and overlays
    await loadTraffic(viewer);
    const heatData = await fetch('/api/city-activity').then(r => r.json());
    renderHeatMap(viewer, heatData);
  },
  
  onExit: (viewer) => {
    // Cleanup
    viewer.entities.removeAll();
  },
};

```

## Building Custom Overlays

Overlays render visual elements atop the Cesium globe. The [[`src/overlays/worldOverlay.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/overlays/worldOverlay.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/overlays/worldOverlay.js) module provides the base implementation for tokens, labels, and annotations.

To create a new overlay type:

1. Create a module in `src/overlays/`
2. Export a function accepting `viewer` and configuration options
3. Use Cesium's Entity API or custom WebGL for rendering
4. Import and invoke from your scene's `onEnter` handler

## Using the Pinokio Plugin System

The **Pinokio Engine** provides lightweight scripting for session-specific logic. Scripts in the [`pinokio/`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/pinokio/start.js) directory run at defined lifecycle points.

| Script | Execution Point |
|--------|----------------|
| [`start.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/start.js) | Session initialization |
| [`update.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/update.js) | Per-frame update loop |
| [`end.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/end.js) | Session cleanup |

Example Pinokio script:

```javascript
// pinokio/telemetryOverlay.js
export default async function(ctx) {
  const { viewer, state } = ctx;
  
  // Add real-time telemetry readout
  const telemetry = await fetch('/api/telemetry').then(r => r.json());
  
  viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(telemetry.lon, telemetry.lat, telemetry.alt),
    label: {
      text: `ALT: ${Math.round(telemetry.alt)}m`,
      font: '14px monospace',
      fillColor: Cesium.Color.YELLOW,
      outlineColor: Cesium.Color.BLACK,
      outlineWidth: 2,
    },
  });
}

```

## Extension Checklist

Follow this process for any new feature:

1. **Select the appropriate layer** — data, overlay, policy, or scene
2. **Copy an existing module** as your template
3. **Implement your logic** following the established patterns
4. **Register the module** in the host file (index or [`main.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/main.js))
5. **Add UI controls** in [`src/ui.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/ui.js) if user interaction is needed
6. **Verify with tests** using `scripts/run-unit-tests.mjs`
7. **Update build config** in [[`vite.config.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/vite.config.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/vite.config.js) if adding new entry points

## Key Files Reference

| File | Role |
|------|------|
| [[`src/main.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/main.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/main.js) | Application bootstrap and render loop |
| [[`src/scenes/recipes.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/scenes/recipes.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/scenes/recipes.js) | Scene registry and definitions |
| [[`src/scenes/scenePolicy.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/scenes/scenePolicy.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/scenes/scenePolicy.js) | Scene selection policy driver |
| [[`src/overlays/worldOverlay.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/overlays/worldOverlay.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/overlays/worldOverlay.js) | Base overlay renderer |
| [[`src/cockpitVisionPolicy.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/cockpitVisionPolicy.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/cockpitVisionPolicy.js) | Cockpit UI and effects policies |
| [[`src/data/traffic.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/traffic.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/traffic.js) | Example data loader implementation |
| [[`pinokio/start.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/pinokio/start.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/pinokio/start.js) | Pinokio plugin entry point |
| [[`src/ui.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/ui.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/ui.js) | User interface controls |
| [[`vite.config.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/vite.config.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/vite.config.js) | Build configuration |
| [[`README.md`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/README.md)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/README.md) | Project documentation and quick-start |

## Summary

- **gods-eye-view organizes functionality into discrete layers**: core app, policies, scenes, data, overlays, and plugins
- **Policies provide the primary extension mechanism** for behavior changes—pure functions that transform state
- **New data sources require a loader module** in `src/data/` plus registration in [`main.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/main.js)
- **Scenes combine multiple elements** into reusable views via [`src/scenes/recipes.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/scenes/recipes.js)
- **The Pinokio system enables session scripts** without modifying core code
- **All extensions follow copy-modify-register pattern** for consistency and testability

## Frequently Asked Questions

### What is the fastest way to add a new visualization layer?

Create an overlay module in `src/overlays/` modeled on [[`src/overlays/worldOverlay.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/overlays/worldOverlay.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/overlays/worldOverlay.js), then invoke it from your scene's `onEnter` handler. Overlays require no policy changes and minimal registration.

### How do I modify camera behavior without breaking existing scenes?

Extend or create a policy in [[`src/cockpitVisionPolicy.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/cockpitVisionPolicy.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/cockpitVisionPolicy.js). Policies encapsulate camera logic as pure functions, so you can add new behaviors without altering the core camera system or affecting other scenes.

### Can I load proprietary data formats?

Yes—implement a custom data loader in `src/data/` following the pattern in [[`src/data/traffic.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/traffic.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/traffic.js). Parse your format, convert to Cesium Entity objects or custom primitives, and expose a standard async load function. Register in [`main.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/main.js) like any other data source.

### Where do I add user-facing configuration controls?

Add DOM event listeners in [[`src/ui.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/ui.js)](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/ui.js) that invoke your policy methods or toggle scene states. The UI module is the designated location for all user interaction wiring, keeping presentation logic separate from core visualization code.