Kit App Template Integration#

Note

Applies to: Spatial Extensions, Kit 109.0.3+, CloudXR 6

This integration reference covers integrating XR functionality into applications built with the Kit App Template.

Kit App Template Overview#

The Kit App Template (kit-app-template) is the standard starting point for building Omniverse Kit SDK-based applications. It provides:

  • Application Templates: Starting points for different app types

  • Extension Templates: Scaffolding for new extensions

  • Build System: repo.sh for building and packaging

  • Application Layers: Modular configuration system

Repository: kit-app-template

Three Integration Methods#

Method

Flexibility

Reusability

Complexity

Best For

Direct .kit

Low

Low

Low

Quick prototypes

Custom Bundle

High

High

Medium

Organizations

Application Layer

Medium

Medium

Medium

Deployment configs

Method A: Direct .kit File Integration#

Add XR directly to your application’s .kit file.

Step 1: Create Application with Kit App Template#

# Initialize kit app template (if not already)
git clone https://github.com/NVIDIA-Omniverse/kit-app-template.git
cd kit-app-template

# Create new application
./repo.sh template new

# Follow prompts:
# - Choose: Application
# - Template: Kit Base Editor (or USD Viewer, USD Composer, etc.)
# - Name: my_xr_app

This creates:

apps/
└── my_xr_app/
    ├── my_xr_app.kit
    └── ...

Step 2: Add XR Bundle to .kit File#

# apps/my_xr_app/my_xr_app.kit

[package]
title = "My XR Application"
version = "1.0.0"
description = "XR-enabled application"
keywords = ["xr", "vr"]

[dependencies]
# Existing dependencies...
"omni.kit.uiapp" = {}
"omni.kit.viewport.window" = {}
# ... other deps ...

# Add XR bundle
"omni.kit.xr.bundle.generic" = {}  # Cross-platform
# OR
# "omni.kit.xr.bundle.apple_vision_pro" = {}  # For AVP
# "omni.kit.xr.bundle.quest" = {}  # For Quest (if available)

[settings]
# Optional: XR-specific settings
defaults.xr.activeProfile = "vr"
defaults.xr.system.display = "OpenXR"
defaults.xr.profile.vr.renderQuality = "balanced"

Step 3: Create Startup Extension#

Create an extension to auto-start XR:

./repo.sh template new

# Choose: Extension
# Template: basic_python
# Name: my_xr_app.startup
# exts/my_xr_app.startup/my_xr_app/startup/extension.py

import omni.ext
import omni.kit.xr.core
import carb.events

class MyXRAppStartupExtension(omni.ext.IExt):
    """Auto-start XR on application launch."""
    
    def on_startup(self, ext_id):
        print("My XR App: Starting XR")
        
        self.xr_core = omni.kit.xr.core.XRCore.get_singleton()
        
        # Wait for XR system to be ready
        self._wait_for_xr_ready()
    
    def _wait_for_xr_ready(self):
        """Wait for XR system, then enable profile."""
        import omni.kit.app
        
        async def enable_xr_when_ready():
            # Wait a frame for XR system to initialize
            await omni.kit.app.get_app().next_update_async()
            
            # Enable VR profile
            self.xr_core.request_enable_profile("vr")
            print("My XR App: VR profile enabled")
        
        import asyncio
        asyncio.ensure_future(enable_xr_when_ready())
    
    def on_shutdown(self):
        print("My XR App: Shutting down")
        
        # Disable XR
        if self.xr_core and self.xr_core.is_xr_enabled():
            self.xr_core.request_disable_profile()
# exts/my_xr_app.startup/config/extension.toml

[package]
version = "1.0.0"
title = "My XR App Startup"
description = "Auto-start XR for My XR App"

[dependencies]
"omni.kit.xr.core" = {}

[[python.module]]
name = "my_xr_app.startup"

Step 4: Add Startup Extension to App#

# apps/my_xr_app/my_xr_app.kit

[dependencies]
"omni.kit.xr.bundle.generic" = {}
"my_xr_app.startup" = {}  # Add startup extension

[settings.app.exts]
folders.'++' = [
    "${app}/../../exts"  # Include local extensions
]

Step 5: Build and Run#

# Build
./repo.sh build

# Run
./repo.sh launch --config=apps/my_xr_app/my_xr_app.kit

# Or directly
_build/linux-x86_64/release/kit/kit --enable apps/my_xr_app/my_xr_app.kit

Method B: Custom Bundle Extension#

Create a reusable XR bundle for your organization, then use across apps.

Step 1: Create Custom Bundle#

See Custom Bundles Guide for details.

