npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@liiift-studio/sanity-font-manager

v2.3.17

Published

Sanity Studio plugin — full font management suite with batch upload, format conversion, metadata extraction, CSS generation, collection/pair generation, and script variant support. Supports Sanity v3, v4, and v5.

Readme

@liiift-studio/sanity-font-manager

Full font management suite for Sanity Studio. Handles batch upload, multi-format conversion, metadata extraction, CSS @font-face generation, collection and pair generation, and script variant management.

Compatible with Sanity v3, v4, and v5.


Installation

npm install @liiift-studio/sanity-font-manager

Peer dependencies

npm install sanity @sanity/ui @sanity/icons react

| Peer | Required version | |---|---| | sanity | >=3 | | @sanity/ui | >=3 | | @sanity/icons | >=3 | | react | >=18 |

If you hit peer dependency conflicts, add legacy-peer-deps=true to your .npmrc.


Components

BatchUploadFonts

Drag-and-drop batch uploader for a typeface document. Accepts TTF/OTF/WOFF/WOFF2 etc., shows a reviewable file list with count, confirm button, elapsed timer, Wake Lock, and beforeunload guard for long uploads. Calls uploadFontFiles for each batch.

import { BatchUploadFonts } from '@liiift-studio/sanity-font-manager';

export const typefaceSchema = {
  name: 'typeface',
  type: 'document',
  fields: [
    {
      name: 'styles',
      type: 'object',
      components: { input: BatchUploadFonts },
      fields: [ /* see Schema fields below */ ],
    },
  ],
};

SingleUploaderTool

Per-font file manager inside a font document. Shows TTF/OTF/WOFF/WOFF2/CSS rows always. EOT/SVG/WEB/SUBSET/DATA are hidden behind an advanced toggle (cog icon). Each row has Upload/Build/Delete controls. Handles CSS regeneration, font data extraction, and WEB+SUBSET building via fontWorker.

import { SingleUploaderTool } from '@liiift-studio/sanity-font-manager';

{
  name: 'fileInput',
  type: 'object',
  components: { input: SingleUploaderTool },
  fields: [ /* format fields — see Schema fields below */ ],
}

GenerateCollectionsPairsComponent

One-click generator for Full Family, Uprights, Italics, and Subfamily collections, plus Regular/Italic pairs matched by weight. Has configurable price inputs for collection-per-font and pair price.

import { GenerateCollectionsPairsComponent } from '@liiift-studio/sanity-font-manager';

PrimaryCollectionGeneratorTypeface

One-click generator for a single full-family collection that includes all fonts linked to the typeface. Prepends the new collection to the existing styles.collections array — non-destructive. Uses SANITY_STUDIO_DEFAULT_COLLECTION_PRICE as the default price, falling back to 100.

Wire it up on a string field in the typeface schema:

import { PrimaryCollectionGeneratorTypeface } from '@liiift-studio/sanity-font-manager';

{
  name: 'generateCollectionGroup',
  type: 'string',
  title: 'Generate Full Family Collection',
  description: 'Generate a collection that includes all the styles from this typeface.',
  components: { input: PrimaryCollectionGeneratorTypeface },
  hidden: ({ parent }) => !parent?.styles?.fonts?.length,
}

FontScriptUploaderComponent

Script-aware uploader for per-script font file variants (Latin, Arabic, Hebrew, etc.) stored in scriptFileInput on the font document.

UploadScriptsComponent

Batch uploader for script-specific font variants across multiple fonts at once.

UpdateScriptsComponent

Updates and re-links existing script font variant references on font documents — used to fix or reassign script variant assignments.

RegenerateSubfamiliesComponent

Recalculates and patches the subfamily field on all fonts linked to a typeface, based on the typeface's defined subfamily groups — without re-uploading any files.

SetOTF

Detects which configured OpenType feature keys are supported by the typeface's first linked font. Reads opentypeFeatures.chars from the font document (populated by generateFontData) and patches the features array on the field. Shows a feature count when features are detected, and clear error messages when font data is missing.

Wire it up on the openType object field in the typeface schema:

import { SetOTF } from '@liiift-studio/sanity-font-manager';

{
  name: 'openType',
  type: 'object',
  components: { input: SetOTF },
  options: { collapsible: true },
  fields: [ /* feature fields — each with a `feature` string e.g. 'liga', 'smcp' */ ],
}

StyleCountInput

Displays the total number of font styles (static + variable) linked to a typeface. Reads styles.fonts and styles.variableFont arrays from the form context. Useful as a read-only display field in the typeface schema.

import { StyleCountInput } from '@liiift-studio/sanity-font-manager';

{
  name: 'styleCount',
  type: 'number',
  readOnly: true,
  components: { input: StyleCountInput },
}

KeyValueInput

Generic ordered key-value editor where both keys and values are plain strings. Supports add, remove, and reorder (up/down arrows). Values are stored as an array of { key, value } objects.

import { KeyValueInput } from '@liiift-studio/sanity-font-manager';

{
  name: 'aliases',
  type: 'array',
  of: [{ type: 'object', fields: [{ name: 'key', type: 'string' }, { name: 'value', type: 'string' }] }],
  components: { input: KeyValueInput },
}

KeyValueReferenceInput

Generic key-value editor where keys are plain strings and values are weak Sanity document references. Supports searching by title via a popover picker, add/remove/reorder, and an optional topActions slot for action buttons above the list.

| Prop | Type | Description | |---|---|---| | fetchReferences | async (client, doc) => [{_id, title}] | Async function that returns candidate references for the picker. Receives the Sanity client and the current document. | | topActions | ReactNode | Optional content rendered above the key-value rows (e.g. autofill buttons). | | referenceType | string | Document type for the created weak references (default: 'font'). |

import { KeyValueReferenceInput } from '@liiift-studio/sanity-font-manager';

{
  name: 'instanceMap',
  type: 'array',
  of: [{ type: 'object', fields: [{ name: 'key', type: 'string' }, { name: 'value', type: 'reference', weak: true, to: [{ type: 'font' }] }] }],
  components: { input: KeyValueReferenceInput },
  // Pass props via options or a wrapper component:
  options: {
    fetchReferences: async (client, doc) => client.fetch('*[_type == "font"]{_id, title}'),
    referenceType: 'font',
  },
}

VariableInstanceReferencesInput

Font-specific wrapper around KeyValueReferenceInput for mapping variable font instance names to their matching static font documents. Provides:

  • A picker filtered to fonts sharing the same typefaceName, excluding variable fonts
  • Autofill with Matching — calls parseVariableFontInstances to match instance names to existing font documents by weight/style heuristics
  • Autofill Keys Only — populates instance name keys from the font's variableInstances metadata without resolving references
  • Autofill buttons are shown only when the document is a variable font with parsed instance data
  • Replace/merge confirmation dialog when pairs already exist
import { VariableInstanceReferencesInput } from '@liiift-studio/sanity-font-manager';

{
  name: 'variableInstanceReferences',
  title: 'Variable Font Instances',
  type: 'array',
  hidden: ({ parent }) => !parent.variableFont,
  of: [
    {
      type: 'object',
      fields: [
        { name: 'key', type: 'string', title: 'Instance Name' },
        { name: 'value', type: 'reference', weak: true, to: [{ type: 'font' }], title: 'Matching Font' },
      ],
    },
  ],
  components: { input: VariableInstanceReferencesInput },
}

StatusDisplay

Shared status bar used by all components. Shows Status: [message] in green on success and red on error, with an optional action element slot on the far right (used for the advanced toggle in SingleUploaderTool).

import { StatusDisplay } from '@liiift-studio/sanity-font-manager';

<StatusDisplay status="ready" error={false} action={<Button ... />} />

PriceInput

Reusable $ + number input for collection and pair price fields.

UploadButton

Label-wrapped button that triggers a hidden file input.


Schema field definitions

Pre-built Sanity schema field objects that can be spread directly into a typeface schema's fields array. Eliminates hundreds of lines of repeated field definitions across consumer studios.

openTypeField

A complete openType object field wired to the openType tab group. Includes the features checkbox array (all standard OpenType feature keys) plus per-feature sub-objects with title, feature, and customText fields. Uses SetOTF internally for auto-detection.

import { openTypeField } from '@liiift-studio/sanity-font-manager';

