ArcGIS Map SDK for JS: Preparing and Hosting Local .pbf Font Assets, feat. MapBox API & Vite

ChunKang Wong
3 min readJun 27, 2023

--

In this article, I will be demonstrating on how to prepare a .pbf font asset by converting from a .ttf file format and host the font asset locally in a Vite project.

Problem Statement

Let’s say you want to create a graphic with TextSymbol of Times New Roman family:

const textSymbol = new TextSymbol({
text: "Hello World",
color: "black",
font: {
size: 12,
family: "Times New Roman",
},
});

const textGraphic = new Graphic({
geometry: {
type: "point",
longitude: -118.805,
latitude: 34.027,
},
symbol: textSymbol,
});

view.graphics.add(textGraphic);

You will be immediately met with the Couldn't find font xxxxxx. Falling back to Arial Unicode MS Regular error:

This is because Times New Roman font is currently not hosted by ArcGIS (check out here for a list of fonts currently hosted by ArcGIS).

Solution

The solution is to host the font assets locally, by setting esriConfig.fontsUrl, for example:

esriConfig.fontsUrl = "./assets/fonts";

The output error should now resemble the following screenshot:

Note that the URL is now calling localhost instead of static.arcgis.com.

Though this has been documented officially, there is a little to no documentation from ESRI nor the Internet on how to obtain a .pbf file or convert a more popular font format such as .ttf or woff2 to .pbf format.

MapBox

Meet MapBox Fonts API, it allows users to add custom fonts in the format of .ttf or .otf, and later retrieve them in the format .pbf.

To start using MapBox Fonts API, create an account here. With the account created, login to MapBox and create an access token here, which is necessary for their Fonts API.

When creating access token, ensure the FONTS:LIST and FONTS:WRITE scope are checked under Secret scopes section:

With the access token created, you can now add new custom font to MapBox via its add-a-font Fonts API, for example:

curl -X POST "https://api.mapbox.com/fonts/v1/{username}/?access_token=YOUR_MAPBOX_ACCESS_TOKEN" \
--data-binary @Times-New-Roman-Regular.ttf

Upon successful request, the API will reflect the font family name and style as a response, for example:

{
"family_name": "Times New Roman",
"style_name": "Regular",
"owner": "{username}",
"visibility": "private"
}

With the font added to MapBox, we can now retrieve the .pbf file of the font via its `retrieve-font-glyph-ranges` Fonts API, for example:

curl "https://api.mapbox.com/fonts/v1/{username}/times%20new%20roman%20regular/0-255.pbf?access_token=YOUR_MAPBOX_ACCESS_TOKEN"

Save the API response, which is in byte, to a file named 0-255.pbf.

Vite

Now that we have the file available, we can place the 0-255.pbf file in the correct location. In my case, it is a Vite project. In the project root public folder, create the following folder structure: /assets/fonts as the base fonts URL as configured earlier.

Next create a font folder with the font family name and style as the folder name, for example: /times-new-roman-regular.

Finally, place the 0-255.pbf file in this folder. The public folder should resemble the following:

./public/assets/fonts/times-new-roman-regular/0-255.pbf

With everything done correctly, ArcGIS JS API should be able to locate the font assets and render the TextSymbol correctly. This can also be observed by inspecting the browser network:

Now you have successfully prepared a .pbf font asset by converting from a more common .ttf format using MapBox API, and hosted it locally with Vite.

--

--