From cesiumjs-skills
Sets up CesiumJS Viewer and Scene configuration including Ion tokens, Google Maps, iTwin, widgets, and geocoders. Use when initializing a 3D globe application.
How this skill is triggered — by the user, by Claude, or both
Slash command
/cesiumjs-skills:cesiumjs-viewer-setupThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Reference for bootstrapping CesiumJS applications: Viewer, CesiumWidget, Ion/GoogleMaps/ITwinPlatform configuration, widgets, factory helpers, geocoder services, viewer mixins, Credits, and related enums.
Reference for bootstrapping CesiumJS applications: Viewer, CesiumWidget, Ion/GoogleMaps/ITwinPlatform configuration, widgets, factory helpers, geocoder services, viewer mixins, Credits, and related enums.
import { Ion, Viewer, Terrain } from "cesium";
import "cesium/Build/Cesium/Widgets/widgets.css";
// Always set your Ion token before any other Cesium calls
Ion.defaultAccessToken = "YOUR_CESIUM_ION_ACCESS_TOKEN";
const viewer = new Viewer("cesiumContainer", {
terrain: Terrain.fromWorldTerrain(),
});
Required HTML: <div id="cesiumContainer" style="width:100%;height:100vh"></div>
import { Ion } from "cesium";
Ion.defaultAccessToken = "YOUR_TOKEN"; // required for ion assets
Ion.defaultServer = "https://your-ion-server.example.com/"; // optional: self-hosted
import { IonResource, Cesium3DTileset } from "cesium";
const resource = await IonResource.fromAssetId(96188);
const tileset = await Cesium3DTileset.fromUrl(resource);
viewer.scene.primitives.add(tileset);
import { GoogleMaps, createGooglePhotorealistic3DTileset, Viewer, IonGeocodeProviderType } from "cesium";
GoogleMaps.defaultApiKey = "YOUR_GOOGLE_MAPS_API_KEY"; // optional: without key, served via ion
const viewer = new Viewer("cesiumContainer", {
geocoder: IonGeocodeProviderType.GOOGLE, // required with Google 3D Tiles
});
const tileset = await createGooglePhotorealistic3DTileset({
onlyUsingWithGoogleGeocoder: true,
});
viewer.scene.primitives.add(tileset);
import { ITwinPlatform, ITwinData } from "cesium";
ITwinPlatform.defaultAccessToken = "YOUR_ITWIN_TOKEN";
const tileset = await ITwinData.createTilesetForIModel(viewer, "imodel-id");
// 1.140+ (#13208): Reality Data of type GaussianSplat3DTiles is now supported
const splats = await ITwinData.createTilesetForRealityDataId(
iTwinId,
realityDataId,
ITwinPlatform.RealityDataType.GaussianSplat3DTiles,
);
viewer.scene.primitives.add(splats);
new Viewer(container, options?) -- container is a DOM element or its string ID.
| Option | Default | Purpose |
|---|---|---|
animation | true | Playback controls |
baseLayerPicker | true | Imagery/terrain switcher |
fullscreenButton | true | Fullscreen toggle |
vrButton | false | WebVR toggle |
geocoder | IonGeocodeProviderType.DEFAULT | Search bar (false to hide) |
homeButton | true | Reset to home view |
infoBox | true | Entity info popup |
sceneModePicker | true | 2D/3D/Columbus toggle |
selectionIndicator | true | Selection reticle |
timeline | true | Time scrubber |
navigationHelpButton | true | Mouse/touch help |
projectionPicker | false | Perspective/ortho toggle |
| Option | Default | Purpose |
|---|---|---|
sceneMode | SceneMode.SCENE3D | Initial scene mode |
scene3DOnly | false | Lock to 3D, saves GPU memory |
shadows | false | Shadow casting |
terrainShadows | ShadowMode.RECEIVE_ONLY | Terrain shadow mode |
requestRenderMode | false | Render only on changes |
maximumRenderTimeChange | 0.0 | Max sim-time delta for render |
msaaSamples | 4 | MSAA (1 to disable) |
orderIndependentTranslucency | true | Translucent ordering |
mapMode2D | MapMode2D.INFINITE_SCROLL | 2D scroll behavior |
| Option | Default | Purpose |
|---|---|---|
baseLayer | ImageryLayer.fromWorldImagery() | Base imagery (false for none; needs baseLayerPicker: false) |
terrain | none | Async terrain helper (cannot combine with terrainProvider) |
terrainProvider | EllipsoidTerrainProvider | Sync terrain provider |
globe | new Globe() | false for no globe (space scenes) |
skyBox | auto (WGS84) | false disables sky/sun/moon |
skyAtmosphere | auto (WGS84) | false disables limb glow |
import { Viewer, Ion, Terrain } from "cesium";
Ion.defaultAccessToken = "YOUR_TOKEN";
const viewer = new Viewer("cesiumContainer", {
animation: false, baseLayerPicker: false, fullscreenButton: false,
geocoder: false, homeButton: false, infoBox: false,
sceneModePicker: false, selectionIndicator: false,
timeline: false, navigationHelpButton: false,
terrain: Terrain.fromWorldTerrain(),
});
No UI widgets, no Knockout dependency. Suitable for custom UIs or embedding.
import { CesiumWidget, Ion } from "cesium";
Ion.defaultAccessToken = "YOUR_TOKEN";
const widget = new CesiumWidget("cesiumContainer", { shouldAnimate: true });
// Exposes: widget.scene, widget.camera, widget.entities
| Value | Description |
|---|---|
SceneMode.SCENE3D | Standard 3D globe (default) |
SceneMode.SCENE2D | Top-down orthographic map |
SceneMode.COLUMBUS_VIEW | 2.5D flat map with height |
SceneMode.MORPHING | Transitioning between modes |
import { Viewer, SceneMode } from "cesium";
const viewer = new Viewer("cesiumContainer", { sceneMode: SceneMode.SCENE2D });
viewer.scene.morphTo3D(2.0); // animated transition
viewer.scene.morphToColumbusView(2.0);
const scene = viewer.scene;
scene.globe.depthTestAgainstTerrain = true; // entities interact with terrain
scene.globe.enableLighting = true; // sun-based lighting
// Key sub-objects
scene.camera; // Camera
scene.primitives; // PrimitiveCollection
scene.groundPrimitives; // PrimitiveCollection (ground-clamped)
scene.imageryLayers; // ImageryLayerCollection
scene.postProcessStages;
scene.requestRender(); // trigger frame in requestRenderMode
import { createOsmBuildingsAsync, Cesium3DTileStyle } from "cesium";
// Default styling (colors from OSM tags)
const tileset = await createOsmBuildingsAsync();
viewer.scene.primitives.add(tileset);
// Custom style
const styled = await createOsmBuildingsAsync({
style: new Cesium3DTileStyle({
color: { conditions: [
["${feature['building']} === 'hospital'", "color('#0000FF')"],
[true, "color('#ffffff')"],
]},
}),
});
import { createGooglePhotorealistic3DTileset, IonGeocodeProviderType } from "cesium";
// Must use Google geocoder
const viewer = new Viewer("cesiumContainer", { geocoder: IonGeocodeProviderType.GOOGLE });
const tileset = await createGooglePhotorealistic3DTileset({ onlyUsingWithGoogleGeocoder: true });
viewer.scene.primitives.add(tileset);
Preferred for the terrain constructor option. Non-blocking with error events.
import { Viewer, Terrain } from "cesium";
// World terrain with normals and water
const viewer = new Viewer("cesiumContainer", {
terrain: Terrain.fromWorldTerrain({ requestVertexNormals: true, requestWaterMask: true }),
});
// Bathymetry (ocean floor)
const viewer2 = new Viewer("cesiumContainer", {
terrain: Terrain.fromWorldBathymetry({ requestVertexNormals: true }),
});
import { Terrain, CesiumTerrainProvider } from "cesium";
const terrain = new Terrain(CesiumTerrainProvider.fromUrl("https://my-terrain.example.com"));
viewer.scene.setTerrain(terrain);
terrain.readyEvent.addEventListener((provider) => {
viewer.scene.globe.enableLighting = true;
});
terrain.errorEvent.addEventListener((error) => console.error("Terrain failed:", error));
Lower-level: return raw providers. Use when you need the provider directly.
import { createWorldTerrainAsync, createWorldImageryAsync, IonWorldImageryStyle } from "cesium";
const terrainProvider = await createWorldTerrainAsync({ requestVertexNormals: true });
viewer.terrainProvider = terrainProvider;
const imageryProvider = await createWorldImageryAsync({ style: IonWorldImageryStyle.AERIAL_WITH_LABELS });
IonWorldImageryStyle: AERIAL (default) | AERIAL_WITH_LABELS | ROAD
The geocoder option accepts false, an IonGeocodeProviderType, or a GeocoderService[].
IonGeocodeProviderType: DEFAULT | GOOGLE (required with Google tiles) | BING
import { Viewer, CartographicGeocoderService, IonGeocoderService, OpenCageGeocoderService } from "cesium";
// Multiple services (searched in order)
const viewer = new Viewer("cesiumContainer", {
geocoder: [
new CartographicGeocoderService(), // accepts "lat, lon" input
new IonGeocoderService({ scene: viewer.scene }),
],
});
const myGeocoder = {
async geocode(input, type) {
// type: GeocodeType.SEARCH or GeocodeType.AUTOCOMPLETE
const resp = await fetch(`https://api.example.com/search?q=${input}`);
const data = await resp.json();
return data.map((item) => ({
displayName: item.name,
destination: Cartesian3.fromDegrees(item.lon, item.lat),
}));
},
};
const viewer = new Viewer("cesiumContainer", { geocoder: [myGeocoder] });
import { Viewer, viewerDragDropMixin, viewerCesium3DTilesInspectorMixin,
viewerCesiumInspectorMixin, viewerPerformanceWatchdogMixin, viewerVoxelInspectorMixin } from "cesium";
const viewer = new Viewer("cesiumContainer");
// Drag-and-drop CZML/GeoJSON/KML loading
viewer.extend(viewerDragDropMixin, { dropTarget: "cesiumContainer", clearOnDrop: true });
viewer.dropError.addEventListener((handler, name, error) => console.error(error));
viewer.extend(viewerCesium3DTilesInspectorMixin); // 3D Tiles debug panel
viewer.extend(viewerCesiumInspectorMixin); // general scene inspector
viewer.extend(viewerPerformanceWatchdogMixin); // low-FPS warning
viewer.extend(viewerVoxelInspectorMixin); // voxel debug panel
| Property | Type |
|---|---|
viewer.scene | Scene |
viewer.camera | Camera |
viewer.entities | EntityCollection |
viewer.dataSources | DataSourceCollection |
viewer.imageryLayers | ImageryLayerCollection |
viewer.terrainProvider | TerrainProvider |
viewer.clock / clockViewModel | Clock / ClockViewModel |
viewer.canvas | HTMLCanvasElement |
viewer.screenSpaceEventHandler | ScreenSpaceEventHandler |
viewer.selectedEntity / trackedEntity | Entity |
viewer.shadows | boolean |
viewer.resolutionScale | number (default 1.0) |
await viewer.flyTo(entity, { duration: 3.0, offset: headingPitchRange }); // animated
await viewer.zoomTo(tileset); // instant
viewer.destroy(); // free all resources
import { Credit, FrameRateMonitor } from "cesium";
// Custom credit (showOnScreen = true)
viewer.creditDisplay.addStaticCredit(new Credit("Data by Example Corp", true));
// Monitor frame rate
const monitor = FrameRateMonitor.fromScene(viewer.scene);
monitor.lowFrameRate.addEventListener(() => console.warn("Low FPS"));
monitor.nominalFrameRate.addEventListener(() => console.log("FPS recovered"));
import { Ion, Viewer, Terrain, createOsmBuildingsAsync, Cartesian3, Math as CesiumMath } from "cesium";
Ion.defaultAccessToken = "YOUR_TOKEN";
const viewer = new Viewer("cesiumContainer", {
terrain: Terrain.fromWorldTerrain(), animation: false, timeline: false,
});
viewer.scene.primitives.add(await createOsmBuildingsAsync());
viewer.scene.camera.flyTo({
destination: Cartesian3.fromDegrees(-74.019, 40.6912, 750),
orientation: { heading: CesiumMath.toRadians(20), pitch: CesiumMath.toRadians(-20) },
});
const viewer = new Viewer("cesiumContainer", {
globe: false, skyAtmosphere: false, baseLayerPicker: false,
});
const viewer = new Viewer("cesiumContainer", {
requestRenderMode: true, maximumRenderTimeChange: Infinity,
});
// Call viewer.scene.requestRender() after programmatic changes
import { Viewer, ImageryLayer, OpenStreetMapImageryProvider } from "cesium";
const viewer = new Viewer("cesiumContainer", {
baseLayerPicker: false,
baseLayer: new ImageryLayer(new OpenStreetMapImageryProvider({
url: "https://tile.openstreetmap.org/",
})),
});
import { Viewer, SceneMode, WebMercatorProjection } from "cesium";
const viewer = new Viewer("cesiumContainer", {
sceneMode: SceneMode.COLUMBUS_VIEW, mapProjection: new WebMercatorProjection(),
});
requestRenderMode: true for mostly-static apps. Reduces CPU/GPU and battery drain. Call scene.requestRender() after changes.scene3DOnly: true when 2D/Columbus View is not needed. Saves GPU memory per geometry instance.animation: false, timeline: false) to reduce DOM overhead.msaaSamples: 1 on low-power devices. Default 4 balances quality.resolutionScale (e.g., 0.75) on HiDPI displays for better frame rates.Terrain.fromWorldTerrain() over await createWorldTerrainAsync() -- non-blocking with error events.requestVertexNormals: true on terrain for proper lighting at negligible cost.viewer.destroy() when removing from DOM to free WebGL contexts.npx claudepluginhub cesiumgs/cesiumjs-skills --plugin cesiumjs-skillsConfigures CesiumJS terrain providers (Ion, URL, ellipsoid, custom heightmap), samples terrain heights with sampleTerrain/sampleTerrainMostDetailed, and customizes globe atmosphere, sky, fog, lighting, and shadows.
Guides users through first interactions with the Cesium 3D globe via MCP tools, including camera navigation, entity creation, and layer loading.
Create 2D and 3D maps and scenes using ArcGIS Maps SDK for JavaScript. Initialize MapViews, SceneViews, layers, navigation; supports ESM imports, CDN dynamic imports, autocasting, explicit classes.