Practical guide for working with the Micrio codebase.
Micrio is a layered architecture:
- TypeScript Core (
src/ts/) - Main logic, state management, WebGL - Svelte UI (
src/svelte/) - Reactive components for controls and overlays - WebAssembly (
src/wasm/) - Performance-critical math (camera, tiles)
Data flow: User input → Events → Wasm calculates → WebGL renders → Svelte UI updates
A <micr-io> element manages one or more MicrioImage instances:
// Single image
<micr-io id="abc123"></micr-io>
// Multiple images (split screen, grid)
// Access via micrio.canvases arrayUses Svelte stores for reactivity:
// Global state
micrio.state.tour // Current active tour
micrio.state.marker // Opened marker
micrio.state.ui.hidden // UI visibility
// Per-image state
image.state.view // Current viewport [x, y, w, h]
image.state.marker // Marker opened in this imageTypeScript talks to Wasm via the Wasm class:
// Wasm handles: camera math, tile visibility, animations
// JS handles: rendering, events, UI, data loading
// Example: Request tile draw from Wasm
wasm.drawTile(canvasPtr, tileId, x, y, width, height);- Core logic → Add to
src/ts/ - UI component → Add Svelte component in
src/svelte/components/ - Mount in UI → Import in
src/svelte/Main.svelte - Update types → Add to
src/types/models.tsif needed
Use the error utilities:
import { MicrioError, ErrorCodes } from './utils/error';
import { withRetry } from './utils/retry';
// For network requests - automatic retry
try {
const data = await withRetry(() => fetchJson(url));
} catch (e) {
// After retries exhausted
throw new MicrioError('Failed to load', {
code: ErrorCodes.NETWORK_SERVER_ERROR,
displayMessage: 'Server error. Please try again.'
});
}Tours are in src/svelte/virtual/Tour.svelte:
- Marker tours: Navigate between markers
- Video tours: Synchronized video with events
- Serial tours: Multi-image sequential tours
State is persisted via micrio.state.get() / micrio.state.set().
Console debugging:
// Check current image
document.querySelector('micr-io').$current
// Check stores
micrio.state.tour.subscribe(t => console.log('Tour:', t))
// Wasm status
micrio.wasm.i // > 0 means initializedEnable verbose logging:
localStorage.setItem('micrio_debug', 'true');
location.reload();When to put code where:
| Task | Location |
|---|---|
| Core viewer logic | src/ts/element.ts, src/ts/image.ts |
| Rendering | src/ts/webgl.ts, src/wasm/ |
| UI components | src/svelte/components/ |
| Complex UI logic | src/svelte/virtual/ |
| Data fetching | src/ts/utils/fetch.ts |
| Error handling | src/ts/utils/error.ts, src/ts/utils/retry.ts |
- Minimize Wasm/JS boundary crossings - Batch operations
- Use Svelte stores - Don't manually update DOM
- Lazy load - Gallery thumbnails, tour data
- WebGL - Clean up textures when images switch
Before submitting a PR:
-
pnpm run typecheckpasses - Works in Chrome, Firefox, Safari
- Works on mobile (touch gestures)
- Test with 360° images if touching camera/Wasm
- Test error scenarios (offline, slow network)
# Build Wasm (optimized)
pnpm run asbuild:optimized
# Build Wasm (debug - better stack traces)
pnpm run asbuild:untouched
# Type check
pnpm run typecheck
# Build production
pnpm run build
# Update docs
pnpm run docs