# How Data Layers Are Registered and Managed in God’s Eye View

> Learn how God's Eye View registers and manages data layers using the DataLayerManager. Explore deterministic APIs for toggling, enabling, and refreshing sources.

- Repository: [Bilawal Sidhu/gods-eye-view](https://github.com/bilawalsidhu/gods-eye-view)
- Tags: internals
- Published: 2026-08-29

---

**God’s Eye View centralizes all overlay logic in a `DataLayerManager` class that stores layers in an internal `Map`, seals the registry with `finalizeRegistrations`, and exposes deterministic APIs for toggling, enabling, and refreshing each source.**

The `bilawalsidhu/gods-eye-view` repository relies on this manager to coordinate real-time data overlays such as flights, earthquakes, and CCTV feeds. Understanding how data layers are registered and managed in God’s Eye View is essential for anyone extending the codebase or debugging layer state issues.

## The DataLayerManager Core

At the heart of the system is the `DataLayerManager` class defined in [`src/data/manager.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/manager.js). The manager maintains a private `this.layers` structure—specifically a `Map`—where each entry tracks the layer module, its visibility state, lifecycle metadata, refresh timers, and event listeners. This single source of truth is initialized in the class constructor around lines 18–26 of [`src/data/manager.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/manager.js).

## Step 1: Registering Data Layers

### Bootstrap Registration in main.js

Layer registration begins during application bootstrap inside [`src/main.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/main.js). Each data source is implemented as a module that exports a stable `id`. These modules are passed to `DataLayerManager.register()` for production builds, or to `registerForQa()` when running in development mode, as shown in lines 9–26 of [`src/main.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/main.js).

### Internal Map Storage

Once `register()` is invoked, the manager inserts a record into `this.layers`. The record holds the module reference, default visibility flags, and placeholders for lifecycle state. You can inspect this initialization logic in the `DataLayerManager` constructor in [`src/data/manager.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/manager.js) at lines 18–26.

## Step 2: Finalizing the Registry

After all production layers have been added, the bootstrap sequence calls `DataLayerManager.finalizeRegistrations()` with a static `LAYER_STATE_REGISTRY`. This step performs a strict consistency check: every registered layer must declare a serialization disposition, and no stray identifiers are permitted. Only after this call succeeds are the layers considered sealed and usable by the rest of the application. See the implementation in [`src/data/manager.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/manager.js), lines 18–38.

## Step 3: Runtime Visibility and Lifecycle Control

### Toggling Layers with toggle()

The `toggle(layerId, options)` method flips a layer’s enabled state. It is designed to respect any ongoing lifecycle work by queueing the request rather than interrupting in-flight transitions, which prevents race conditions. This logic resides in [`src/data/manager.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/manager.js), lines 40–52.

### Deterministic State Changes with setEnabled()

For explicit control—whether from UI clicks, voice commands, or scene scripts—the manager exposes `setEnabled(layerId, shouldEnable, options)`. This deterministic helper internally delegates to `_setEnabledWithIntent()`, which creates an **intent epoch**, records the request, and serializes the lifecycle transition so that overlapping calls do not corrupt state. Review this flow in [`src/data/manager.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/manager.js), lines 58–71.

### Lifecycle States and UI Synchronization

Every layer moves through well-defined states: `enabling`, `enabled`, `disabling`, and `disabled`. The manager drives these transitions by invoking the layer’s own `init()`, `enable()`, `update()`, and `disable()` methods at the appropriate times. After a transition completes, the manager synchronizes the toggle panel via `_refreshTogglePanel()` and notifies detection consumers through `markDetectionSourcesChanged()`. These mechanisms are implemented in [`src/data/manager.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/manager.js), lines 89–106 and 137–148.

### Periodic Refresh and Event Broadcasting

For layers that specify a `refreshInterval`, the manager arms a timer via `setInterval` that triggers `_runPeriodicUpdate()`. The refresh loop updates the layer data, requests a render, and then notifies listeners of success or failure. Timer setup appears around lines 22–33 of [`src/data/manager.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/manager.js), while the update and notification logic spans lines 88–100.

State changes emit structured events such as `visibility-will-change`, `visibility`, `refresh`, and `refresh-failed`. UI components and voice handlers subscribe to these events through `dataManager.subscribe()`, as shown in lines 84–92 of [`src/data/manager.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/manager.js).

## Code Example: Registering and Controlling a Layer

The following pattern demonstrates the full registration and management sequence used throughout the codebase:

```javascript
// 1️⃣ Register a custom layer (e.g., a new satellite feed)
import { DataLayerManager } from './data/manager.js';
import mySatelliteLayer from './layers/mySatelliteLayer.js';

const dataManager = new DataLayerManager(viewer);
dataManager.register(mySatelliteLayer);      // ← adds to internal Map

// 2️⃣ Finalize the registration set (usually done once at startup)
dataManager.finalizeRegistrations(LAYER_STATE_REGISTRY);

// 3️⃣ Enable the layer via UI or script
await dataManager.setEnabled('my-satellite', true, {
  origin: 'user',               // marks the intent source
  notificationToken: 'ui-click' // optional token for UI correlation
});

// 4️⃣ Toggle a layer (e.g., user clicks the “Traffic” checkbox)
await dataManager.toggle('traffic', {
  origin: 'user',
  notificationToken: 'traffic-checkbox'
});

// 5️⃣ Force a fresh refresh (useful for voice commands like “refresh flights”)
await dataManager.refreshLayer('flights');

```

All calls above ultimately route through [`src/data/manager.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/manager.js), where intent epochs, lifecycle transitions, and periodic updates are handled.

## Summary

- **`DataLayerManager`** in [`src/data/manager.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/manager.js) is the single authority for layer state.
- Layers are registered during bootstrap in [`src/main.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/main.js) and stored in an internal `Map`.
- **`finalizeRegistrations()`** seals the registry by validating every layer against `LAYER_STATE_REGISTRY`.
- **`toggle()`** and **`setEnabled()`** provide deterministic, race-safe visibility control.
- Lifecycle methods (`init`, `enable`, `update`, `disable`) and periodic refresh timers keep overlays current.
- Structured events broadcast state changes to UI, voice, and scene subsystems.

## Frequently Asked Questions

### What class is responsible for data layer registration and management in God’s Eye View?

The `DataLayerManager` class defined in [`src/data/manager.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/manager.js) is responsible. It exposes `register()`, `finalizeRegistrations()`, `toggle()`, `setEnabled()`, and `refreshLayer()` to coordinate every overlay’s lifecycle.

### How does God’s Eye View prevent race conditions when toggling layers?

The manager queues toggle requests rather than allowing them to interrupt active lifecycle transitions. The `setEnabled()` path uses `_setEnabledWithIntent()` to create an intent epoch, which serializes overlapping calls and guarantees deterministic state.

### Why is finalizeRegistrations required before layers can be used?

`finalizeRegistrations()` performs a consistency check against `LAYER_STATE_REGISTRY` to ensure every registered layer has a valid serialization disposition and that no stray IDs exist. This step seals the registry so that runtime code operates on a validated, immutable layer set.

### Which other modules integrate with DataLayerManager?

Beyond the core [`src/data/manager.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/manager.js) implementation, [`src/main.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/main.js) handles bootstrap registration, [`src/ui.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/ui.js) wires checkboxes and menus to `toggle()` and `setEnabled()`, [`src/voice/gevActions.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/voice/gevActions.js) enables voice-driven layer control, and [`src/scenes/director.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/scenes/director.js) manipulates layers during scripted scene playback.