How to Configure a Cesium Ion Token for 3D Globe Rendering in GeoLibre

Set VITE_CESIUM_TOKEN or CESIUM_TOKEN in your environment, then pass the token to the CesiumCanvas component via its ionToken prop to enable Cesium Ion world imagery and terrain.

GeoLibre renders interactive 3D globes using CesiumJS through the CesiumCanvas component in the @geolibre/map package. Configuring a Cesium Ion token unlocks high-resolution world terrain and satellite imagery, while a missing token triggers an automatic fallback to OpenStreetMap. This guide walks through every layer of the token configuration system as implemented in the opengeos/GeoLibre source code.

Where the Token Originates

GeoLibre's token resolution follows a priority chain from build-time injection to runtime environment lookup.

Runtime Environment Detection

The @geolibre/core package exposes getCesiumIonToken() in packages/core/src/runtime-env.ts. This function checks for two environment variable names:

export function getCesiumIonToken(env?: Record<string, string | undefined>): string | undefined {
  const runtimeEnv = env ?? process.env;
  const trimmed = runtimeEnv.VITE_CESIUM_TOKEN?.trim() || runtimeEnv.CESIUM_TOKEN?.trim();
  return trimmed?.length ? trimmed : undefined;
}
  • VITE_CESIUM_TOKEN — Takes precedence; injected by Vite at build time for client-side access
  • CESIUM_TOKEN — Fallback for server-side or non-Vite environments

The function trims whitespace and returns undefined for empty strings, preventing invalid token errors.

Build-Time Injection

The desktop app configuration at apps/geolibre-desktop/vite.config.ts bridges the gap between bare CESIUM_TOKEN and Vite's required VITE_ prefix:

// vite.config.ts (excerpt)
export default defineConfig({
  define: {
    'import.meta.env.VITE_CESIUM_TOKEN': JSON.stringify(process.env.CESIUM_TOKEN)
  }
})

This ensures existing CESIUM_TOKEN values are automatically available to the client bundle without manual renaming.

How the Token Propagates to the Globe

UI Layer: MapGrid

The MapGrid component in apps/geolibre-desktop/src/components/layout/MapGrid.tsx reads the token at render time using React state:

const [cesiumToken, setCesiumToken] = useState<string | undefined>(() => getCesiumIonToken());

Storing the token in state allows runtime refresh without rebuilding the application—users can update their token through a settings dialog and call setCesiumToken(getCesiumIonToken()) to apply changes immediately.

Canvas Layer: CesiumCanvas

The CesiumCanvas component receives the token via its ionToken prop and applies it during CesiumJS initialization in packages/map/src/CesiumCanvas.tsx:

const ionTokenRef = useRef<string | undefined>(ionToken);

// After dynamic import of CesiumJS
if (ionTokenRef.current) {
  Cesium.Ion.defaultAccessToken = ionTokenRef.current;
}

The token assignment happens once, before viewer construction, ensuring all Ion-dependent resources use authenticated requests.

What the Token Enables

With a Valid Token

When ionToken is present, CesiumCanvas configures:

  • Cesium World Terrain — High-resolution global elevation via Cesium.createWorldTerrainAsync()
  • Cesium Ion Imagery — Default Bing Maps satellite layers from Cesium's asset server

Without a Token

The component automatically falls back to OpenStreetMap imagery by setting a custom baseLayer in the viewer constructor. The 3D globe remains functional but lacks premium terrain and imagery quality.

Configuration Methods

Create or edit .env in your project root:

VITE_CESIUM_TOKEN=your-ion-jwt-token

Vite injects this value at build time. getCesiumIonToken() picks it up automatically in both development and production.

Method 2: Pass Token Directly to CesiumCanvas

For custom implementations or testing:

import { CesiumCanvas } from "@geolibre/map";

<CesiumCanvas 
  viewId="main-globe" 
  ionToken={process.env.VITE_CESIUM_TOKEN} 
/>

Method 3: Runtime Refresh from UI

Enable user-controlled token updates:

import { getCesiumIonToken } from "@geolibre/core";

function TokenSettings() {
  const [cesiumToken, setCesiumToken] = useState<string | undefined>(
    () => getCesiumIonToken()
  );

  const refreshToken = () => setCesiumToken(getCesiumIonToken());

  return (
    <div>
      <input 
        type="text" 
        onChange={(e) => {
          // Persist to env or storage, then:
          refreshToken();
        }}
      />
      <CesiumCanvas viewId="globe" ionToken={cesiumToken} />
    </div>
  );
}

Method 4: Programmatic Fallback Handling

Detect missing tokens for conditional UI messaging:

const token = getCesiumIonToken();

if (!token) {
  console.warn("Cesium Ion token not set – OSM fallback active");
  showNotification("Globe running in basic mode. Add Cesium token for terrain.");
}

Architecture Reference

File Purpose
packages/map/src/CesiumCanvas.tsx Creates Cesium viewer, applies Cesium.Ion.defaultAccessToken, manages terrain fallback
packages/core/src/runtime-env.ts Exports getCesiumIonToken() with VITE_CESIUM_TOKEN > CESIUM_TOKEN priority
apps/geolibre-desktop/vite.config.ts Injects CESIUM_TOKEN into VITE_CESIUM_TOKEN for client access
apps/geolibre-desktop/src/components/layout/MapGrid.tsx UI integration: reads token into React state for live updates

Summary

  • Primary method: Set VITE_CESIUM_TOKEN in .env for automatic detection by getCesiumIonToken()
  • Build bridge: vite.config.ts maps CESIUM_TOKEN to VITE_CESIUM_TOKEN for compatibility
  • Runtime propagation: MapGrid reads via getCesiumIonToken(), CesiumCanvas receives via ionToken prop
  • Application: Assigned to Cesium.Ion.defaultAccessToken before viewer initialization
  • Fallback: Missing token triggers OpenStreetMap imagery instead of Cesium Ion resources

Frequently Asked Questions

What happens if I don't configure a Cesium Ion token?

The globe renders with OpenStreetMap as the base imagery layer and flat terrain. The 3D visualization remains functional but lacks high-resolution satellite imagery and accurate elevation data provided by Cesium Ion services.

Can I change the token without rebuilding the application?

Yes. Store the token in React state as implemented in MapGrid.tsx, then update that state when users modify their token through a settings UI. The CesiumCanvas component re-renders and applies the new token to Cesium.Ion.defaultAccessToken.

Why does GeoLibre use VITE_CESIUM_TOKEN instead of just CESIUM_TOKEN?

Vite requires environment variables exposed to the client to use the VITE_ prefix for security. The getCesiumIonToken() helper accepts both names, with VITE_CESIUM_TOKEN taking precedence. The build configuration automatically maps bare CESIUM_TOKEN to the prefixed variant.

Where can I obtain a Cesium Ion token?

Create a free account at cesium.com/ion, then generate an access token from your dashboard. Free tiers include sufficient credits for development and moderate usage.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →