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.
-
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
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.
- 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
- Type:
string - Description: The name in capitalised sentence from
- Default: Title Case of packageName
- Example:
"Material Symbols"(frommaterial-symbols)
- Type:
string - Description: Class name for generated components
- Default: PascalCase of packageName
- Example:
"MaterialSymbols"(frommaterial-symbols)
- Type:
string - Description: PostScript name for the font
- Default: Same as className
- Example:
"MaterialSymbols"
- Type:
string - Description: Base filename for generated fonts
- Default: Same as className
- Example:
"MaterialSymbols"
- 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 }
- Type:
string | boolean - Description: Path to custom source template or
trueto skip generation - Example:
"../../../../fontawesome-common/generators/app/templates/src/index.tsx"
- Type:
boolean - Description: Skip README.md generation
- Default:
false
- Type:
boolean - Description: Copy custom font files instead of generating
- Default:
false
- Type:
string - Description: Path to common package for shared functionality
- Default:
"common" - Example:
"fontawesome-common/fontawesome6"
- 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 } } }
- 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" } ]
The buildSteps object defines the font generation pipeline. Steps are executed in this order:
Execute shell commands before font generation
{
"preScript": {
"script": "mkdir -p fonts\ncurl https://example.com/font.ttf > fonts/font.ttf"
}
}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
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
Generate font TTF from SVGs using FontCustom
{
"fontCustom": {
"location": "fixedSvg",
"cleanup": true
}
}- location: Directory containing SVG files
- cleanup: Remove source directory after processing
Run FontForge script for font post-processing
{
"fontforgeScript": {
"script": "correct-direction.py"
}
}- script: Script name in the generator's fontforge directory
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
Copy existing font files
{
"copyFont": {
"location": "../../node_modules/font-awesome/fonts/fontawesome-webfont.ttf"
}
}- location: Source file path or array of
[source, output]pairs
Execute shell commands after font generation
{
"postScript": {
"script": "node ../scripts/generate-metadata.js"
}
}{
"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" }]
}
}{
"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" }]
}
}{
"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" }]
}
}{
"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" }]
}
}{
"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" }]
}
}{
"generator-react-native-vector-icons": {
"packageName": "fontello",
"customReadme": true,
"customSrc": true,
"copyCustomFonts": true
}
}- 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
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 iosFor 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
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 package versions are independent of upstream font versions. We track the mapping in each font's README.md file as described in CONTRIBUTING.md.
If needed, you can run the generator manually:
cd packages/my-font
npx yo react-native-vector-icons --current-version=1.0.0Note: The
pnpm generatecommand is the preferred method as it handles version management automatically.