// In your typeface schema fields array:
openTypeField,

Requires the openType group to be declared in your schema's groups array:

{ name: 'openType', title: 'Open Type' }

styleCountField

A read-only number field in the styles group that displays the total count of static + variable font styles linked to the typeface. Uses StyleCountInput internally.

import { styleCountField } from '@liiift-studio/sanity-font-manager';

// In your typeface schema fields array:
styleCountField,

stylisticSetField

A complete stylisticSet object field for the stylisticSets group. Contains two sub-arrays: featured (highlighted words/phrases with per-character backtick syntax, stylistic feature picker, size, and CSS overrides) and sets (full catalogue of feature → glyph mappings). Both include the full OpenType feature dropdown (44 named features + all 20 stylistic sets).

import { stylisticSetField } from '@liiift-studio/sanity-font-manager';

// In your typeface schema fields array:
stylisticSetField,

Requires the stylisticSets group to be declared in your schema's groups array:

{ name: 'stylisticSets', title: 'Stylistic Sets' }

Hook

useSanityClient

Returns the Sanity client instance from the studio context. Used internally by all components.

import { useSanityClient } from '@liiift-studio/sanity-font-manager';

const client = useSanityClient();

Utilities

Font processing

| Export | Description | |---|---| | processFontFiles | Reads font files via FileReader, parses with fontkit, and builds the fontsObjects map used by uploadFontFiles | | extractFontMetadata | Extracts weight name, subfamily, style, and variable font flag from a fontkit instance | | extractWeightName | Reads the weight name from fontkit name records, falling back through preferredSubfamily → fontSubfamily | | extractWeightFromFullName | Strips the typeface title from the font's full name to isolate the weight/style suffix | | processSubfamilyName | Strips weight and italic keywords from a subfamily string, preserving non-style words like "Condensed" | | formatFontTitle | Normalises a font filename into a human-readable title — expands abbreviations, title-cases, collapses spaces | | addItalicToFontTitle | Appends the detected italic keyword to a title when the font has a non-zero italic angle | | determineWeight | Maps a weight name to a CSS numeric weight, preferring OS/2 usWeightClass when available | | sortFontObjects | Sorts a fontsObjects map by ascending weight, placing Regular before Italic at equal weights | | createFontObject | Builds the full font object (id, title, weight, style, files, etc.) for a single font file | | uploadFontFiles | Core batch upload orchestrator — uploads each format to Sanity, generates CSS and metadata, then creates or updates font documents | | updateTypefaceDocument | Patches the parent typeface document's styles.fonts array with newly uploaded font references | | renameFontDocuments | Renames font document IDs across a typeface when a typeface slug changes | | updateFontPrices | Bulk-updates the price field across all font documents linked to a typeface | | sanitizeForSanityId | Converts arbitrary strings into valid Sanity document IDs (lowercase, hyphens, no special characters) |

CSS and file generation

| Export | Description | |---|---| | generateCssFile | Builds a @font-face CSS file from a WOFF2 blob — URL or base64 src, variable font axis descriptors, and metric-tuned fallback @font-face for CLS reduction | | buildVFDescriptors | Pure function — maps fontkit variation axes to CSS descriptors (font-weight, font-stretch, font-style), handling degenerate axes, slnt/ital priority, and min > max clamping | | generateFontData | Fetches a TTF URL, parses with fontkit, and patches the Sanity font document with metaData, metrics, glyphCount, opentypeFeatures, characterSet, and variable axes/instances | | buildFontMetadata | Pure function — extracts metaData and metrics from a fontkit instance without any Sanity side effects | | generateFontFile | Fires a POST to the consuming site's /api/sanity/fontWorker endpoint with the format codes to convert (otf, woff, woff2, eot, svg, data) | | generateSubset | Requests DS-WEB fingerprinted WOFF2 and display subset generation from an existing WOFF2 via fontWorker | | parseVariableFontInstances | Resolves named variable font instances into Sanity font document references, creating documents for missing instances | | getEmptyFontKit | Returns a zeroed-out fontkit-shaped placeholder used when no font binary is available |

Keyword utilities

