skills/matterport-sdk/SKILL.md
# Matterport SDK Specialist ## Domain Expertise - Matterport SDK (Showcase SDK, Embed SDK) - Viewer integration and lifecycle management - 3D space data formats and structures (camera poses, mattertags, sweeps) - SDK event handling and subscriptions - Camera control and navigation - Scene graph manipulation ## Responsibilities 1. **Implement SDK Integrations** following established patterns 2. **Handle Viewer Lifecycle** (initialization, ready state, cleanup) 3. **Work with SDK Data Formats*
npx skillsauth add rhettark/multi-agent-dev-team skills/matterport-sdkInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Before implementing, ALWAYS:
kb/matterport-integration.md for existing SDK patternskb/frontend-patterns.md for service patternscat kb/matterport-integration.md 2>/dev/null || echo "No SDK patterns documented yet"
cat kb/frontend-patterns.md
cat work/*-design.md 2>/dev/null || true
Read design specifications:
Follow established patterns:
Ensure proper lifecycle management:
Update knowledge base:
kb/matterport-integration.mdAfter implementation, update:
echo "## SDK Pattern: <feature>" >> kb/matterport-integration.md
echo "<implementation details>" >> kb/matterport-integration.md
You are a Matterport SDK Specialist implementing 3D viewer integrations.
WORKFLOW:
1. PRE-FLIGHT CHECKS (REQUIRED):
- Read kb/matterport-integration.md for existing SDK patterns
- Read design requirements from workspace documents
- Read kb/frontend-patterns.md for service patterns
- Check Matterport SDK version in use
2. IMPLEMENTATION:
- Initialize Matterport viewer following lifecycle pattern
- Subscribe to SDK events (Camera.pose, Sweep.current, etc.)
- Work with SDK data formats (poses, mattertags, sweeps)
- Add error handling for SDK connection/subscription failures
- Clean up SDK resources on teardown
3. KNOWLEDGE BASE UPDATES (REQUIRED):
- Update kb/matterport-integration.md with new SDK patterns
- Document SDK quirks or version-specific behaviors
- Add implementation notes to design doc
CONSTRAINTS:
- ALWAYS read KB patterns before implementing
- ALWAYS use async/await for SDK operations
- ALWAYS handle SDK initialization failures gracefully
- ALWAYS clean up SDK subscriptions on teardown
- ALWAYS update KB after implementation
Current task: {task_description}
Design document: {design_doc_path}
/**
* Matterport viewer lifecycle pattern
* Based on BlackBox production implementation
*/
class MatterportService {
constructor() {
this.sdk = null;
this.subscriptions = [];
}
/**
* Initialize Matterport SDK and subscribe to events
* @param {string} modelId - Matterport model ID
* @returns {Promise<SDK>} Initialized SDK instance
*/
async init(modelId) {
const viewer = document.querySelector('#mpv');
if (!viewer) throw new Error('Matterport viewer element not found');
// Wait for custom element to be defined
await customElements.whenDefined('matterport-viewer');
// Connect to SDK (self-hosted bundle pattern)
this.sdk = await viewer.playingPromise;
// Subscribe to SDK events
await this._subscribeToEvents();
// Build sweep graph for navigation
await this._buildSweepGraph();
return this.sdk;
}
/**
* Subscribe to SDK events with error handling
*/
async _subscribeToEvents() {
// Camera pose subscription
try {
const poseSub = this.sdk.Camera.pose.subscribe(pose => {
// Handle pose updates
if (pose?.sweep) {
this.currentSweepId = pose.sweep;
}
});
this.subscriptions.push(poseSub);
} catch (e) {
console.warn('Camera pose subscription failed:', e);
}
// Current sweep subscription
try {
const sweepSub = this.sdk.Sweep.current.subscribe(sweep => {
if (sweep?.sid) {
this.onSweepChanged(sweep.sid);
}
});
this.subscriptions.push(sweepSub);
} catch (e) {
console.warn('Sweep subscription failed:', e);
}
// Floor subscription
try {
const floorSub = this.sdk.Floor.current.subscribe(floor => {
this.onFloorChanged(floor);
});
this.subscriptions.push(floorSub);
} catch (e) {
console.warn('Floor subscription failed:', e);
}
}
/**
* Build sweep graph for pathfinding
*/
async _buildSweepGraph() {
// Wait for sweep data to stabilize
await new Promise(async (resolve, reject) => {
const timeout = setTimeout(() => reject(new Error('Sweep data timeout')), 15000);
try {
const modelData = await this.sdk.Model.getData();
if (modelData?.sweeps?.length > 0) {
clearTimeout(timeout);
resolve();
return;
}
} catch {}
// Subscribe to sweep data updates
let stabilityTimer = null;
const unsub = this.sdk.Sweep.data.subscribe({
onAdded() {
if (stabilityTimer) clearTimeout(stabilityTimer);
stabilityTimer = setTimeout(() => {
try { unsub(); } catch {}
clearTimeout(timeout);
resolve();
}, 500);
}
});
});
// Fetch sweep data and build adjacency graph
const sweepData = await this.sdk.Sweep.data.getData();
this.sweepGraph = this._buildAdjacencyGraph(sweepData);
}
/**
* Clean up SDK resources
*/
cleanup() {
// Unsubscribe from all SDK events
this.subscriptions.forEach(sub => {
try { sub(); } catch {}
});
this.subscriptions = [];
// Disconnect from SDK
if (this.sdk) {
try { this.sdk.disconnect(); } catch {}
this.sdk = null;
}
}
/**
* Move camera to specific pose
* @param {Object} pose - Camera pose {position, rotation, projection, sweep}
*/
async moveToPose(pose) {
if (!this.sdk) throw new Error('SDK not initialized');
await this.sdk.Camera.pose.moveTo({
position: pose.position,
rotation: pose.rotation,
projection: pose.projection || this.sdk.Camera.Projection.PERSPECTIVE,
sweep: pose.sweep,
transition: this.sdk.Camera.Transition.FLY,
speed: 1.0
});
}
/**
* Add mattertag to scene
* @param {Object} tag - Mattertag data
*/
async addMattertag(tag) {
if (!this.sdk) throw new Error('SDK not initialized');
const [sid] = await this.sdk.Mattertag.add([{
label: tag.label,
description: tag.description || '',
anchorPosition: tag.position,
stemVector: tag.stemVector || { x: 0, y: 0.3, z: 0 },
color: tag.color || { r: 1, g: 0, b: 0 }
}]);
return sid;
}
}
For standard Matterport embed (non-self-hosted):
/**
* Initialize SDK using MP_SDK.connect()
* Standard pattern for hosted Matterport iframes
*/
async function initMatterport(modelId) {
const iframe = document.getElementById('matterport-viewer');
// Connect to SDK in iframe
const sdk = await window.MP_SDK.connect(iframe, {
applicationKey: 'YOUR_SDK_KEY'
});
// Configure model
await sdk.Scene.configure({
modelId: modelId
});
// Wait for viewer ready
await new Promise((resolve) => {
sdk.on('viewer.ready', () => {
console.log('Matterport viewer ready');
resolve();
});
});
return sdk;
}
/**
* Cleanup SDK connection
*/
function cleanupMatterport(sdk) {
if (sdk) {
try {
sdk.disconnect();
} catch (e) {
console.warn('SDK disconnect failed:', e);
}
}
}
{
position: { x: 1.5, y: 1.2, z: -3.4 },
rotation: { x: 0.1, y: 2.3, z: 0.0 },
projection: sdk.Camera.Projection.PERSPECTIVE,
sweep: "sweepId123"
}
{
sid: "sweepId123",
uuid: "uuid-string",
position: { x: 1.5, y: 0.0, z: -3.4 },
neighbors: ["sweepId456", "sweepId789"],
floorInfo: { sequence: 0 }
}
{
sid: "tagId123",
label: "Equipment Name",
description: "Equipment details",
anchorPosition: { x: 1.5, y: 1.2, z: -3.4 },
stemVector: { x: 0, y: 0.3, z: 0 },
color: { r: 1, g: 0, b: 0 }
}
SDK data may load asynchronously. Use subscription pattern:
async function waitForSweeps(sdk) {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => reject(new Error('Timeout')), 15000);
let stabilityTimer = null;
const unsub = sdk.Sweep.data.subscribe({
onAdded() {
if (stabilityTimer) clearTimeout(stabilityTimer);
stabilityTimer = setTimeout(() => {
unsub();
clearTimeout(timeout);
resolve();
}, 500);
}
});
});
}
Always wrap SDK calls in try/catch:
try {
const subscription = sdk.Camera.pose.subscribe(pose => {
// Handle pose
});
} catch (e) {
console.warn('Subscription failed:', e);
// Fallback behavior
}
For rendering custom scene objects:
async function registerComponent(sdk, componentName, componentClass) {
const [sceneObject] = await sdk.Scene.createObjects(1);
const node = sceneObject.addNode();
const component = node.addComponent(componentName);
await component.bind(componentClass);
await component.waitUntilBound();
return { sceneObject, node, component };
}
Always store and clean up subscriptions to prevent memory leaks:
this.subscriptions.push(sdk.Camera.pose.subscribe(...));
// Later:
this.subscriptions.forEach(unsub => unsub());
Wait for data stability before using sweep/mattertag data:
For self-hosted SDK, wait for custom element:
await customElements.whenDefined('matterport-viewer');
SDK subscriptions can fail - always add try/catch and fallbacks
Scene objects must be explicitly started:
sceneObject.start();
development
# UI/UX Specialist **Domain Expertise:** - User interface design and implementation - Component design and styling - Accessibility (a11y) best practices - Responsive design and mobile-first approach - Visual hierarchy and UX patterns **Responsibilities:** 1. Design UI components and layouts 2. Implement designs with HTML/CSS/JS 3. Ensure accessibility compliance 4. Establish UI patterns and conventions 5. Update `kb/frontend-patterns.md` with UI patterns **Pre-flight Checks:** ```bash cat kb/
tools
# OpenAI Agents SDK Python Specialist **Domain Expertise:** - OpenAI Agents SDK (Python) internals - Agent creation, configuration, tool integration - Swarm patterns and multi-agent orchestration - Prompt optimization and response handling - Tool function decoration and schemas - Latency optimization and performance tuning **Responsibilities:** 1. Design and implement agents using OpenAI Agents SDK 2. Optimize agent configurations for performance and cost 3. Create and integrate function tools
development
# JavaScript Specialist ## Domain Expertise - Modern JavaScript (ES6+) patterns - Async/await and promise handling - Module design and organization - Event handling and delegation - DOM manipulation and performance - ES6 modules and import/export - Error handling and debugging ## Responsibilities 1. **Implement JavaScript Logic** following modern patterns 2. **Optimize Async Operations** with async/await 3. **Design Modular Code** using ES6 modules 4. **Ensure Performance** through optimized
development
# FastAPI Specialist ## Domain Expertise - FastAPI framework patterns and best practices - Pydantic models for request/response validation - Async/await patterns and dependencies - OpenAPI/Swagger documentation - HTTP status codes and error handling - Middleware and dependency injection ## Responsibilities 1. **Implement Endpoints** based on designs from Backend Architect 2. **Type Safety** using Pydantic models for validation 3. **Async Patterns** following async/await best practices 4. **U