🎉 React 19 support is here! Clover IIIF v3.0.0 works with the latest React frameworks.

Viewer (Map)


Docs

The Viewer can replace the default image canvas with a geographic map whenever navPlace data is available. Click either marker below to see the popup. Each one is a manifest in the collection, enriched with its label, summary, thumbnail, and a link back to the source.

Enable the map in the Viewer with options.map.enabled: true, then use options.map.navPlaceLevel to control which level of the IIIF resource hierarchy supplies the features.

OptionTypeDefault
options.map.enabledbooleanfalse
options.map.fitToDatabooleantrue
options.map.navPlaceLevelauto | Collection | Manifest | Canvas | Annotation | allauto

Canvas

navPlaceLevel: "Canvas" renders the navPlace features from the currently active canvas. Navigating between canvases updates the map, making this level ideal for search-result interfaces: each canvas is a result, and the map always shows where the selected item is located.

The example below uses IIIF Cookbook recipe 0240: navPlace on Canvases (opens in a new tab). The manifest has two canvases, each with its own navPlace point. Click the thumbnails to switch canvases and watch the map update.

<Viewer
  iiifContent="https://iiif.io/api/cookbook/recipe/0240-navPlace-on-canvases/manifest.json"
  options={{
    canvasHeight: "500px",
    showIIIFBadge: false,
    informationPanel: { open: false, renderToggle: false },
    map: {
      enabled: true,
      navPlaceLevel: "Canvas",
      fitToData: true,
    },
  }}
/>

Manifest

navPlaceLevel: "Manifest" renders the navPlace features declared on the active manifest. This is the right choice for a detail page that displays a single item and wants to show its geographic context. The map does not change when navigating between canvases.

Map popups are enriched from the manifest's label, summary, thumbnail, and homepage when present.

// Manifest with navPlace injected at the Manifest level
const manifest = {
  ...northwesternManifest,
  navPlace: {
    type: "FeatureCollection",
    features: [
      {
        type: "Feature",
        id: "https://www.geonames.org/7315798/pend-oreille-river.html",
        properties: { label: { none: ["Pend Oreille River"] } },
        geometry: { type: "Point", coordinates: [-117.61775, 49.00381] },
      },
    ],
  },
};
 
<Viewer
  iiifContent={manifest}
  options={{
    canvasHeight: "500px",
    showIIIFBadge: false,
    informationPanel: { open: false, renderToggle: false },
    map: {
      enabled: true,
      navPlaceLevel: "Manifest",
      fitToData: true,
    },
  }}
/>

Collection

navPlaceLevel: "Manifest" on a Collection iiifContent shows the active manifest's location and updates as the user navigates between manifests in the collection browser. This pattern is useful for collection-level browse interfaces where each item in the collection has its own geographic context.

The example below loads a two-manifest collection. Select a manifest from the thumbnail browser, and the map will update to that manifest's navPlace.

navPlace
<Viewer
  iiifContent={collectionNavPlaceJson}
  options={{
    canvasHeight: "500px",
    showIIIFBadge: false,
    informationPanel: { open: false, renderToggle: false },
    map: {
      enabled: true,
      navPlaceLevel: "Manifest",
      fitToData: true,
    },
  }}
/>

All Levels

navPlaceLevel: "all" renders every navPlace feature found across the entire resource hierarchy: Collection, Manifest, Canvas, and Annotation. Use this to give a complete geographic overview of an item and all of its parts.

The example below uses a manifest with navPlace at both the Manifest level (a bounding polygon for the Pend Oreille region) and on the first Canvas (a specific point on the river). Both features are shown together on the map.

// Manifest with navPlace at the Manifest level (polygon) AND Canvas level (point)
const manifest = {
  // ...
  navPlace: {
    type: "FeatureCollection",
    features: [
      {
        type: "Feature",
        properties: { label: { none: ["Pend Oreille River region"] } },
        geometry: {
          type: "Polygon",
          coordinates: [[
            [-118.5, 47.5], [-116.5, 47.5],
            [-116.5, 49.5], [-118.5, 49.5], [-118.5, 47.5],
          ]],
        },
      },
    ],
  },
  items: [
    {
      // ...
      navPlace: {
        type: "FeatureCollection",
        features: [
          {
            type: "Feature",
            properties: { label: { none: ["Pend Oreille River"] } },
            geometry: { type: "Point", coordinates: [-117.61775, 49.00381] },
          },
        ],
      },
    },
    // canvas 2 has no navPlace
  ],
};
 
<Viewer
  iiifContent={manifest}
  options={{
    canvasHeight: "500px",
    showIIIFBadge: false,
    informationPanel: { open: false, renderToggle: false },
    map: {
      enabled: true,
      navPlaceLevel: "all",
      fitToData: true,
    },
  }}
/>

Auto (default)

navPlaceLevel: "auto", the default, selects the most specific level available for the active canvas in order: Annotation → Canvas → Manifest → Collection. If the current canvas has its own navPlace, that is shown. If not, the viewer falls back to the manifest, and so on.

The example below uses the same two-canvas manifest. The first canvas has Canvas-level navPlace (the specific river point), while the second canvas has none. Navigate to the second canvas and the map automatically falls back to the manifest-level polygon.

<Viewer
  iiifContent={manifest}
  options={{
    canvasHeight: "500px",
    showIIIFBadge: false,
    informationPanel: { open: false, renderToggle: false },
    map: {
      enabled: true,
      // navPlaceLevel: "auto" is the default; it can be omitted
      fitToData: true,
    },
  }}
/>

Image Overlays (Georeference)

When a manifest's canvases carry Georeference Extension (opens in a new tab) annotations, the Viewer can warp the source images onto the map as overlays via @allmaps/leaflet (opens in a new tab). It can render multiple sheets together, alongside any navPlace geometry.

Set options.map.showImageOverlay: true. Clover then:

  • auto-discovers motivation: "georeferencing" annotations on the in-scope canvases,
  • auto-adapts each Canvas-sourced annotation to that canvas's painting image service (no manual image-service URL needed), and
  • hosts every warped sheet in a single map layer.

options.map.overlayScope controls which canvases contribute: "manifest" (default) warps every georeferenced canvas in the manifest at once; "canvas" follows only the active/visible canvas.

The example below combines two adjacent Northwestern University Libraries plat maps, the Township of Evanston (opens in a new tab) and the Village of Wilmette, which tile together on the North Shore. The manifest-level navPlace point is rendered at the same time.

OptionTypeDefault
options.map.showImageOverlaybooleanfalse
options.map.imageOverlayOpacitynumber (0-1)0.65
options.map.showControlPointsbooleantrue
options.map.overlayScopemanifest | canvasmanifest
// (target.source is a Canvas). Clover adapts them to each canvas's //
painting image service automatically.
<Viewer
  iiifContent={northShoreManifest}
  options={{
    canvasHeight: "500px",
    showIIIFBadge: false,
    informationPanel: { open: false, renderToggle: false },
    map: {
      enabled: true,
      showImageOverlay: true,
      imageOverlayOpacity: 0.7,
      overlayScope: "manifest", // warp every georeferenced sheet at once
      navPlaceLevel: "Manifest", // also show the region point
      fitToData: true,
    },
  }}
/>

@allmaps/leaflet is an optional dependency, loaded only when showImageOverlay is true. The georeference annotation's target.source must resolve to an IIIF Image API endpoint for warping; Clover handles this by reading the canvas's painting image service, so stored Canvas-sourced annotations work without manual adaptation. Set showControlPoints: false to hide the ground control point markers.