cdn-fonts

v0.0.2
0 PublicLibrary

Locally stored font assets and validation for CDN distributions

MPL-2.0 10 downloads
Updated 3 days ago Repository
cdnfonts

Run

wippy run wippy/cdn-fonts

Wippy CDN Fonts adapter

The public release of wippy/cdn-fonts is version 0.0.3. It requires wippy/cdn >=0.0.3 and wippy/facade >=0.6.45. Facade 0.6.45 selects Host 1.0.64 (npm 0.0.64) by default.

The adapter serves local font metadata, CSS, and WOFF2 files under /cdn/fonts. It does not change the application's font configuration. The host chooses which generated stylesheet to apply.

Default families

The module includes Inter Variable and Outfit Variable at weights 100 to 900, and JetBrains Mono Variable at weights 100 to 800. Each family has normal Latin and Latin-ext WOFF2 faces and an OFL-1.1 notice.

Manual font sets

Place each manual set under this path:

<cdn-data-root>/fonts/library/<family-id>/
  fontset.json
  files/<face-id>.woff2
  notices/license.txt

Copy every WOFF2 face and the complete OFL-1.1 notice first. Write fontset.json last. The physical input manifest has only schemaVersion, id, metadata, and files at the top level. Each files entry has only path, size, and sha256. The files list must describe the exact files in the directory: every declared face and one notice, with no extras or duplicate paths. Record exact byte lengths and lowercase SHA-256 digests.

Example physical fontset.json:

{
  "schemaVersion": 1,
  "id": "my-font",
  "metadata": {
    "family": "My Font",
    "style": "normal",
    "fontDisplay": "swap",
    "license": "OFL-1.1",
    "faces": [
      {
        "id": "latin-regular",
        "path": "files/latin-regular.woff2",
        "style": "normal",
        "weight": "400",
        "fontDisplay": "swap",
        "unicodeRange": "U+0000-00FF"
      },
      {
        "id": "greek-variable",
        "path": "files/greek-variable.woff2",
        "style": "normal",
        "weight": "100 900",
        "fontDisplay": "swap",
        "unicodeRange": "U+0370-03FF",
        "axes": { "wght": { "min": 100, "max": 900 } }
      }
    ]
  },
  "files": [
    { "path": "files/latin-regular.woff2", "size": 12345, "sha256": "0000000000000000000000000000000000000000000000000000000000000000" },
    { "path": "files/greek-variable.woff2", "size": 23456, "sha256": "0000000000000000000000000000000000000000000000000000000000000000" },
    { "path": "notices/license.txt", "size": 1234, "sha256": "0000000000000000000000000000000000000000000000000000000000000000" }
  ]
}

Replace each example size and zero digest with the exact file size and digest. The values above are placeholders. Each face id is lowercase letters and digits separated by single hyphens, and its path must be files/.woff2. The core maps those physical paths to faces/.woff2 in the committed revision. The committed manifest is internal output, not a manual input file.

Faces may use different custom ids and subsets. Only normal style and swap display are accepted. A static face declares one quoted numeric weight such as "400" or "700". A variable face declares a quoted range such as "100 900" and matching numeric axes.wght min and max values. unicodeRange uses comma-separated CSS Unicode ranges. The validator checks syntax, not actual glyph coverage.

The validator performs bounded WOFF2 container and table-directory checks. It checks that a variable face has an fvar table and that the declared numeric wght range is valid. It does not decompress font tables to verify numeric axis bounds, static weight or the characters named by unicodeRange.

A distribution can contain up to 511 WOFF2 faces and one OFL notice within the 512-file limit. Each face can be up to 20 MiB and the whole distribution up to 100 MiB. The notice can be up to 1 MiB. Provide the complete OFL-1.1 text in UTF-8; it must contain the SIL OPEN FONT LICENSE Version 1.1 marker.

Local API

The host binds the router to its existing gateway. Useful read routes are:

GET /cdn/fonts/families?limit=256&cursor=<family-id>
GET /cdn/fonts/<family-id>.css
GET /cdn/fonts/<family-id>/<revision>/stylesheet.css
GET /cdn/fonts/<family-id>/<revision>/<face-id>.woff2

