This guide covers complex architectures, real-time telemetry streaming, and the deployment lifecycle for WorldWideView plugins. If you haven't built a basic plugin yet, start with the Quickstart.
WorldWideView operates on a strict Dynamic CDN Loaded (Bundle) architecture.
Warning
Deprecation Notice: The legacy StaticDataPlugin (GeoJSON loaders) and DeclarativePlugin runtimes are fully deprecated. All new plugins must be dynamically imported at runtime as ES module bundles via import(/* webpackIgnore: true */ entry).
- A user clicks "Install" in the Marketplace.
- The marketplace sends the plugin manifest (containing an ES Module CDN URL, like
unpkg.com) to the WorldWideView database. - At runtime, the
InstalledPluginsLoaderdynamically fetches the JavaScript bundle. - The plugin is instantiated, and its
initialize(ctx)method is invoked.
Relying on the frontend fetch() method is insufficient for high-frequency real-time tracking (like aviation or maritime). For continuous telemetry, you must build a Data Engine Seeder — a lightweight Javascript data polling script.
Instead of the frontend fetching data, you write a lightweight seeder script that connects to an upstream source, normalizes the data, and is executed by the central wwv-data-engine runner.
- Create a Seeder Directory: Inside your WorldWideView project, create a folder under
local-seeders/(e.g.,local-seeders/my-plugin/). - Write the Seeder Script: Create a
seeder.mjsfile that exports afetch(ctx)function. - Engine Auto-Discovery: The local Docker-based
wwv-data-engineautomatically mounts this directory, discovers your script, and runs it on the defined interval. - WebSocket Delivery: The central
wwv-data-engineimmediately broadcasts your returned updates over WebSockets to all connected clients.
Seeders within local-seeders/ are strictly orchestrated within the pnpm workspace. They are executed by the central runner, not as standalone applications.
- Keep
package.jsonclean: Do not include bulkydependenciesin your seeder's localpackage.json(unless it's an exceptional, bespoke library). - Workspace Resolution: Standard packages (e.g.,
axios,ioredis,@worldwideview/wwv-plugin-sdk) are provided by the engine. At runtime, thewwv-data-engineleverages native Node.js module resolution to fetch the required dependencies directly from the root workspace or its own containerized runtime. - Lightweight by Design: This dependency orchestration guarantees that seeders remain extremely lightweight, hot-reloading takes milliseconds, and Docker container size stays optimized.
Tip
Debugging WebSockets: If your frontend isn't receiving data from your backend seeder:
- Check the
wwv-data-enginelogs to ensure your seeder is publishing to Redis successfully. - Verify the frontend is connected to the correct WebSocket endpoint. Local instances default to
ws://localhost:5000/stream, while unrecognized seeders fall back to the cloud atwss://dataengine.worldwideview.dev/stream.
When returning CesiumEntityOptions in renderEntity(entity), you have direct access to the 3D engine's capabilities.
To maintain 60 FPS with tens of thousands of entities, use WorldWideView's Level of Detail (LOD) promotion system.
- Render distant entities as simple
billboardorpointprimitives. - When the camera gets close, the system's
useModelRenderinghook can promote the entity to a full 3D glTF model.
renderEntity(entity: GeoEntity): CesiumEntityOptions {
return {
type: "billboard", // Primary lightweight renderer
color: "#ffffff",
iconUrl: "https://unpkg.com/my-plugin/assets/icon.png",
iconScale: 0.5,
// Provide a 3D model URL. The engine will swap it in automatically at close range.
modelUrl: "https://unpkg.com/my-plugin/assets/model.glb",
modelScale: 1.0,
heading: entity.heading,
};
}Caution
GPU Clipping Bug: NEVER mix size, outlineWidth, or outlineColor properties onto an entity of type: "billboard". This will cause the WebGL compiler to panic and result in severe visual clipping artifacts.
To distribute your plugin globally:
- Publish to NPM:
npm publish --access public
- Submit: Navigate to
https://marketplace.worldwideview.dev/submit. - Register: Enter your NPM package name. The marketplace automatically scrapes your
package.jsonfor the required"worldwideview"object block (containing yourid,icon, andcategory). - Review: Once approved, your plugin's ES Module bundle will be served via CDN to all WorldWideView instances worldwide.
- "Invalid Manifest" Error: Ensure you are using
@worldwideview/wwv-plugin-sdkas apeerDependency(not a direct dependency) so the host application injects the context correctly. - Icon Not Showing: Icons must be valid Lucide icon strings (e.g.,
"Plane","Anchor").