pfodWeb — extraFonts Guide

Providing font files maintains uniformity of the menus across varying browsers and operating systems. The standard pfodWeb build embeds Roboto's Latin and Latin Extended fonts. Extra off-line locally loaded fonts can be added to the extraFonts directory without needing to recompile pfodWeb.

This document describes how to add other fonts without having to rebuild pfodWeb.html.

1. Why extraFonts/ exists

pfodWeb.html embeds Roboto's Latin and Latin Extended subsets directly as base64 data:, because almost every pfodWeb screen needs them and they're always wanted as soon as the page loads. References to every other font needed (Cyrillic, Greek, etc.) are moved out into a separate, plain CSS file — extraFonts/pfodweb-extra-fonts.css — referenced via an ordinary <link rel="stylesheet href="extraFonts/pfodweb-extra-fonts.css"> tag rather than inlined.

This split matters for two reasons:

2. Adding a new script/font to pfodWeb

extraFonts/ sits next to pfodWeb.html and pfodProxy.exe in every build output (Windows, Linux, and the Contents/MacOS folder of the macOS .app) — not embedded inside pfodWeb.html

  1. Get a woff2 file covering the script. If Roboto itself has glyphs for it, download it from Google Fonts for that subset. If Roboto has no glyphs for the script (e.g. Thai), use a different actual font family (e.g. Noto Sans Thai) — that's fine, since step 3 still labels it font-family: 'Roboto' so pfodWeb's existing font stacks pick it up automatically.
  2. Drop the woff2 file(s) into pfodWeb's directory extraFonts/.
  3. Add an @font-face rule to pfodweb-extra-fonts.css following the existing pattern — same font-family: 'Roboto', correct unicode-range, and a normal + italic pair if both are available. The filename itself is just a local reference you choose; it doesn't need to follow the Roboto-<Style>-<Subset> convention used by the real Roboto subsets — name it after whatever font you actually sourced the woff2 from, since it's the font-family: 'Roboto' label (not the filename) that makes pfodWeb's font stacks pick it up:
    @font-face {
        font-family: 'Roboto';
        font-style: normal;
        font-weight: 100 900;
        font-display: swap;
        src: url('NotoSansThai-Normal.woff2') format('woff2');
        unicode-range: U+0E01-0E5B;
    }
  4. Clear the browser cache and restart pfodWeb / pfodProxy

3. Current subset coverage

Four extra scripts are currently included in the /extraFonts directory, each as a separate woff2 per style (normal/italic).
If you don't need these fonts you can just delete the /extraFonts directory

SubsetFilesunicode-range covers
CyrillicRoboto-Normal-Cyrillic.woff2, Roboto-Italic-Cyrillic.woff2 Russian and related Cyrillic-script languages
Cyrillic ExtendedRoboto-Normal-CyrillicExt.woff2, Roboto-Italic-CyrillicExt.woff2 Additional Cyrillic letters used by some minority languages
GreekRoboto-Normal-Greek.woff2, Roboto-Italic-Greek.woff2 Modern Greek
Greek ExtendedRoboto-Normal-GreekExt.woff2, Roboto-Italic-GreekExt.woff2 Polytonic Greek (accented historical text)

4. How it's wired up

pfodWeb.html attempts to load the locally hosted extraFonts/pfodweb-extra-fonts.css stylesheet.
The extraFonts/pfodweb-extra-fonts.css and fonts are entirely optional. If the .css or one of its woff2 files is missing, the local load attempt returns 404 not found, and the pfodWeb continues to work just fine — text in that script falls back to Arial / the OS system font instead of Roboto. Nothing in pfodWeb depends on this local directory being present.

Every rule inside that file uses font-family: 'Roboto' — the same family name used everywhere else in pfodWeb. Because each rule's unicode-range only covers its own script, the browser layers all of them (the two inlined Latin/LatinExt faces plus whichever extraFonts faces are present) into one logical "Roboto" that automatically picks the right face per character. No JS or font-stack changes are needed elsewhere in pfodWeb to support a new script — once a matching @font-face rule exists in extraFonts/pfodweb-extra-fonts.css, any text containing those characters just renders correctly.

Both font-weight: 100 900 (a variable-font weight range covering normal and bold in one file) and normal/italic styles are declared per subset, mirroring the four faces already inlined in pfodCommon.css.

5. Serving at runtime: pfodProxy and micro self-hosted

When the browser requests extraFonts/pfodweb-extra-fonts.css (and then the individual .woff2 files that CSS references via relative url(...)), pfodProxy and ESP_PicoW_pfodWebServer (in the micro self-hosted case) has no specific route for /extraFonts/..., so the request falls through to a generic fallback handler that serves static files. That handler:

6. Refreshing an existing subset from Google Fonts

pfodWeb_src/fonts/fetch-roboto.js only fetches the two subsets inlined in pfodWeb.html (Latin, Latin Extended) by default — Cyrillic, Cyrillic Extended, Greek, and Greek Extended are commented out of its KEEP_SUBSETS list, since they no longer need to be embedded. To pull a fresh copy of one of the extraFonts subsets:

  1. Uncomment the relevant line(s) in KEEP_SUBSETS near the top of fetch-roboto.js.
  2. Run node pfodWeb_src/fonts/fetch-roboto.js. It writes the new woff2 file(s) into pfodWeb_src/fonts/ (not extraFonts/).
  3. Move the resulting file(s) into /extraFonts/ by hand, then re-comment the line(s) you uncommented in step 1.