Integrate Maps
Admin UI and Form Template Settings
Admin UI Settings
The first step is to ensure that the App function flag for enabling the map feature is activated in the Form Template settings within the Admin UI. Without this flag, maps will not be available in the Form Templates.


Next, define the maps that will be globally available across all Form Templates. These settings are configured in the Admin UI under Core Server > App Settings.


For other supported map libraries, such as MapLibreGL and OpenLayers, you can configure their availability as follows:
- Default Maps: If you want that a specific map is available automatically in all of your Form Templates without further doing, use the prefix
hfMap-followed by a unique name (e.g., hfMap-MapLibreBaseMap). If no specific map settings are applied in the Form Template, this map will be displayed automatically (assuming the map feature flag is enabled). - Optional Maps: If you do not want a map to appear by default in the Form Templates, omit the
hfMap-prefix. Use any unique name for the map (e.g., MapLibreBaseMap). This map will then only be available in a Form Template if it is explicitly configured in the Form Template VariableFormSettings(see below).
For detailed instructions on configuring non-Google Maps options, refer to the sections for MapLibreGL and OpenLayers.
Form Template Settings
If you prefer to override the default maps defined in the Admin UI or want to include maps that are not globally
available, you can specify them in the Form Template settings. Use the template variable MediaSettings and the
attribute data-hf-registerMaps to define a comma-separated list of map IDs. These IDs correspond to the App setting IDs
configured in the Admin UI.
Only the specified maps will be available in your Form Template, overriding any default maps.
<var data-hf-name="MediaSettings" data-hf-registerMaps="googleMapsApiKey,hfMap-MapLibreBaseMap,Basemap-OpenLayers">
</var>
In this example, three maps are included in the Form Template:
- Google Maps (using the googleMapsApiKey),
- MapLibreGL Map (with the name MapLibreBaseMap),
- OpenLayers Map (with the name Basemap-OpenLayers).
Integrate Google Maps
To integrate Google Maps into your Form Templates, simply set the Google Maps API key in the App Settings section of the Admin UI using the googleMapsApiKey.
Integrate Custom Maps with MapLibreGL and OpenLayers
You can select one of two supported map providers — MapLibreGL or OpenLayers — and configure the map features through a JSON configuration that you define the Admin UI as described above.
-
MapLibreGL: MapLibreGL is an open-source mapping library based on Mapbox GL JS. It enables high-performance, interactive maps rendered in a browser using WebGL. It is ideal for modern, visually rich web applications and supports a wide range of map styles and customizations.
-
OpenLayers: OpenLayers is a robust and versatile open-source JavaScript library for displaying maps in web browsers. It supports a wide variety of mapping formats and services, making it an excellent choice for applications with complex geospatial requirements.
JSON Configuration Overview
Below is the structure of the configuration JSON used to define map settings:
{
"provider": "[MapLibreGL | OpenLayers]",
"tileType?": "Raster",
"style?": "https://url-to-map-style", // MapLibreGL
"styles?": [ // MapLibreGL alternative to style
{
"id": "street",
"style": "https://url-to-styles-file",
"label": "Street View",
"default": true
},
{
"id": "satellite",
"label": "Satellite View",
"style": "https://url-to-another-styles-file"
}
],
"capabilities?": { // only for OpenLayers maps; WMTS cappabilities
"url": "https://url-to-wmts-xml",
"layers": [
{
"id": "street",
"base": "[Identifier of the base layer]",
"baseHiDPI": "[Identifier of an alternative high dpi base layer]",
"overlays": [
{
"id": "[additional layer identifier]",
"opacity": 0.8,
}
],
"label": "[Label for the layer]",
"default": true
},
{
"id": "hybrid",
"base": "ortholayer", // Identifier of the base layer
"overlays": [
{
"id": "streetname-layer", // Identifier of the additional layer
"opacity": 0.8, // opacity of the layer
},
],
"label": "Ortho-Satellite",
},
],
"wfsLayers?": [
{
"type": "explicit",
"name": "workspace:layer-name",
"url": "https://geoserver.example.com/wfs?service=WFS&request=GetFeature&typename=workspace:layer-name&outputFormat=application/json&srsname=EPSG:3857&bbox=${extent},EPSG:3857",
"format": "geojson",
"label": "Feature layer",
"strategy": "bbox",
"zoomToLayerOnLoad": true,
"styleLayer": "HFFormdefinition.CustomCode.styleLayer"
},
{
"type": "auto",
"capabilitiesUrl": "https://geoserver.example.com/geoserver/workspace/wfs",
"autoDetectLayers": true,
"zoomToLayerOnLoad": true,
"includeLayers": ["workspace:layer-a"],
"excludeLayers": ["workspace:internal-layer"]
}
],
"wfsActions?": {
"styleLayer": "HFFormdefinition.CustomCode.styleLayer",
"onFeatureClick": "HFFormdefinition.CustomCode.onFeatureClick"
}
},
"apiKey?": "your-api-key",
"mapConfig?": {
"center": [15.439504, 47.070713],
"zoom": 14,
"pitch": 61,
"bearing": 172,
"hash": true
},
"geoJSON?": "districts.geojson", // MapLibreGL attachment filename
"source?": "https://tiles.example.com/{z}/{x}/{y}.png", // MapLibreGL raster source when tileType=Raster
"features?": {
"setMarkers": {
"maxMarkers": 1,
"callback": "HFFormdefinition.MLMaps.onMarkerSet"
},
"toggleLayerVisibility": true, // MapLibreGL
"directions": true, // MapLibreGL
"drawing": true, // MapLibreGL
"html2Canvas": true,
"createSnapshot": true
},
"controls?": {
"geolocation": true,
"mapNavigation": true,
"geocoding": true // MapLibreGL
},
"addressMarkers?": [
"Alexanderplatz 1, 10178 Berlin, Germany",
"Brandenburger Tor, Pariser Platz, 10117 Berlin, Germany",
"[... more addresses ...]"
],
"onLoad?": "HFFormdefinition.CustomCode.mapOnLoad",
"hooks?": {
"onMapReady": "HFFormdefinition.CustomCode.onMapReady"
}
}
If for OpenLayers maps in the capabilities section more than one layer is defined, the user can switch between the layers in the apps map.
If in MapLibre maps more than one view should be available, define the styles array at the top level of the configuration object (instead of the style property).
Provider-specific behavior matters:
controls.geocoding,features.directions,features.drawingandfeatures.toggleLayerVisibilityare relevant for MapLibreGL maps.capabilities.layers,capabilities.wfsLayers,capabilities.wfsActionsandhooks.onMapReadyare relevant for OpenLayers maps.features.createSnapshotis used to enable snapshot creation in connected map workflows and is enabled in the current OpenLayers app settings examples.
OpenLayers WFS Configuration
OpenLayers maps can combine WMTS basemaps with WFS feature layers. The current configuration model supports two WFS modes:
type: "explicit"for manually configured feature layers with a fully defined GetFeature URL.type: "auto"for automatic feature layer discovery from a WFS capabilities document.
You can additionally define capabilities.wfsActions.styleLayer and capabilities.wfsActions.onFeatureClick to style loaded features and react to feature clicks. If hooks.onMapReady is set, the callback runs after the first render and after asynchronous WFS loading has finished.
Explicit WFS Layer Example
{
"provider": "OpenLayers",
"capabilities": {
"url": "https://mapsneu.wien.gv.at/basemapneu/1.0.0/WMTSCapabilities.xml",
"layers": [
{
"id": "street",
"base": "geolandbasemap",
"baseHiDPI": "bmaphidp",
"overlays": [],
"label": "Street",
"default": true
}
],
"wfsLayers": [
{
"type": "explicit",
"name": "asfinag-test:testpunkte",
"url": "https://geoserver.icomedias.com/geoserver/asfinag-test/wfs?service=WFS&version=1.1.0&request=GetFeature&typename=asfinag-test:testpunkte&outputFormat=application/json&srsname=EPSG:3857&bbox=${extent},EPSG:3857",
"format": "geojson",
"label": "Testpunkte",
"strategy": "bbox",
"zoomToLayerOnLoad": true
}
],
"wfsActions": {
"styleLayer": "HFFormdefinition.Playground.customStyleLayer",
"onFeatureClick": "HFFormdefinition.Playground.customOnFeatureClick"
}
},
"mapConfig": {
"center": [15.439504, 47.070713],
"zoom": 14
},
"features": {
"setMarkers": true,
"createSnapshot": true
},
"controls": {
"geolocation": true,
"mapNavigation": true
}
}
Auto-Detected WFS Layers Example
{
"provider": "OpenLayers",
"capabilities": {
"url": "https://mapsneu.wien.gv.at/basemapneu/1.0.0/WMTSCapabilities.xml",
"layers": [
{
"id": "street",
"base": "geolandbasemap",
"baseHiDPI": "bmaphidp",
"overlays": [],
"label": "Street"
},
{
"id": "hybrid",
"base": "bmaporthofoto30cm",
"overlays": [
{
"id": "bmapoverlay",
"opacity": 1
}
],
"label": "Hybrid"
}
],
"wfsLayers": [
{
"type": "auto",
"capabilitiesUrl": "https://geoserver.icomedias.com/geoserver/asfinag-test/wfs",
"autoDetectLayers": true,
"zoomToLayerOnLoad": true
}
],
"wfsActions": {
"styleLayer": "HFFormdefinition.GeoserverMap.customStyleLayer",
"onFeatureClick": "HFFormdefinition.GeoserverMap.onFeatureClick"
}
},
"mapConfig": {
"center": [15.484977, 47.026724],
"zoom": 17
},
"features": {
"setMarkers": true,
"createSnapshot": true
},
"controls": {
"geolocation": true,
"mapNavigation": true
},
"hooks": {
"onMapReady": "HFFormdefinition.GeoserverMap.customOnMapReady"
}
}
Main MapLibreGL and OpenLayers Options
mapConfig - required
mapConfig: {
center: [15.439504, 47.070713],
zoom: 14,
pitch: 61,
bearing: 172
}objectprovider - required
provider: "MapLibreGL"stringaddressMarkers
addressMarkers: [
"Alexanderplatz 1, 10178 Berlin, Germany",
"Brandenburger Tor, Pariser Platz, 10117 Berlin, Germany"
]array of stringsapiKey
apiKey: "abcd"stringcapabilities
capabilities: {
url: "https://url-to-wmts-xml",
layers: [{
id: "street",
base: "basemap",
label: "Street",
default: true
}]
}objectcontrols
controls: {
geolocation: true,
mapNavigation: true,
geocoding: true
}objectfeatures
features: {
setMarkers: {
maxMarkers: 1,
callback: "HFFormdefinition.MLMaps.onMarkerSet"
},
toggleLayerVisibility: true,
directions: true,
drawing: true,
createSnapshot: true
}objectgeoJSON
geoJSON: "districts.geojson"stringhooks
hooks: {
onMapReady: "HFFormdefinition.CustomCode.onMapReady"
}objectonLoad
onLoad: "HFFormdefinition.CustomCode.mapOnLoad"string (function name)source
source: "https://tiles.example.com/{z}/{x}/{y}.png"string (URL template)style
style: "https://api.maptiler.com/maps/topo-v2/style.json?key=XYZ"string (URL)styles
[
{"id": "street", "style": "https://style-url-1.json", "label": "Street View", "default": true},
{"id": "satellite", "style": "https://style-url-2.json", "label": "Satellite View"}]array of objectstileType
tileType: "Raster"stringOpenLayers Capabilities Options
layers.base - required
base: "geolandbasemap"stringlayers.label - required
label: "Hybrid"stringurl - required
url: "https://url-to-wmts-xml"string (URL)layers
{"id":"hybrid","base":"ortholayer","overlays":[{"id":"streetname-layer","opacity":0.8}],"label":"Ortho-Satellite"}array of objectslayers.baseHiDPI
baseHiDPI: "bmaphidp"stringlayers.default
default: truebooleanlayers.id
id: "hybrid"stringlayers.overlays
overlays: [{"id":"bmapoverlay","opacity":1}]array of objectswfsActions
{"styleLayer":"HFFormdefinition.CustomCode.styleLayer","onFeatureClick":"HFFormdefinition.CustomCode.onFeatureClick"}objectwfsLayers
{"type":"auto","capabilitiesUrl":"https://example.com/geoserver/wfs","autoDetectLayers":true}array of objectsMap Configuration Options
center - required
center: [15.439504, 47.070713]array of numbershash
hash: truebooleanMap Controls Options
geocoding
geocoding: truebooleangeolocation
geolocation: truebooleanmapNavigation
mapNavigation: truebooleanMap Features Options
createSnapshot
createSnapshot: truebooleandirections
directions: truebooleanhtml2Canvas
html2Canvas: truebooleansetMarkers
setMarkers: {
maxMarkers: 1,
callback: "HFFormdefinition.MLMaps.onMarkerSet"
}boolean or objectsetMarkers.callback
callback: "HFFormdefinition.MLMaps.onMarkerSet"string (function name)toggleLayerVisibility
toggleLayerVisibility: truebooleanOpenLayers WFS Layer Options
type - required
type: "auto"stringautoDetectLayers
autoDetectLayers: truebooleancapabilitiesUrl
capabilitiesUrl: "https://geoserver.example.com/geoserver/workspace/wfs"string (URL)excludeLayers
excludeLayers: ["workspace:internalLayer"]array of stringsformat
format: "geojson"stringincludeLayers
includeLayers: ["workspace:layerA", "workspace:layerB"]array of stringsname
name: "asfinag-test:testpunkte"stringstrategy
strategy: "bbox"stringstyleLayer
styleLayer: "HFFormdefinition.CustomCode.styleLayer"string (function name)url
url: "https://geoserver.example.com/wfs?service=WFS&request=GetFeature&typename=test:layer&outputFormat=application/json&srsname=EPSG:3857&bbox=${extent},EPSG:3857"string (URL)zoomToLayerOnLoad
zoomToLayerOnLoad: truebooleanOpenLayers WFS Actions Options
onFeatureClick
onFeatureClick: "HFFormdefinition.GeoserverMap.onFeatureClick"string (function name)styleLayer
styleLayer: "HFFormdefinition.GeoserverMap.customStyleLayer"string (function name)Map Hooks Options
onMapReady
onMapReady: "HFFormdefinition.GeoserverMap.customOnMapReady"string (function name)