How to Extend gods-eye-view Functionality: A Complete Guide for Customizing the Cesium-Based Visualization Platform
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 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 |
| 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), 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), which drives scene selection.
Example: Adding Night Vision Mode
// 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):
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) as a template.
Example: Weather Stations Loader
// 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):
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) file contains the scene registry.
Example: Night City Scene with Heat Map
// 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;
};
// 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) module provides the base implementation for tokens, labels, and annotations.
To create a new overlay type:
- Create a module in
src/overlays/ - Export a function accepting
viewerand configuration options - Use Cesium's Entity API or custom WebGL for rendering
- Import and invoke from your scene's
onEnterhandler
Using the Pinokio Plugin System
The Pinokio Engine provides lightweight scripting for session-specific logic. Scripts in the pinokio/ directory run at defined lifecycle points.
| Script | Execution Point |
|---|---|
start.js |
Session initialization |
update.js |
Per-frame update loop |
end.js |
Session cleanup |
Example Pinokio script:
// 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:
- Select the appropriate layer — data, overlay, policy, or scene
- Copy an existing module as your template
- Implement your logic following the established patterns
- Register the module in the host file (index or
main.js) - Add UI controls in
src/ui.jsif user interaction is needed - Verify with tests using
scripts/run-unit-tests.mjs - Update build config in [
vite.config.js](https://github.com/bilawalsidhu/gods-eye-view/blob/main/vite.config.js) if adding new entry points
Key Files Reference
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 inmain.js - Scenes combine multiple elements into reusable views via
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), 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). 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). Parse your format, convert to Cesium Entity objects or custom primitives, and expose a standard async load function. Register in 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) 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →