Develop

Starter Sample

Updated: May 8, 2026

Overview

This sample demonstrates the fundamental architecture of a Meta Spatial SDK application, including activity lifecycle, feature registration, GLXF scene loading, environment configuration, and Compose UI panels. It serves as the template project for the Getting started tutorial.

Learning objectives

Complete this guide to learn how to:
  • Structure an AppSystemActivity with the standard lifecycle methods (registerFeatures, onCreate, onSceneReady, registerPanels)
  • Register production and debug features using conditional logic
  • Load and configure a 3D scene using GLXF files exported from Meta Spatial Editor
  • Create a Compose UI panel and position it in 3D space using scene nodes
  • Set up a scene environment with reference space, lighting, IBL, and a skybox
  • Apply UISet theming to spatial panels with dark/light mode support

Requirements

  • Quest 2, Quest 3, or Quest 3S headset
  • Android development environment with Android Studio
Note: This guide assumes you have a working development environment. See Getting started for initial setup.

Get started

Clone or download the sample from the Meta Spatial SDK Samples repository. Open the StarterSample project in Android Studio. Connect your Quest device via USB or Wi-Fi, then run the app. For detailed build instructions and troubleshooting, see the project’s README.

Explore the sample

File / SceneWhat it demonstratesKey concepts
StarterSampleActivity.kt
Main activity with lifecycle methods, feature registration, GLXF loading, and environment setup
AppSystemActivity lifecycle, async scene loading with coroutines, scene configuration
WelcomePanel.kt
Compose UI panel with UISet theming
SpatialTheme, SpatialColorScheme, dark/light mode selection
app/scenes/Composition/Main.scene
Scene graph with two nodes: Environment (3D room model) and Panel (UI)
Scene composition, node positioning, panel binding via resource ID
app/scenes/collab_room/
3D collaboration room model with meshes, materials, and textures
GLXF model structure, mesh references, material assignment
app/build.gradle.kts
SDK dependencies and Meta Spatial Editor integration via spatial {} block
Scene export configuration, hot reload setup

Runtime behavior

When you run this sample, you see a furnished collaboration room environment rendered with the unlit shader, so it displays its textures without dynamic lighting. A spherical sky dome surrounds the scene, also unlit. A floating UI panel appears in front of you at approximately eye level, displaying the title Starter Sample and a brief description. The scene includes directional lighting and low-intensity image-based lighting from an environment map. The sample has no interactive elements; it is a static template for understanding project structure.

Key concepts

Activity lifecycle

The sample extends AppSystemActivity and overrides four lifecycle methods: registerFeatures(), onCreate(), onSceneReady(), and registerPanels(), in that order. The framework calls registerFeatures() first to collect feature instances, then triggers onSceneReady() when the spatial scene is ready for configuration. The registerPanels() method links Compose UI to scene nodes. See StarterSampleActivity.kt for the complete implementation.

Feature registration

The sample demonstrates conditional feature registration:
if (BuildConfig.DEBUG) {
  features.add(HotReloadFeature(this))
  features.add(OVRMetricsFeature(this, ...))
}
Production features (VRFeature, ComposeFeature) are always registered. Debug features, including hot reload, metrics overlay, cast input forwarding, and data model inspector, are conditionally added only in debug builds. This pattern keeps release builds lean. See StarterSampleActivity.kt for the full feature list.

GLXF scene loading

The sample loads the scene asynchronously in onCreate using a coroutine:
glXFManager.inflateGLXF(
    "apk:///scenes/Composition.glxf".toUri(),
    rootEntity = gltfxEntity!!,
    onLoaded = onLoaded,
)
The apk:/// URI scheme accesses assets bundled with the APK. The method creates a root entity, loads the scene asynchronously via coroutine, and provides an onLoaded callback that receives a GLXFInfo object with access to scene nodes by name. The sample uses this callback to override the environment mesh shader to SceneMaterial.UNLIT_SHADER. See the loadGLXF() method in StarterSampleActivity.kt.

Compose panel registration

Panel registration links a Compose UI to a scene node via a resource ID:
ComposeViewPanelRegistration(
    R.id.panel,
    composeViewCreator = { _, ctx ->
      ComposeView(ctx).apply { setContent { WelcomePanel() } }
    },
)
Notice how R.id.panel matches the panel: "@id/panel" property in the scene node definition. This binds the Compose UI to the panel node’s position and transform. The settingsCreator lambda configures the panel shape (QuadShapeOptions with width and height in meters), a transparent background style, and dp-per-meter display scaling. See StarterSampleActivity.kt for the complete panel registration.

UISet theming

The panel respects system dark/light theme:
SpatialTheme(colorScheme = getPanelTheme()) {
  Column(modifier = Modifier
      .clip(SpatialTheme.shapes.large)
      .background(brush = LocalColorScheme.current.panel))
}
The SpatialTheme wrapper provides access to typography, shapes, and color schemes from the UISet design system. LocalColorScheme.current.panel supplies the background brush. The getPanelTheme() function selects darkSpatialColorScheme() or lightSpatialColorScheme() based on isSystemInDarkTheme(), so the panel automatically adapts to the system setting. See WelcomePanel.kt for the complete implementation.

Extend the sample

Once you understand the baseline structure, you can extend this sample in several ways:
  • Add interactive elements using buttons, toggles, or Interaction SDK grabbable objects
  • Create custom ECS components and systems to implement game logic or data-driven behavior
  • Replace the collaboration room model with a different 3D environment by modifying the scene node’s document reference
For examples of these patterns, explore the Object3DSample, CustomComponentsSample, and HybridSample in the same repository.