Creating a font package
July 20, 2025 ยท View on GitHub
You can create a new font package either via a PR to this repository or by publishing your own font package on NPM.
We use a yeoman generator to fully automate the generation the fonts from a configuration file.
In the future the idea is to automate this to automatically release new fonts in line with upstream.
Below we describe how to create a font in this monorepo, the process for creating your own package would be quite similar.
Note: Before contributing a new font package, please read our Contributing Guidelines and follow the development workflow described there.
Quick Start
-
Set up development environment (see CONTRIBUTING.md):
pnpm install -
Create font package directory and config:
mkdir packages/my-font vi packages/my-font/.yo-rc.json git add packages/my-font/.yo-rc.json -
Generate the font package:
# Generate single font pnpm generate my-font # Or generate all fonts pnpm generate
Configuration Reference
The .yo-rc.json file contains all configuration for the font package generation. Here's the complete structure:
For most fonts you should be able to set the packageName and most other variaables will be derived from them, but you can adjust with the optional propertires when necessary.
Required Properties
packageName
- Type:
string - Description: The name of the node package and directory name
- Example:
"material-symbols" - Note: Currently assumes package will live in
@react-native-vector-iconsnamespace
Optional Properties
name
- Type:
string - Description: The name in capitalised sentence from
- Default: Title Case of packageName
- Example:
"Material Symbols"(frommaterial-symbols)
className
- Type:
string - Description: Class name for generated components
- Default: PascalCase of packageName
- Example:
"MaterialSymbols"(frommaterial-symbols)
postScriptName
- Type:
string - Description: PostScript name for the font
- Default: Same as className
- Example:
"MaterialSymbols"
fontFileName
- Type:
string - Description: Base filename for generated fonts
- Default: Same as className
- Example:
"MaterialSymbols"
upstreamFont
- Type:
string | object - Description: The upstream font package dependency where the font comes from a node module
- String format:
"package-name"- fetches latest version from npm - Object format:
{ "packageName": "@fortawesome/fontawesome-free", "versionRange": "^6", "registry": "https://registry.npmjs.org", "versionOnly": false }
customSrc
- Type:
string | boolean - Description: Path to custom source template or
trueto skip generation - Example:
"../../../../fontawesome-common/generators/app/templates/src/index.tsx"
customReadme
- Type:
boolean - Description: Skip README.md generation
- Default:
false
copyCustomFonts
- Type:
boolean - Description: Copy custom font files instead of generating
- Default:
false
commonPackage
- Type:
string - Description: Path to common package for shared functionality
- Default:
"common" - Example:
"fontawesome-common/fontawesome6"
meta
- Type:
object - Description: Metadata for multi-style fonts
- Example:
{ "defaultStyleName": "regular", "styleNames": ["regular", "solid", "brand"], "styles": { "regular": { "family": "FontAwesome6Free-Regular", "name": "FontAwesome6_Regular.ttf", "weight": 400 } } }
versions
- Type:
array - Description: Version history tracking. Updated when a new upstream font version is released.
- Example:
[ { "rnvi": "12.0.0", "upstream": "4.29.2" }, { "rnvi": "12.0.1", "upstream": "4.30.0" } ]
Build Steps
The buildSteps object defines the font generation pipeline. Steps are executed in this order:
preScript
Execute shell commands before font generation
{
"preScript": {
"script": "mkdir -p fonts\ncurl https://example.com/font.ttf > fonts/font.ttf"
}
}
renameSVGs
Rename and filter SVG files
{
"renameSVGs": {
"location": "../../node_modules/@primer/octicons/build/svg",
"keepPostfix": "-16"
}
}
- location: Source directory containing SVGs
- keepPostfix: Only keep files ending with this postfix, remove it from output
fixSVGPaths
Fix SVG path issues using oslllo-svg-fixer
{
"fixSVGPaths": {
"location": "../../node_modules/ionicons/dist/svg",
"cleanup": true
}
}
- location: Source directory or
"renamedSVGs"if after renameSVGs - cleanup: Remove source directory after processing
fontCustom
Generate font TTF from SVGs using FontCustom
{
"fontCustom": {
"location": "fixedSvg",
"cleanup": true
}
}
- location: Directory containing SVG files
- cleanup: Remove source directory after processing
fontforgeScript
Run FontForge script for font post-processing
{
"fontforgeScript": {
"script": "correct-direction.py"
}
}
- script: Script name in the generator's fontforge directory
glyphmap
Generate icon mapping files
{
"glyphmap": {
"mode": "css",
"location": "FontAwesome.css",
"prefix": ".fa-",
"cleanup": true
}
}
- mode:
"css"or"codepoints" - location: Source file or array of
[source, output]pairs - prefix: CSS class prefix (css mode only)
- cleanup: Remove source files after processing
copyFont
Copy existing font files
{
"copyFont": {
"location": "../../node_modules/font-awesome/fonts/fontawesome-webfont.ttf"
}
}
- location: Source file path or array of
[source, output]pairs
postScript
Execute shell commands after font generation
{
"postScript": {
"script": "node ../scripts/generate-metadata.js"
}
}
Configuration Examples
SVG to Font Generation (Feather Icons)
{
"generator-react-native-vector-icons": {
"packageName": "feather",
"upstreamFont": "feather-icons",
"buildSteps": {
"fontCustom": {
"location": "node_modules/feather-icons/dist/icons"
},
"glyphmap": {
"mode": "css",
"cleanup": true
}
},
"versions": [{ "rnvi": "12.0.0", "upstream": "4.29.2" }]
}
}
CSS-based Font (FontAwesome)
{
"generator-react-native-vector-icons": {
"packageName": "fontawesome",
"postScriptName": "FontAwesome",
"fontFileName": "FontAwesome",
"className": "FontAwesome",
"upstreamFont": "font-awesome",
"buildSteps": {
"glyphmap": {
"location": "../../node_modules/font-awesome/css/font-awesome.css",
"mode": "css",
"prefix": ".fa-"
},
"copyFont": {
"location": "../../node_modules/font-awesome/fonts/fontawesome-webfont.ttf"
}
},
"versions": [{ "rnvi": "12.0.0", "upstream": "4.7.0" }]
}
}
Codepoints-based Font (Material Icons)
{
"generator-react-native-vector-icons": {
"packageName": "material-icons",
"postScriptName": "MaterialIcons-Regular",
"buildSteps": {
"preScript": {
"script": "mkdir -p fonts\nREF='f7bd4f25f3764883717c09a1fd867f560c9a9581'\ncurl https://raw.githubusercontent.com/google/material-design-icons/$REF/font/MaterialIcons-Regular.codepoints -Ls > MaterialIcons-Regular.codepoints\ncurl https://raw.githubusercontent.com/google/material-design-icons/$REF/font/MaterialIcons-Regular.ttf -Ls > fonts/MaterialIcons.ttf"
},
"glyphmap": {
"location": "MaterialIcons-Regular.codepoints",
"mode": "codepoints",
"prefix": ".mdi-",
"cleanup": true
}
},
"versions": [{ "rnvi": "12.0.0", "upstream": "0.0.1" }]
}
}
Multi-style Font (FontAwesome 6)
{
"generator-react-native-vector-icons": {
"packageName": "fontawesome6",
"className": "FontAwesome6",
"commonPackage": "fontawesome-common/fontawesome6",
"customSrc": "../../../../fontawesome-common/generators/app/templates/src/index.tsx",
"customReadme": true,
"upstreamFont": {
"packageName": "@fortawesome/fontawesome-free",
"versionRange": "^6"
},
"meta": {
"defaultStyleName": "regular",
"styleNames": ["regular", "solid", "brand"],
"styles": {
"regular": {
"family": "FontAwesome6Free-Regular",
"name": "FontAwesome6_Regular.ttf",
"weight": 400
},
"solid": {
"family": "FontAwesome6Free-Solid",
"name": "FontAwesome6_Solid.ttf",
"weight": 900
},
"brand": {
"family": "FontAwesome6Brands-Regular",
"name": "FontAwesome6_Brands.ttf",
"weight": 400
}
}
},
"buildSteps": {
"glyphmap": {
"location": "node_modules/@fortawesome/fontawesome-free/css/all.css",
"mode": "css",
"prefix": ".fa-"
},
"copyFont": {
"location": [
["node_modules/@fortawesome/fontawesome-free/webfonts/fa-brands-400.ttf", "FontAwesome6_Brands"],
["node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.ttf", "FontAwesome6_Regular"],
["node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.ttf", "FontAwesome6_Solid"]
]
},
"postScript": {
"script": "node ../fontawesome-common/scripts/generate-fontawesome-metadata --path node_modules/@fortawesome/fontawesome-free --output glyphmaps/FontAwesome6_meta.json"
}
},
"versions": [{ "rnvi": "12.0.0", "upstream": "6.7.2" }]
}
}
SVG Processing with Fixes (Ionicons)
{
"generator-react-native-vector-icons": {
"packageName": "ionicons",
"upstreamFont": "ionicons",
"buildSteps": {
"fixSVGPaths": {
"location": "../../node_modules/ionicons/dist/svg"
},
"fontCustom": {
"location": "fixedSvg",
"cleanup": true
},
"fontforgeScript": {
"script": "correct-direction.py"
},
"glyphmap": {
"mode": "css",
"cleanup": true
}
},
"versions": [{ "rnvi": "12.0.0", "upstream": "7.4.0" }, { "rnvi": "12.0.1", "upstream": "8.0.8" }]
}
}
Custom Font Package (Fontello)
{
"generator-react-native-vector-icons": {
"packageName": "fontello",
"customReadme": true,
"customSrc": true,
"copyCustomFonts": true
}
}
Build Process
- Install Dependencies: The generator installs upstream font packages
- Template Generation: Creates package.json, TypeScript files, Android/iOS config
- Build Steps Execution: Runs configured build steps in order
- Font Generation: Uses FontCustom in Docker container if needed
- Glyph Mapping: Generates JSON mapping files for icons
Testing Your Font Package
After generating your font package, test it in the example app:
# Start the example app (see CONTRIBUTING.md for details)
pnpm run example start
pnpm run example android # or ios
Development Workflow
For ongoing development and testing:
- Make template changes to
packages/generator-react-native-vector-icons/src/app/templates/ - Regenerate fonts:
pnpm generate my-font - Test changes in the IconExplorer app
- Run linting and tests (see CONTRIBUTING.md):
pnpm run lint pnpm run test
Submitting Your Font Package
When ready to contribute your font package:
- Follow commit conventions described in CONTRIBUTING.md
- Create a pull request following the PR guidelines
- Include documentation updates if needed
- Ensure all tests pass in CI
Font Versioning
Font package versions are independent of upstream font versions. We track the mapping in each font's README.md file as described in CONTRIBUTING.md.
Manual Generator Execution
If needed, you can run the generator manually:
cd packages/my-font
npx yo react-native-vector-icons --current-version=1.0.0
Note: The
pnpm generatecommand is the preferred method as it handles version management automatically.