Open-source project
software-mansion-labs/react-native-nano-icons avatar
software-mansion-labs/react-native-nano-icons

react-native-nano-icons turns your SVGs into a font at build time

High-performance icon rendering for React Native & Expo

635 stars19 forksTypeScriptMIT

At a glance

What is it?
react-native-nano-icons converts a folder of SVG files into an icon font during the build and renders each icon as a native text glyph, bypassing the React component tree, which is what makes it cheap on screens that repeat the same small symbol many times. It suits React Native and Expo apps with custom icons, and it requires the new architecture and a font-generation step in your pipeline.
Who is it for?
Adopt react-native-nano-icons when your React Native or Expo app repeats the same small icon many times on screen, especially in lists, tab bars and inline badges, and when you want your own SVGs rather than a bundled icon pack, since the build step converts them to a font and the runtime cost is a text glyph.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem is fifty identical icons in a scrollable list

Nano Icons is described as high-performance icon rendering for React Native and Expo, and the README makes the case in terms of a specific screen rather than a benchmark table. It is at its best when the same small symbols appear many times on screen: row icons in a list, tab bars, inline badges.

The reasoning starts with react-native-svg. The README says it works, but it was not designed for icons, and every SVG component spins up a full React subtree that gets parsed, reconciled and laid out on each mount. One icon is fine. Fifty in a scrollable list and your UI starts paying for it.

The comparison with expo-image and similar is about rasterization pipelines: it is a better choice for complex vector graphics, but each image goes through its own pipeline, which is not optimized for drawing many copies of the same small symbol.

The third comparison is with react-native-vector-icons, and it is the one that defines the target user. That library is already font-based, so rendering is fast, and it is a good fit if you use a bundled icon pack from one of the well known icon font libraries. But if you need your own custom icons, you are back to managing font files manually with external tools, which is exactly the workflow Nano Icons removes.

SVGs become a font, icons become native text glyphs

The mechanism is two-stage, and both stages matter.

At build time, your SVGs are automatically converted into an optimized icon font. At runtime, each icon renders as a single native text glyph stack, bypassing React's component tree entirely. The result, as the README puts it, is dramatically less work per icon, especially in screens with many repeated symbols.

The developer experience is deliberately minimal. You drop your SVGs in a folder and use them as a fully typed component by name. File names become icon names, so heart.svg is rendered with an Icon element with the name heart.

The reference directory layout looks like this:

code
assets/icons/my-icons/
├── heart.svg
├── search.svg
├── flag-us.svg
└── ...

Only the .svg format is supported, which is a constraint worth noting if you have design assets in other formats. The typing is the other half of the value: because the icon names come from the folder contents at build time, the component is fully typed, and a typo in a name is a compile error rather than a blank square at runtime.

Two setup paths: an Expo config plugin or a CLI run

There are two ways to run the font generation pipeline, and which one you need follows from whether your app has a prebuild step.

In an Expo app, the library uses an Expo Config Plugin that hooks into the prebuild phase. That automatically generates the .ttf and .glyphmap.json files and links the font into the native iOS and Android projects. The configuration lives in app.json:

JSON
{
  "expo": {
    "plugins": [
      [
        "react-native-nano-icons",
        {
          "iconSets": [
            {
              "inputDir": "./assets/icons/my-icons"
            }
          ]
        }
      ]
    ]
  }
}

The plugin accepts an iconSets array, so one build can generate multiple distinct fonts. After that you run npx expo prebuild and rebuild the app once, for example with npx expo run:ios, and from then on the Metro plugin picks up SVG edits without another rebuild.

For bare React Native, React Native Web and Expo Go, there is no prebuild step, so the same pipeline is driven by the CLI. You add a .nanoicons.json file with the same iconSets shape, with paths relative to its own folder, then run the CLI from the app root:

sh
   npx react-native-nano-icons

The CLI is flexible about where things live. If the config lives elsewhere in the app you pass it with --path path/to/.nanoicons.json, from outside the app such as a monorepo root you pass the app folder with --path apps/mobile, and if the config's folder has a package.json the CLI links there, otherwise it links in the current directory.

What the runtime API looks like beyond the Icon component

The table of contents points to a reference section that goes past rendering a single icon, and two entries there are worth knowing about before you design around the package.

There is a symbolSets option alongside the iconSets option, and a nativeNanoSymbol() function. The distinction, judging by the names and the separate documentation entries, is that icons go through the generated font while native symbols are drawn by the platform's own symbol rendering. The documentation for both is in the reference section rather than in the quick start, which is a hint that this is where the interesting behaviour lives.

Then there is the font integrity side of the API: addFontIntegrityListener() and getFontIntegrityIssues(). The presence of a listener and an issue list in the public API tells you the package expects the font on the device to be able to drift from the font the app was built against, and gives you a way to detect it at runtime rather than discovering a rendering problem as blank or mismatched glyphs.

