title: Font hosting description: Self-hosted Google Fonts: source, fetching, upload, and required metadata.
Font hosting
Realm does not load fonts directly from fonts.googleapis.com — Google Fonts is unreliable in mainland China. All font files are downloaded, the CSS is rewritten, and the assets are hosted on cdn.arsvine.com/shared/fonts/.
Three families
Noto Serif SC 500 is unused in practice and was removed from data/site.ts. The three families cover four weight values across unicode-range.
Source of truth
cdnPreconnectadds<link rel="preconnect">in<head>to shorten the TLS handshakegoogleStylesheetis the input, only consumed byscripts/fetch-google-fonts.mjscdnStylesheetis the output, the actual CSS loaded by browsers
Fetch script
The script:
- Fetches the Google CSS with a modern Chrome User-Agent
- Downloads every
.woff2 - Rewrites each
url()tocdn.arsvine.com/shared/fonts/<family>/<file> - Writes the staging tree to
public/_fonts-staging/
public/_fonts-staging/ is a temporary directory, gitignored, not version controlled.
Upload and metadata
Strict COS custom-header values:
The Value field holds only the value. Never paste Cache-Control: public, ... as a value. A wrong value produces Cache-Control: Cache-Control: ..., Firefox rejects the font, and Traditional Chinese characters occasionally render as tofu. This is GOTCHAS.md item 3.
Verification
Expect to see Content-Type and Cache-Control each appear once with the correct values.
Variable font deduplication
Google Fonts returns multiple @font-face blocks for the same .woff2 at different font-weight values. This is expected behavior for Variable Fonts — a single file covers a continuous wght axis. Do not rewrite fetch-google-fonts.mjs to force "one weight per file" (GOTCHAS.md item 4).