Generate robotics simulation environments in minutes, not weeks.
Built on the World Labs Marble API — shipped on launch day (January 21, 2025).
On January 21, 2025, World Labs launched their Marble API. Within hours, I had a working full-stack application generating 3D robotics environments from text prompts.
| Milestone | Time |
|---|---|
| API docs released | Hour 0 |
| API client implemented | Hour 2 |
| Generation flow working | Hour 4 |
| 3D viewer integrated | Hour 6 |
| Full demo deployed | Hour 8 |
How I went about it:
- Identify a specific use case (robotics simulation) rather than building a generic demo
- Read the docs deeply — Implemented the API endpoints
- Make technical bets — chose SparkJS for Gaussian splat rendering based on World Labs' own recommendations
- Ship something real — A tool researchers could actually use
Robotics researchers face a bottleneck: environment diversity for simulation training.
| Pain Point | Impact |
|---|---|
| Manual 3D modeling takes time | Slows R&D velocity |
| Limited environment variety | Poor sim-to-real transfer |
| Expensive creation time per environment | High operational costs |
The result: Robots trained in simulation fail in the real world because they've never seen enough environmental variety.
RoboSim Studio + World Labs Marble API:
| Capability | Benefit |
|---|---|
| Text → 3D World in <5 minutes | 100x faster than manual modeling |
| Unlimited variety | Better domain randomization |
| Physics mesh export | Ready for use |
Describe your simulation environment in plain English. Four robotics-optimized presets included:
- Warehouse — shelving, pallets, loading docks
- Factory — assembly lines, machinery, industrial equipment
- Hospital — corridors, patient rooms, medical equipment
- Office — desks, meeting rooms, common areas
| Mode | Time | Quality | Physics Mesh |
|---|---|---|---|
| Draft (Marble 0.1-mini) | ~30-45 sec | Good | No |
| Full (Marble 0.1-plus) | ~5 min | Best | Yes |
Gaussian splat viewer with real-time rendering:
- Mouse drag: Orbit camera
- Scroll: Zoom in/out
- Quality selector: 100k / 500k / full resolution splats
This demo implements the complete World Labs Marble API integration:
| Endpoint | Implementation | Purpose |
|---|---|---|
POST /worlds:generate |
generateWorldFromText(), generateWorldFromImageBase64() |
Create worlds from text or images |
GET /operations/{id} |
pollOperation() |
Check generation status |
GET /worlds/{id} |
getWorld() |
Fetch world details and assets |
POST /worlds:list |
listWorlds() |
Retrieve all generated worlds |
// Centralized API client with proper error handling
async function apiFetch<T>(path: string, options: RequestInit = {}): Promise<T> {
const response = await fetch(`${API_BASE_URL}/${path}`, {
...options,
headers: {
"WLT-Api-Key": getApiKey(), // Server-side only
"Content-Type": "application/json",
},
});
// ... error handling with custom error classes
}- API key never exposed to client — All World Labs calls go through Next.js API routes
- Server-side environment variables —
WLT_API_KEYonly accessible in API routes - No client-side secrets — Frontend only talks to our own
/api/*endpoints
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router) |
| Language | TypeScript 5 |
| UI | React 19 |
| Styling | Tailwind CSS 4 |
| 3D Rendering | SparkJS + Three.js |
| API | World Labs Marble API |
| Deployment | Vercel |
┌─────────────────────────────────────────────────────────────┐
│ Next.js Frontend │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Generation │ │ Worlds │ │ 3D Viewer │ │
│ │ Form │ │ Gallery │ │ (SparkJS + Three.js)│ │
│ └──────┬──────┘ └──────┬──────┘ └──────────┬──────────┘ │
└─────────┼────────────────┼────────────────────┼─────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ Next.js API Routes │
│ POST /api/worlds GET /api/worlds GET /api/worlds/[id]│
│ GET /api/operations/[id] │
└─────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ world-api.ts (API Client) │
│ • generateWorldFromText() • pollOperation() │
│ • generateWorldFromImage() • getWorld() │
│ • listWorlds() • waitForCompletion() │
└─────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ World Labs Marble API │
│ POST /worlds:generate GET /operations/{id} │
│ GET /worlds/{id} POST /worlds:list │
└─────────────────────────────────────────────────────────────┘
robosim-studio/
├── src/
│ ├── app/
│ │ ├── api/
│ │ │ ├── worlds/
│ │ │ │ ├── route.ts # POST generate, GET list
│ │ │ │ └── [id]/route.ts # GET world by ID
│ │ │ └── operations/
│ │ │ └── [id]/route.ts # GET operation status
│ │ ├── layout.tsx # Root layout, metadata
│ │ ├── page.tsx # Main app (sidebar, gallery, modal)
│ │ └── globals.css # Tailwind + custom styles
│ ├── components/
│ │ ├── GenerationForm.tsx # Text/image input, templates
│ │ ├── WorldsList.tsx # Environment gallery grid
│ │ └── WorldViewer.tsx # 3D Gaussian splat viewer
│ └── lib/
│ ├── world-api.ts # World Labs API client
│ └── types.ts # TypeScript type definitions
├── PRODUCT_STRATEGY.md # Product vision & roadmap
└── package.json
- Node.js 18+
- World Labs API key (get one here)
# Clone the repo
git clone https://github.com/ashstep2/robosim-studio.git
cd robosim-studio
# Install dependencies
npm install
# Set up environment
cp .env.local.example .env.local
# Add your WLT_API_KEY to .env.local
# Run locally
npm run devOpen http://localhost:3000 to see the app.
| Variable | Description |
|---|---|
WLT_API_KEY |
World Labs API key from platform.worldlabs.ai |
- Select a template or write your own description
- Choose mode: Draft (faster) or Full (higher quality + physics mesh)
- Click Generate Environment
- Wait for generation (~30 sec for Draft, ~5 min for Full)
Click any generated environment to open the interactive viewer:
- Mouse drag: Look around
- Scroll: Zoom
- Quality selector: Switch between 100k, 500k, or full resolution
Each environment includes downloadable assets:
- Gaussian splats (SPZ format) — for perception training
- Collision mesh (GLB format) — for physics simulation (Full mode only, not in draft)
- Panorama — 360-degree reference image