There is also a multicolor icons guide in the Guides section, which is one of the four topics the documentation covers, along with native symbols, OTA updates and dynamic linking, and rebuilds and font integrity. The last of those, rebuilds and font integrity, is the one to read first if you ship over the air, because it is the connection between the two APIs above.

The known limitations section is the honest part

The README has a Known Limitations section in its table of contents, placed right before the font generation pipeline documentation, which is the right place for it and a good sign about the project's honesty.

The structural limitation is the platform floor. The supported platforms are React Native 0.81 and above with the new architecture only, iOS 15.1 and above, Android API 24 and above, web, Expo Go, and tvOS 15.1 and above. The new architecture requirement is the significant one, because it means an app still on the old architecture cannot use the package at all.

The other limitation is inherent to the design. An icon font stores shapes as glyph outlines, so an icon that needs more than one colour cannot be a single glyph. That is why multicolor icons get their own guide, and it is the point where a font-based approach stops being the right tool and the project will point you at a different one.

The rebuild and OTA section addresses the other real problem. Because the font is a build artifact, a JavaScript-only update can add an icon name the installed font does not contain. The OTA updates and dynamic linking guide is about handling that case, and the integrity functions are the mechanism for detecting it.

A young monorepo with a benchmark harness of its own

The repository is a Yarn 4 monorepo with the package and the examples as workspaces, and the script names in the root package.json describe the development setup precisely.

There are separate example applications: an Expo example, a bare React Native example, and a NanoIconsBenchmarking example, each with ios and android build scripts and separate release variants. The benchmark example is the interesting one, since the performance claims in the README are the reason to consider this package at all, and the repository ships the harness used to produce them. There is also a font-benchmark script at the repository root, run with node scripts/font-benchmark.mjs, which suggests the font generation step itself is measured rather than assumed to be free.

The tooling is modern and thorough. The package manager is pinned to [email protected] with a .yarn/ directory and a .yarnrc.yml, husky handles git hooks with a .lintstagedrc.json, and there are scripts for running the test suite, a TypeScript check across all workspaces, linting and formatting. The linting configuration is a flat eslint.config.mjs at the root.

The release history is very young, which is the main caveat. There is a v1.0.0-beta.1 on 2026-09-25, v1.0.0 on 2026-10-12 and v1.0.1 on 2026-10-14, and the last push to main was on 2026-10-14. A 1.0 that is two weeks old will still be finding its edges, so treat the API as settled but the ecosystem, meaning the icon packs and the guides that other projects write against it, as still forming. The licence is MIT, and there is a LICENSES.md alongside the LICENSE file.

Editorial conclusion

Adopt react-native-nano-icons when your React Native or Expo app repeats the same small icon many times on screen, especially in lists, tab bars and inline badges, and when you want your own SVGs rather than a bundled icon pack, since the build step converts them to a font and the runtime cost is a text glyph. Do not adopt it for complex vector graphics or illustrations, since the README itself points at expo-image for richer artwork, and do not adopt it in an app that has not moved to the new architecture, because the package supports React Native 0.81 and above with the new architecture only. Before you commit, decide how the font will be regenerated, since the build produces .ttf and .glyphmap.json files, read the known limitations section on multicolor icons, native symbols and rebuilds, and note that this is a young package, at v1.0.1 with the first stable release on 2026-10-12.

Frequently asked questions

How do I install react-native-nano-icons and add my own icons?

Run npm install react-native-nano-icons, create a directory for your icon set and place your .svg files in it, since only the svg format is supported. File names become icon names, so heart.svg is rendered with an Icon element using the name heart.

How do I configure the icon set in an Expo app?

The library uses an Expo Config Plugin that hooks into the prebuild phase, so you add it to the plugins array in app.json with an iconSets array whose entries carry an inputDir path. Then run npx expo prebuild and rebuild the app once, after which the Metro plugin picks up SVG edits without a rebuild.

How do I use react-native-nano-icons in a bare React Native app?

Bare apps have no prebuild step, so you add a .nanoicons.json file with the same iconSets shape, with paths relative to that file, and run npx react-native-nano-icons from the app root. The CLI links the font where the config's folder has a package.json, or in the current directory otherwise, and it accepts a --path argument for a config or app folder elsewhere.

What platforms and React Native versions does react-native-nano-icons support?

The supported list is React Native 0.81 and above with the new architecture only, iOS 15.1 and above, Android API 24 and above, web, Expo Go, and tvOS 15.1 and above.

What are the known limitations of react-native-nano-icons?

The package requires the new architecture, and an icon font stores outlines as glyphs, so multicolor icons need their own handling, which the README covers in a dedicated guide. It also has sections on native symbols, OTA updates and dynamic linking, and on rebuilds and font integrity, including the addFontIntegrityListener and getFontIntegrityIssues functions.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. software-mansion-labs/react-native-nano-icons on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/software-mansion-labs-react-native-nano-icons.svg)](https://hysenlabs.com/projects/software-mansion-labs-react-native-nano-icons)

Was this useful?