# Create bundle extension
mkdir -p exts/my_company.xr.bundle.custom/config
# exts/my_company.xr.bundle.custom/config/extension.toml

[package]
version = "1.0.0"
title = "My Company XR Bundle"
description = "Custom XR configuration"

[dependencies]
"omni.kit.xr.core" = {}
"omni.kit.xr.system.openxr" = {}
"omni.kit.xr.system.simulatedxr" = {}
"omni.kit.xr.ui.stage" = {}
"omni.kit.xr.ui.window.profile" = {}
"omni.kit.xr.ui.window.viewport" = {}

[settings]
defaults.xr.activeProfile = "vr"
defaults.xr.profile.vr.renderQuality = "balanced"
# ... more settings ...

Step 2: Use Bundle in Multiple Apps#

# apps/app1/app1.kit
[dependencies]
"my_company.xr.bundle.custom" = {}

[settings.app.exts]
folders.'++' = ["${app}/../../exts"]
# apps/app2/app2.kit
[dependencies]
"my_company.xr.bundle.custom" = {}  # Same bundle

[settings.app.exts]
folders.'++' = ["${app}/../../exts"]

Step 3: Version and Publish#

# Package bundle
./repo.sh package --ext my_company.xr.bundle.custom

# Publish to your extension registry
./repo.sh publish --ext my_company.xr.bundle.custom --registry my_company_registry

Method C: Application Layer#

Create modular deployment configurations using application layers.

Step 1: Create Base Application#

# apps/my_base_app/my_base_app.kit

[package]
title = "My Base Application"
version = "1.0.0"
description = "Base application without XR"

[dependencies]
# Core dependencies (no XR)
"omni.kit.uiapp" = {}
"omni.kit.viewport.window" = {}
"omni.kit.property.bundle" = {}
# ... application-specific extensions ...

[settings]
# Base application settings
app.name = "My Base Application"
app.window.title = "My Application"

Step 2: Create XR Application Layer#

# apps/my_app_xr_layer/my_app_xr_layer.kit

[package]
title = "My Application - XR Mode"
version = "1.0.0"
description = "XR layer for My Application"
keywords = ["app", "layer", "xr"]

[dependencies]
# Reference base application
"my.base.app" = {}

# Add XR support
"omni.kit.xr.bundle.generic" = {}

# Optional: XR startup extension
"my_xr_app.startup" = {}

[settings]
# Override app name for XR mode
app.name = "My Application (XR Mode)"
app.window.title = "My Application - XR"

# XR-specific settings
defaults.xr.activeProfile = "vr"
defaults.xr.system.display = "OpenXR"

# Performance tweaks for XR
rtx.ecoMode.enabled = false
rtx.post.aa.op = 3

[settings.app.exts]
folders.'++' = ["${app}/../../exts"]

Step 3: Create Additional Layers (Optional)#

# apps/my_app_streaming/my_app_streaming.kit
# Streaming layer

[package]
title = "My Application - Streaming"
version = "1.0.0"

[dependencies]
"my.base.app" = {}
"omni.kit.livestream.app" = {}

[settings]
livestream.enabled = true
# ... streaming settings ...
# apps/my_app_xr_streaming/my_app_xr_streaming.kit
# XR + Streaming combined

[package]
title = "My Application - XR Streaming"
version = "1.0.0"

[dependencies]
"my.base.app" = {}
"omni.kit.xr.bundle.generic" = {}
"omni.kit.livestream.app" = {}
"my_xr_app.startup" = {}

[settings]
# XR settings
defaults.xr.activeProfile = "vr"

# Streaming settings
livestream.enabled = true

Step 4: Launch Different Configurations#

# Desktop mode (no XR)
./repo.sh launch --config=apps/my_base_app/my_base_app.kit

# XR mode
./repo.sh launch --config=apps/my_app_xr_layer/my_app_xr_layer.kit

# Streaming mode
./repo.sh launch --config=apps/my_app_streaming/my_app_streaming.kit

# XR + Streaming
./repo.sh launch --config=apps/my_app_xr_streaming/my_app_xr_streaming.kit

Directory Structure#

kit-app-template/
├── apps/
│   ├── my_base_app/
│   │   └── my_base_app.kit
│   ├── my_app_xr_layer/
│   │   └── my_app_xr_layer.kit
│   ├── my_app_streaming/
│   │   └── my_app_streaming.kit
│   └── my_app_xr_streaming/
│       └── my_app_xr_streaming.kit
├── exts/
│   ├── my_xr_app.startup/
│   └── my_company.xr.bundle.custom/
└── repo.toml

Build and Deployment Workflows#

Development Workflow#

