📋 Configuration Schema Reference¶
Complete TypeScript reference for ExperienceConfig - the main configuration object for WebXR Gallery experiences.
Table of Contents¶
- ExperienceConfig
- ExperienceStage
- SkyboxConfig
- HotspotConfig
- NavigationConfig
- ModelConfig
- PlaneConfig
- LightConfig
ExperienceConfig¶
Root configuration object for an entire experience.
interface ExperienceConfig {
experience: ExperienceMetadata;
stages: ExperienceStage[];
navigation?: NavigationConfig;
}
ExperienceMetadata¶
interface ExperienceMetadata {
title: string; // Experience name
description?: string; // Brief description
author?: string; // Creator name
thumbnailUrl?: string; // Preview image URL
createdAt?: string; // ISO 8601 timestamp
updatedAt?: string; // ISO 8601 timestamp
}
Example:
{
"experience": {
"title": "Museum Virtual Tour",
"description": "Explore our collection in 360°",
"author": "Jane Doe",
"thumbnailUrl": "https://cdn.com/thumb.jpg",
"createdAt": "2025-12-02T10:00:00Z",
"updatedAt": "2025-12-02T15:30:00Z"
}
}
ExperienceStage¶
A single stage (scene) in the experience.
interface ExperienceStage {
id: string; // Unique identifier
name: string; // Display name
skybox?: SkyboxConfig; // 360° background
models?: ModelConfig[]; // 3D models
planes?: PlaneConfig[]; // 2D planes (images/videos)
lights?: LightConfig[]; // Scene lighting
hotspots?: HotspotConfig[]; // Interactive hotspots
audioUrl?: string; // Background audio
audioVolume?: number; // 0-1, default 1
audioLoop?: boolean; // Loop audio, default true
location?: GeoCoordinates; // Geographic position
initialCameraTarget?: Vector3Config; // Where camera looks (first stage only)
}
Vector3Config¶
interface Vector3Config {
x: number; // X coordinate
y: number; // Y coordinate
z: number; // Z coordinate
}
GeoCoordinates¶
interface GeoCoordinates {
lat: number; // Latitude (-90 to 90)
lng: number; // Longitude (-180 to 180)
}
Example:
{
"id": "lobby",
"name": "Main Lobby",
"skybox": {
"type": "video",
"url": "https://cdn.com/lobby.mp4",
"autoplay": true
},
"hotspots": [
{
"id": "info-desk",
"type": "info",
"position": { "x": 0, "y": 0, "z": 100 },
"infoTitle": "Welcome",
"infoBody": "Welcome to our museum!"
}
],
"audioUrl": "https://cdn.com/ambient.mp3",
"audioVolume": 0.5,
"location": {
"lat": 40.7128,
"lng": -74.0060
},
"initialCameraTarget": { "x": 0, "y": 0, "z": 100 }
}
SkyboxConfig¶
360° background configuration.
interface SkyboxConfig {
type: 'video' | 'image' | 'color';
url?: string; // Media URL (required for video/image)
hlsUrl?: string; // HLS manifest URL (.m3u8) for streaming
thumbnailUrl?: string; // Preview image (video only)
color?: string; // Hex color (type='color')
autoplay?: boolean; // Video: auto-play, default true
loop?: boolean; // Video: loop, default true
rotation?: number; // Rotation in degrees, default 0
// Multi-variant support (advanced)
variants?: {
desktop?: TextureVariant;
mobile?: TextureVariant;
tablet?: TextureVariant;
vr?: TextureVariant;
fallback: TextureVariant; // Required
};
}
TextureVariant¶
interface TextureVariant {
url: string;
format: 'ktx2-uastc' | 'ktx2-etc1s' | 'jpg' | 'png';
resolution?: string; // e.g., "4096x2048"
quality?: number; // ETC1S quality (1-255)
fileSize?: number; // Bytes
}
Examples:
Video Skybox:
{
"type": "video",
"url": "https://cdn.com/tour.mp4",
"hlsUrl": "https://stream.mux.com/abc123.m3u8",
"thumbnailUrl": "https://cdn.com/tour-thumb.jpg",
"autoplay": true,
"loop": true,
"rotation": 90
}
Image Skybox:
Color Skybox:
Multi-Variant (Advanced):
{
"type": "image",
"variants": {
"desktop": {
"url": "https://cdn.com/pano-4k.ktx2",
"format": "ktx2-uastc",
"resolution": "4096x2048"
},
"mobile": {
"url": "https://cdn.com/pano-2k.ktx2",
"format": "ktx2-etc1s",
"resolution": "2048x1024",
"quality": 128
},
"fallback": {
"url": "https://cdn.com/pano.jpg",
"format": "jpg"
}
}
}
HotspotConfig¶
Interactive 3D hotspots.
interface HotspotConfig {
id: string; // Unique ID
position: Vector3Config; // 3D position
type: 'info' | 'audio' | 'both' | 'navigation';
// Visual customization
color?: string; // Hex color, default "#4A90E2"
size?: number; // Radius in meters
opacity?: number; // 0-1, default 0.9
label?: string; // Text label
customIconUrl?: string; // Custom PNG icon URL
// Portal-specific (navigation type)
targetStageId?: string; // Which stage to navigate to
portalEffectStyle?: PortalEffectStyle;
portalRestSize?: number; // Scale at rest
portalHoverSize?: number; // Scale on hover
portalColor?: string; // Hex color
initialViewDirection?: Vector3Config; // Camera look direction
// Info content (info/both types)
infoTitle?: string;
infoBody?: string;
infoImageUrl?: string;
infoImageAspectRatio?: number; // Width/height
infoVideoUrl?: string;
infoLinks?: InfoLink[];
// Audio (audio/both types)
audioUrl?: string;
audioLoop?: boolean; // Default true
audioVolume?: number; // 0-1, default 1
audioSpatial?: boolean; // 3D spatial audio, default true
audioRolloffFactor?: number; // Distance attenuation, default 1
audioMaxDistance?: number; // Max audible distance, default 100
}
PortalEffectStyle¶
type PortalEffectStyle =
| 'liquid' // Flowing liquid metal
| 'shimmer' // Shimmering particles
| 'warp' // Space-time warp
| 'minimal'; // Simple glow
InfoLink¶
Examples:
Info Hotspot:
{
"id": "artwork-1",
"type": "info",
"position": { "x": 50, "y": 10, "z": 80 },
"color": "#FFD700",
"label": "Starry Night",
"infoTitle": "The Starry Night",
"infoBody": "Vincent van Gogh, 1889...",
"infoImageUrl": "https://cdn.com/starry-night.jpg",
"infoLinks": [
{
"label": "Learn More",
"url": "https://en.wikipedia.org/wiki/The_Starry_Night",
"icon": "external"
}
]
}
Audio Hotspot:
{
"id": "ambient-1",
"type": "audio",
"position": { "x": 0, "y": 50, "z": 100 },
"audioUrl": "https://cdn.com/birds.mp3",
"audioSpatial": true,
"audioRolloffFactor": 2,
"audioMaxDistance": 50
}
Navigation Portal:
{
"id": "portal-gallery-2",
"type": "navigation",
"position": { "x": 0, "y": 0, "z": -100 },
"targetStageId": "gallery-2",
"portalEffectStyle": "liquid",
"portalColor": "#4A90E2",
"portalRestSize": 1.0,
"portalHoverSize": 1.2,
"initialViewDirection": { "x": 0, "y": 0, "z": 1 }
}
NavigationConfig¶
Geographic navigation system.
interface NavigationConfig {
type: 'floorplan' | 'map' | 'none';
showMinimap?: boolean; // Show corner minimap, default true
markers: NavigationMarker[];
// Map-specific
mapConfig?: {
tileLayer?: string; // 'streets' | 'satellite' | 'outdoors' | 'dark'
initialZoom?: number; // Default 15
maxZoom?: number; // Default 18
minZoom?: number; // Default 10
};
// Floor plan-specific
floorPlan?: FloorPlanConfig; // Single floor
floorPlans?: FloorPlanConfig[]; // Multi-floor
// Legacy (deprecated)
displayMode?: 'minimap' | 'fullscreen' | 'both' | 'none';
minimapPosition?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
minimapSize?: 'small' | 'medium' | 'large';
}
NavigationMarker¶
interface NavigationMarker {
stageId: string; // Which stage?
label?: string; // Display name
// Geographic (maps)
geoPosition?: GeoCoordinates;
// Floor plan
floorPlanPosition?: FloorPlanPosition;
// Visual
icon?: 'default' | 'star' | 'info' | 'camera' | 'video' | 'audio';
customIconUrl?: string;
color?: string;
// Metadata
placeName?: string; // From geocoding
}
FloorPlanPosition¶
interface FloorPlanPosition {
x: number; // 0-1 (0=left, 1=right)
y: number; // 0-1 (0=top, 1=bottom)
}
FloorPlanConfig¶
interface FloorPlanConfig {
floor?: number; // Floor number (1-indexed)
name?: string; // Floor name
imageUrl: string; // Floor plan image
}
Examples:
Map Navigation:
{
"type": "map",
"showMinimap": true,
"mapConfig": {
"tileLayer": "streets",
"initialZoom": 15
},
"markers": [
{
"stageId": "stage-1",
"label": "Main Entrance",
"geoPosition": { "lat": 40.7128, "lng": -74.0060 },
"icon": "star",
"color": "#FF0000"
}
]
}
Floor Plan Navigation:
{
"type": "floorplan",
"showMinimap": true,
"floorPlans": [
{
"floor": 1,
"name": "Ground Floor",
"imageUrl": "https://cdn.com/floor1.png"
},
{
"floor": 2,
"name": "Second Floor",
"imageUrl": "https://cdn.com/floor2.png"
}
],
"markers": [
{
"stageId": "lobby",
"label": "Main Lobby",
"floorPlanPosition": { "x": 0.5, "y": 0.3 }
}
]
}
ModelConfig¶
3D model configuration (glTF/GLB).
interface ModelConfig {
id?: string; // Optional ID
url: string; // Model URL
position?: Vector3Config; // Position, default {0,0,0}
rotation?: Vector3Config; // Rotation (radians), default {0,0,0}
scale?: Vector3Config | number; // Scale, default 1
}
Example:
{
"url": "https://cdn.com/sculpture.glb",
"position": { "x": 0, "y": 0, "z": 50 },
"rotation": { "x": 0, "y": 1.57, "z": 0 },
"scale": 2.0
}
PlaneConfig¶
2D plane (image/video) in 3D space.
interface PlaneConfig {
type: 'image' | 'video';
url: string;
hlsUrl?: string; // HLS for video
position?: Vector3Config;
rotation?: Vector3Config; // Radians
scale?: { width: number; height: number };
autoplay?: boolean; // Video only
loop?: boolean; // Video only
muted?: boolean; // Video only
}
Example:
{
"type": "image",
"url": "https://cdn.com/poster.jpg",
"position": { "x": 0, "y": 20, "z": 80 },
"rotation": { "x": 0, "y": 0, "z": 0 },
"scale": { "width": 30, "height": 40 }
}
LightConfig¶
Scene lighting configuration.
interface LightConfig {
type: 'hemispheric' | 'directional' | 'point' | 'spot';
intensity?: number; // 0-2, default 1
diffuse?: string; // Hex color, default "#FFFFFF"
specular?: string; // Hex color, default "#FFFFFF"
// Hemispheric only
groundColor?: string;
// Directional/Hemispheric
direction?: Vector3Config;
// Point/Spot
position?: Vector3Config;
range?: number;
// Spot only
angle?: number; // Radians
exponent?: number; // 0-128
}
Examples:
Hemispheric Light:
{
"type": "hemispheric",
"intensity": 0.7,
"diffuse": "#FFFFFF",
"groundColor": "#444444",
"direction": { "x": 0, "y": 1, "z": 0 }
}
Point Light:
Validation Rules¶
Required Fields¶
experience.title- Must not be emptystages- Must have at least one stagestage.id- Must be unique across all stagesstage.name- Must not be emptyhotspot.id- Must be unique within stage
Value Constraints¶
audioVolume: 0-1opacity: 0-1lat: -90 to 90lng: -180 to 180floorPlanPosition.x: 0-1floorPlanPosition.y: 0-1- Colors: Must be valid hex (#RGB or #RRGGBB)
URL Validation¶
urlfields must be valid HTTP/HTTPS URLs- For local development:
http://localhost:*allowed - CORS headers must be configured for remote URLs
Migration Guides¶
v2.0 → v2.1¶
New Fields: - stage.initialCameraTarget - Camera orientation (first stage only) - hotspot.customIconUrl - Custom PNG icons - navigation.showMinimap - Simplified minimap control - marker.placeName - Auto-filled by geocoding
Deprecated Fields: - navigation.displayMode - Use showMinimap instead - navigation.minimapPosition - Now fixed at bottom-left - navigation.minimapSize - Now fixed at 100x100px
Breaking Changes: - None! All deprecated fields still work for backward compatibility.
Next Steps¶
- Hotspots Guide - Interactive elements
- Navigation System - Maps and floor plans
- Self-Hosting - Host your own tours