Quick Start Tutorial
This guide walks you through rendering a basic 3D indoor map, loading an IMDF archive, and applying standard theme colors using @bloomsparkagency/core.
Step 1: Import Style Prerequisites
Make sure you import MapLibre's stylesheet in your main React file (e.g., main.tsx or index.tsx):
typescript
import 'maplibre-gl/dist/maplibre-gl.css';Step 2: Establish the Map Shell
Create a simple mapping component. <SpatialProvider> wraps the state store, registers the custom pmtiles:// protocol once internally, and applies default visual variables.
tsx
import React from 'react';
import { SpatialProvider, SpatialMap } from '@bloomsparkagency/core';
export function MapApp() {
return (
<SpatialProvider>
<SpatialMap
buildings={[]}
initialViewState={{
longitude: -122.4,
latitude: 37.8,
zoom: 15,
pitch: 45,
bearing: 0,
}}
style={{ width: '100vw', height: '100vh' }}
/>
</SpatialProvider>
);
}Step 3: Load an IMDF Building Model
To load and extrude an IMDF building, import <IMDFSource> and <FloorLayers>:
tsx
import React, { useState, useEffect } from 'react';
import {
SpatialProvider,
SpatialMap,
IMDFSource,
FloorLayers,
FloorSwitcher,
ModeToggle
} from '@bloomsparkagency/core';
export function BuildingApp() {
const [imdfBuffer, setImdfBuffer] = useState<ArrayBuffer | null>(null);
useEffect(() => {
// Fetch an IMDF zip archive as an ArrayBuffer
fetch('/maps/silicon-valley-office.imdf.zip')
.then(res => res.arrayBuffer())
.then(buffer => setImdfBuffer(buffer));
}, []);
if (!imdfBuffer) {
return <div style={{ padding: 20 }}>Loading IMDF Assets...</div>;
}
// Define building metadata
const buildings = [
{
id: 'building-hq',
name: { en: 'Headquarters Office' },
levels: [
{ id: 'floor-1', ordinal: 1, name: { en: 'Floor 1' }, short_name: { en: 'L1' } },
{ id: 'floor-2', ordinal: 2, name: { en: 'Floor 2' }, short_name: { en: 'L2' } }
]
}
];
return (
<SpatialProvider>
<SpatialMap
buildings={buildings}
activeBuildingId="building-hq"
mode="3d"
initialViewState={{
longitude: -122.084,
latitude: 37.422,
zoom: 18.5,
pitch: 50,
bearing: -15
}}
style={{ width: '100vw', height: '100vh', position: 'relative' }}
>
{/* Render base layers and load IMDF geometries */}
<IMDFSource archive={imdfBuffer}>
<FloorLayers />
</IMDFSource>
{/* UI overlays */}
<FloorSwitcher position="top-right" />
<ModeToggle position="top-left" />
</SpatialMap>
</SpatialProvider>
);
}Step 4: Loading PMTiles Basemaps
Rather than pulling Mapbox-hosted tiles, you can point to self-hosted Protomaps vectors:
tsx
import { SpatialProvider, SpatialMap, BasemapPMTilesSource } from '@bloomsparkagency/core';
export function SelfHostedMap() {
return (
<SpatialProvider>
<SpatialMap buildings={[]}>
{/* Single static vector tile file serving the entire campus map */}
<BasemapPMTilesSource url="pmtiles://https://tiles.yourdomain.com/campus-basemap.pmtiles" />
</SpatialMap>
</SpatialProvider>
);
}