| Export | Description | |---|---| | generateStyleKeywords | Builds weight and italic keyword lists (including abbreviation expansions like Bd → Bold, Lt → Light) for parsing font subfamily names | | reverseSpellingLookup | Resolves a font name abbreviation to its canonical weight name | | expandAbbreviations | Expands all known abbreviations in a string to full weight names | | removeWeightNames | Strips weight and italic keywords from a string, leaving only non-style words |

Constants

| Export | Description | |---|---| | SCRIPTS | Array of supported script variant names | | SCRIPTS_OBJECT | Map of script names to their display labels | | HtmlDescription | React component rendering the supported script list as formatted HTML |


Schema fields

Font document (font)

| Field | Type | Description | |---|---|---| | title | string | Full font name (e.g. MyFont SemiBold Italic) | | slug | slug | Sanitized document ID as a slug (current = document _id) | | typefaceName | string | Name of the parent typeface | | style | string | 'Regular' or 'Italic' | | weight | number | Numeric CSS weight (100–900) | | weightName | string | Human-readable weight name (e.g. 'SemiBold') | | subfamily | string | Subfamily name (e.g. 'Condensed') | | variableFont | boolean | true for variable fonts | | normalWeight | boolean | true when the weight is the normal/regular weight | | fileInput | object | Container for all uploaded format files | | fileInput.ttf | file | Uploaded TTF file (Sanity asset reference) | | fileInput.otf | file | OTF file (built from TTF or uploaded directly) | | fileInput.woff2 | file | WOFF2 file (built from TTF or uploaded directly) | | fileInput.woff | file | WOFF file | | fileInput.eot | file | EOT file (legacy) | | fileInput.svg | file | SVG font file (legacy) | | fileInput.css | file | Generated @font-face CSS file | | fileInput.woff2_web | file | DS-WEB fingerprinted WOFF2 for web delivery | | fileInput.woff2_subset | file | Display subset WOFF2 (Latin + Latin-1, fingerprinted) | | metaData | object | Font metadata — postscriptName, fullName, familyName, subfamilyName, copyright, version, genDate | | metrics | object | Font metrics — unitsPerEm, ascender, descender, lineGap, capHeight, xHeight, italicAngle, etc. | | glyphCount | number | Total number of glyphs | | opentypeFeatures | object | Available OpenType feature tags | | characterSet | object | Array of Unicode code points covered by the font | | variableInstanceReferences | array<object> | Maps variable font instance names to static font document references — [{ key: string, value: reference }] |

Typeface document (typeface)

| Field | Type | Description | |---|---|---| | styles.fonts | array<reference> | References to regular font documents | | styles.variableFont | array<reference> | References to variable font documents | | styles.collections | array<reference> | References to generated collection documents | | styles.pairs | array<reference> | References to generated pair documents | | styles.subfamilies | array<object> | Subfamily groups — each has title, _key, and fonts: array<reference> | | preferredStyle | reference | Reference to the preferred regular-weight font document |


Environment variables

| Variable | Required | Description | |---|---|---| | SANITY_STUDIO_SITE_URL | Yes | Base URL of the consuming site. Used by generateFontFile and generateSubset to call /api/sanity/fontWorker. | | SANITY_STUDIO_PROJECT_ID | Yes | Sanity project ID. Used to build CDN file URLs inside the uploaders. | | SANITY_STUDIO_DATASET | Yes | Sanity dataset name. Used alongside PROJECT_ID for CDN URLs. | | SANITY_STUDIO_SCRIPTS | No | Comma-separated script variant names (e.g. latin,greek,arabic). Controls which script tabs appear. | | SANITY_STUDIO_DEFAULT_COLLECTION_PRICE | No | Default per-font price for generated collections. | | SANITY_STUDIO_DEFAULT_PAIR_PRICE | No | Default price for generated pairs. |


Local development

To use the local source instead of the published npm package, symlink it into a foundry repo:

# From the sanity-font-manager directory:
npm run link:darden   # symlink into Darden Studio
npm run link:tdf      # symlink into The Designers Foundry
npm run link:mckl     # symlink into MCKL CMS
npm run link:all      # symlink into all three at once

Then run the watch build so consumers pick up changes live:

npm run dev

To restore the published package in a consumer repo, run npm install inside that repo.


License

MIT — Liiift Studio