docs/CREATE_FONT_PACKAGE.md
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.
string"material-symbols"@react-native-vector-icons namespacestring"Material Symbols" (from material-symbols)string"MaterialSymbols" (from material-symbols)string"MaterialSymbols"string"MaterialSymbols"string | object"package-name" - fetches latest version from npm{
"packageName": "@fortawesome/fontawesome-free",
"versionRange": "^6",
"registry": "https://registry.npmjs.org",
"versionOnly": false
}
string | booleantrue to skip generation"../../../../fontawesome-common/generators/app/templates/src/index.tsx"booleanfalsebooleanfalsestring"common""fontawesome-common/fontawesome6"object{
"defaultStyleName": "regular",
"styleNames": ["regular", "solid", "brand"],
"styles": {
"regular": {
"family": "FontAwesome6Free-Regular",
"name": "FontAwesome6_Regular.ttf",
"weight": 400
}
}
}
array[
{ "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"
}
}
Fix SVG path issues using oslllo-svg-fixer
{
"fixSVGPaths": {
"location": "../../node_modules/ionicons/dist/svg",
"cleanup": true
}
}
"renamedSVGs" if after renameSVGsGenerate font TTF from SVGs using FontCustom
{
"fontCustom": {
"location": "fixedSvg",
"cleanup": true
}
}
Run FontForge script for font post-processing
{
"fontforgeScript": {
"script": "correct-direction.py"
}
}
Generate icon mapping files
{
"glyphmap": {
"mode": "css",
"location": "FontAwesome.css",
"prefix": ".fa-",
"cleanup": true
}
}
"css" or "codepoints"[source, output] pairsCopy existing font files
{
"copyFont": {
"location": "../../node_modules/font-awesome/fonts/fontawesome-webfont.ttf"
}
}
[source, output] pairsExecute 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
}
}
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
For ongoing development and testing:
packages/generator-react-native-vector-icons/src/app/templates/pnpm generate my-font
pnpm run lint
pnpm run test
When ready to contribute your font package:
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.0
Note: The
pnpm generatecommand is the preferred method as it handles version management automatically.