# 1. Build application
./repo.sh build --config=apps/my_xr_app/my_xr_app.kit

# 2. Run locally
./repo.sh launch --config=apps/my_xr_app/my_xr_app.kit

# 3. Package for distribution
./repo.sh package --config=apps/my_xr_app/my_xr_app.kit

CI/CD Integration#

# .github/workflows/build-xr-app.yml

name: Build XR Application

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      
      - name: Build Application
        run: |
          ./repo.sh build --config=apps/my_xr_app/my_xr_app.kit
      
      - name: Package Application
        run: |
          ./repo.sh package --config=apps/my_xr_app/my_xr_app.kit
      
      - name: Upload Artifact
        uses: actions/upload-artifact@v2
        with:
          name: my-xr-app
          path: _build/packages/

Multi-Platform Builds#

# Build for Windows
./repo.sh build --config=apps/my_xr_app/my_xr_app.kit --platform windows-x86_64

# Build for Linux
./repo.sh build --config=apps/my_xr_app/my_xr_app.kit --platform linux-x86_64

# Package all
./repo.sh package --config=apps/my_xr_app/my_xr_app.kit --all

Configuration Management#

Environment-Specific Settings#

# apps/my_xr_app/my_xr_app.kit

[settings]
# Development settings
[settings.dev]
xr.simulatedxr.enabled = true
defaults.xr.system.display = "SimulatedXR"

# Production settings
[settings.prod]
defaults.xr.system.display = "OpenXR"
persistent.xr.system.openxr.runtime = "system"

Runtime Configuration#

# Command-line override
# ./repo.sh launch --config=apps/my_xr_app/my_xr_app.kit \
#   --/persistent/xr/profile/vr/renderQuality=performance

# In code
import carb.settings

settings = carb.settings.get_settings()

# Check environment
import os
if os.getenv("XR_DEV_MODE"):
    settings.set("/xr/simulatedxr/enabled", True)
    settings.set("/xr/system/display", "SimulatedXR")

Testing XR Applications#

Unit Tests#

# exts/my_xr_app.tests/my_xr_app/tests/test_xr_setup.py

import omni.kit.test
import omni.kit.xr.core

class TestXRSetup(omni.kit.test.AsyncTestCase):
    async def setUp(self):
        """Set up test."""
        pass
    
    async def tearDown(self):
        """Clean up test."""
        pass
    
    async def test_xr_enabled(self):
        """Test XR can be enabled."""
        xr_core = omni.kit.xr.core.XRCore.get_singleton()
        
        # Enable VR profile
        xr_core.request_enable_profile("vr")
        
        # Wait for XR to enable
        for _ in range(60):  # Wait up to 60 frames
            await omni.kit.app.get_app().next_update_async()
            if xr_core.is_xr_enabled():
                break
        
        # Verify enabled
        self.assertTrue(xr_core.is_xr_enabled())
        
        # Disable
        xr_core.request_disable_profile()

Run Tests#

# Run all tests
./repo.sh test

# Run specific test
./repo.sh test --filter=test_xr_setup

Troubleshooting#

Extension Not Found#

Issue: Custom bundle or extension not loading

Solution:

[settings.app.exts]
folders.'++' = [
    "${app}/../../exts",  # Local extensions
    "/absolute/path/to/extensions"  # Absolute path if needed
]

XR Not Auto-Starting#

Issue: XR doesn’t start automatically

Check:

  1. Startup extension is in dependencies

  2. Extension is enabled in logs

  3. No errors in console

Debug:

# In startup extension
import carb
carb.log_info("XR Startup: Attempting to enable VR")
self.xr_core.request_enable_profile("vr")
carb.log_info("XR Startup: Request sent")

Settings Not Applied#

Issue: Application layer settings not overriding base

Solution: Ensure layer is loaded after base:

[dependencies]
"my.base.app" = {}  # Load base first
"omni.kit.xr.bundle" = {}  # Then XR

# Settings apply in order loaded

Best Practices#

Application Structure#

  1. Modular Design: Separate base app from XR layer

  2. Reusable Bundles: Share XR configs through bundles

  3. Clear Naming: Use descriptive names for layers

  4. Version Control: Track all .kit files in git

Settings Management#

  1. Defaults in Bundles: Set defaults in custom bundles

  2. Overrides in Apps: Override in app .kit files

  3. Runtime Flexibility: Allow command-line overrides

  4. Document Changes: Comment settings in .kit files

Testing#

  1. Automated Tests: Test XR initialization

  2. CI/CD: Build and test on every commit

  3. Multi-Platform: Test on all target platforms

  4. SimulatedXR: Use for automated testing

Next Steps#