Skip to content

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>
  );
}

Released under commercial licensing.