FONT_MIRROR_URL to serve all catalog fonts from your own static host. Current web and mobile clients,
server-generated PDFs, font-picker previews, public resume HTML, and social preview cards use the same mirror.
The default deployment continues to use the original font hosts.
The mirror is a directory of prepared files. Rendering never downloads a missing file from Google or jsDelivr.
PDF export reports missing fonts; font-picker labels and public HTML can fall back to system fonts when files
cannot load. Catalog font containers are checked for required tables, valid offsets and table checksums before caching. This rejects
truncated files and HTML fallbacks returned with HTTP 200; it does not certify every OpenType table or glyph.
The saved resume’s typography is not changed.
Prepare the files
Use a source checkout matching the deployed release (Node 24 and its pinned pnpm). Inspect the complete catalog:manifest.json with source URLs, sizes and SHA-256 checksums only after every download succeeds. Four
files download concurrently; each file has a size limit and timeout. Prepare while online, then transfer the
whole directory, including licenses/, to the static host. No font files are added to the application image.
For a smaller installation or a test, select families and resume languages:
--all for the full catalog. Include all
families used by your resumes and letters, and repeat preparation after catalog changes on an upgrade.
If a font’s original license notice cannot be located, preparation stops. Obtain that font’s notice from its
upstream project and put it in a directory as <family>.txt, then pass --licenses <directory>. No license is
inferred or substituted. A failed preparation directory is incomplete; use a new directory for the next attempt.
The source host and path form the mirror path, for example:
Configure the instance
http://fonts is not reachable from a visitor’s browser. Use HTTPS when the application uses HTTPS, and serve the
mirror with CORS allowing font reads from the application, public/custom resume domains and sandboxed previews.
Since fonts are public assets, Access-Control-Allow-Origin: * is suitable when no credentials are required.
The setting accepts an absolute HTTP(S) URL with an optional path, without credentials, a query or fragment.
For Docker, add the variable to the app’s environment and restart/recreate the app container. No frontend rebuild
is needed. As one local-development example, expose a static nginx container on port 8080 with the prepared
folder mounted read-only at /usr/share/nginx/html. Use a configuration such as:
FONT_MIRROR_URL to that server’s externally reachable address, for example
http://192.168.1.20:8080 on a trusted local HTTP development network. For production, serve the same directory
through your HTTPS static host. On Vercel, set the backend environment variable and redeploy; the mirror remains
on the external static host.
FONT_MIRROR_URL takes precedence over the legacy WEB_FONT_BASE_URL. Remove it and restart to return to the
previous font behavior. Configuration reaches current clients through the public flags endpoint; it contains no
credentials. Reload web clients after changing it. Mobile saves each server’s configuration and reuses it for five
minutes; after that, it confirms the configuration before the next render, and keeps the saved one if the server
can’t be reached. A device that has never read the configuration (first use, or offline right after updating the
app) renders only fonts it already has and downloads none until it can read the configuration. Previously
installed mobile versions do not understand this setting and must be updated.
When replacing font bytes, publish a versioned mirror path (for example /resume/v2) and update the setting.
Font caches key by the resolved URL; overwriting a file at the same URL does not invalidate running clients.
Keep the previous mirror path available during rollout for clients still using the previous configuration.
Verify delivery
Start with cleared font/browser caches. Block requests tofonts.gstatic.com, fonts.gstatic.cn and
cdn.jsdelivr.net, then open the font picker, edit a resume, export its PDF and visit its public page. Check
attempted requests, including failures; only your configured mirror should receive font requests. Include
bold, italics, the resume’s languages, arrows and symbols. Test a letter and a mobile client as well.
Temporarily remove a required mirrored file: PDF generation should report a font error, with no retry to an
original font host. Put the file back and retry. Mirror font fetches refuse redirects; public HTML’s font CSP
restricts font loads to the application and mirror origins. Images and optional AI services have their own
network behavior: this setting controls catalog fonts, not every external resource on a resume.
Legacy Computer Modern server mirror
SetWEB_FONT_BASE_URL when you want the Node.js server to fetch Computer Modern font files from a
mirror you control. You need a running Reactive Resume instance and an HTTP(S) server that can serve static files.
1. Prepare the mirror
Copy thefont/ directory from the bitmaks/cm-web-fonts source used by your release’s
packages/fonts/src/webfontlist.json to your static file server. Keep the directory names, filenames and case:
https://fonts.example.com/cm, this original URL:
font/ segment in the base URL: the resolver appends it. Use an address reachable from the app server; inside
Docker, localhost refers to the app container itself. The mirror must serve font bytes without a login page.
2. Configure the deployment
The server validates the URL at startup. An unset or empty value preserves the original URLs. Remove the variable
and restart or redeploy to return to the default CDN.
Set this value before starting the server. The server PDF entry supplies it to the font loader; the shared font
catalog does not read environment variables. This setting is not exposed to the Vite browser app; rebuilding the
web app does not enable browser mirroring.
The Cloudflare Workers deployment is not covered by this Node.js server setup.
3. Check delivery
From the app server’s network, request a mirrored file:font/Bright/. Repeat with any other Computer Modern families you use. A missing weight or italic
file can fail PDF rendering; the mirror is not retried against the original CDN.
Server-to-server font fetches do not require CORS headers. If another browser application also uses your mirror,
configure that host to allow its origin and serve the appropriate font content type. CORS headers alone do not
enable this setting in Reactive Resume’s browser app.
External Google requests can still occur for punctuation, symbols, emoji or language fallback fonts, even when
the chosen heading and body fonts are Computer Modern. Browser network requests to the original font hosts are
also expected with the current implementation.
Related pages
- Environment variables: the setting’s default and URL constraints.
- Self-hosting with Docker: configure the application container.
- Customizing typography: choose heading and body fonts.
Source-checkout smoke test
With the example multilingual subset prepared and served, run the dedicated browser test against the disposable local database. It checks the actual runtime flags, browser PDF download, server PDF export and public HTML while blocking browser requests to the original font hosts. It requires Chromium, Poppler’spdftotext, and local
PostgreSQL, as described in Development setup:
FONT_MIRROR_URL is unset. Unit tests cover default and mirrored resolution,
worker/main-thread handoff, native server switching, offline configuration, missing fonts and refused redirects.