The families route accepts an optional integer limit from 1 to 256, with a default of 256, and an optional exclusive family-ID cursor. It returns { "families": [...], "next_cursor": "" }; next_cursor is null when no more results remain. The route reads at most two 128-entry core pages per request, so it may return fewer families than the limit when selected entries have no valid font metadata. Family records keep the existing fields: id, revision, family, style, fontDisplay, license, stylesheet, and revisionStylesheet.

Management listings show at most four face summaries. The face_count field reports the full count; faces_truncated is true when additional faces are omitted from the summary. Generated CSS includes every committed face.

The stable stylesheet follows the selected revision. The revision-qualified stylesheet and files identify immutable content. Generated CSS uses URLs relative to each stylesheet, so WOFF2 requests keep deployment path prefixes. To use a family from another origin, link to the absolute stylesheet URL on the application's origin and allow anonymous cross-origin access:

<link rel="stylesheet" href="https://your-app.example/cdn/fonts/my-font.css" crossorigin="anonymous">

You can also import the stable active-family URL from CSS. Put the @import before other CSS rules:

@import url("https://your-app.example/cdn/fonts/my-font.css");

Use the application's public origin in these examples. Do not copy the stylesheet response into application CSS. The module generates that CSS from validated face metadata. Stable stylesheet URLs revalidate on use; revision-qualified CSS and WOFF2 files use immutable cache headers. Reload affected documents after changing the selected family.

Explicit acquisition and host setup

An authorized management client may acquire one exact @fontsource-variable/ version through POST /cdn/fonts//acquire. Send a JSON body with version. For an existing selection, include base_revision and expected_selection_token from the reviewed catalog snapshot. Poll GET /cdn/operations/<operation_id> for the result. Acquisition contacts only the configured npm registry origin after the explicit action; reads, misses, scans, startup, restart, and stylesheet requests do not download packages.

The provider recipe remains the existing two-face variable Latin and Latin-ext set. Manual font sets can use other normal faces, static weights, variable ranges, custom ids, and declared subsets. This adapter is manual-only for source selection. It does not expose a source selector or add CSS to application settings automatically.

Add the generated local CSS to your application's existing global, host, or child CSS configuration. The Fonts Inspector provides a copyable import for the stable active-family stylesheet and a separate font-family declaration using the exact metadata.family value. Add the import before other CSS rules, then place the family declaration in the selectors you choose. The import follows the active revision, so updates and rollbacks do not require a new URL. The module does not change application typography automatically. Reload affected documents after changing the selected font. Revision previews remain pinned to their selected revision.

Inspector panel

The lazy wippy-cdn-fonts-admin component previews saved families and provides Add font files, Download family, revision actions, and advanced folder-import instructions. Add font files accepts up to 511 normal WOFF2 faces and one OFL-1.1 notice within the limits above. Review a static weight or variable range and Unicode coverage for each face. Files are sent only after Upload fonts. The form creates the manifest.

The panel uses the shared AppConfig proxy client for API URLs and authentication. It takes no API-base or public-base attributes. A preview or upload does not change application typography or source preferences. Only a family with an active local stylesheet has copyable use snippets. Add the copied CSS and family declaration manually to the application CSS locations you choose.

The download catalog includes pinned Fontsource variable families with normal Latin and Latin-ext faces and OFL-1.1 licensing. Review the exact available version before downloading. The provider recipe remains two normal variable faces; manual uploads can use other supported normal faces and subsets.

Build the panel with make.bat build-wc-admin. Wippy serves static/wc/admin/index.js at /cdn/admin/fonts/index.js. The component is announced for explicit lazy loading through loadByTagName and adds no application route.

The local display-name snapshot is dated 2026-10-15 and comes from https://api.fontsource.org/v1/fonts?variable=true&subsets=latin,latin-ext. Its SHA-256 is f27e1d2f11e24bf3537e04ebb6b14a1893a138ff97bf46af910222babaaf7dd0. The local filter verifies both subsets, normal style, variable status, and OFL-1.1 license. Opening the panel does not refresh this catalog or download fonts.