RORK LABJP
MAX — Rork Max generates native Swift apps for iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and iMessageNATIVE — Rork Max unlocks native features: AR/LiDAR, Metal 3D, widgets, Dynamic Island, Live Activities, HealthKit, and Core MLSTACK — Rork builds native iOS and Android apps with React Native (Expo) from a plain-English descriptionGROWTH — Rork now attracts over 743,000 monthly visits, growing at an 85% ratePRICE — Rork is free to start, with paid plans from $25/monthTREND — Gartner projects 75% of new apps will be built with low-code/no-code by the end of 2026MAX — Rork Max generates native Swift apps for iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and iMessageNATIVE — Rork Max unlocks native features: AR/LiDAR, Metal 3D, widgets, Dynamic Island, Live Activities, HealthKit, and Core MLSTACK — Rork builds native iOS and Android apps with React Native (Expo) from a plain-English descriptionGROWTH — Rork now attracts over 743,000 monthly visits, growing at an 85% ratePRICE — Rork is free to start, with paid plans from $25/monthTREND — Gartner projects 75% of new apps will be built with low-code/no-code by the end of 2026
Articles/Dev Tools
Dev Tools/2026-07-08Intermediate

Your SVG Icon Shows in Expo Go but Vanishes in a Build — Making SVGs Render Reliably in Rork Apps

When a .svg import renders nothing, throws a resolve error, or ignores your theme colors in Rork and Expo apps, here is how to fix it with metro.config.js, react-native-svg-transformer, and currentColor — with working code.

Troubleshooting37SVGExpo135React Native199Icons

I was swapping the tab-bar icons in a wallpaper app for a set of thin, custom SVGs. They looked perfect in Expo Go, so I built a development build with confidence — and on the very same screen, the icons had quietly disappeared. No error. Just a transparent hole where a shape should have been. It took me the better part of an hour to trace it, so let me lay out what was going on for anyone stuck at the same spot.

The symptoms

Anything involving SVG icons tends to fail in one of these shapes:

  • Renders in Expo Go, but draws nothing in a development or production build
  • A red screen reading Unable to resolve module ./icon.svg
  • Renders, but the color stays black and never follows dark mode
  • Shows on iOS but not Android, or the other way around

The tricky part is that it usually fails silently as a transparent shape rather than an error. The layout box is still reserved, so the icon is invisible while occupying space — which sent me chasing CSS-style problems for far too long.

How to reproduce it

This happens with code Rork generated, or code you added yourself, that loads an SVG file like this:

import TabIcon from "../assets/icons/home.svg";
 
export function HomeTab() {
  return <TabIcon width={24} height={24} />;
}

It looks completely reasonable. But out of the box, the React Native / Expo Metro bundler treats .svg as an image asset. That means <TabIcon /> is an image-source object, not a component, so rendering it as a component produces nothing.

When it happens to work in Expo Go, that is usually an environment-specific accident — a stale cache, an old bundle, a different load path — and leaning on it will bite you in production.

Why the icon doesn't show

There are two root causes.

The first: there is no mechanism to import .svg as a component. React Native has no equivalent of the web's <img src="...svg">; drawing an SVG requires react-native-svg. To treat a .svg file directly as a JSX component, you also need react-native-svg-transformer wired into Metro. Without it, Metro keeps handling SVGs as static assets.

The second: the color is baked into the SVG file. Design tools often export SVGs with concrete fills like fill="#111111", which leaves your app unable to recolor them per theme. That black-that-stays-black-in-dark-mode look is exactly this case.

Fix 1: let Metro import .svg as a component

Install the packages first. Under Expo, npx expo install pulls versions matched to your SDK.

npx expo install react-native-svg
npm install --save-dev react-native-svg-transformer

Then edit metro.config.js at the project root. With Expo, building on top of getDefaultConfig is the safe path. Create the file if it doesn't exist yet.

// metro.config.js
const { getDefaultConfig } = require("expo/metro-config");
 
const config = getDefaultConfig(__dirname);
 
// Let SVGs be treated as JSX components
config.transformer.babelTransformerPath = require.resolve(
  "react-native-svg-transformer"
);
 
// Move .svg out of "assets" and into "source code" resolution
config.resolver.assetExts = config.resolver.assetExts.filter(
  (ext) => ext !== "svg"
);
config.resolver.sourceExts = [...config.resolver.sourceExts, "svg"];
 
module.exports = config;

The key is removing svg from assetExts and adding it to sourceExts. Skip these two lines and Metro will keep treating SVGs as images even with the transformer installed.

If you use TypeScript, you'll get red squiggles without a type for importing .svg, so add one declaration file.

// declarations.d.ts
declare module "*.svg" {
  import type { SvgProps } from "react-native-svg";
  const content: React.FC<SvgProps>;
  export default content;
}

Finally, after changing config, clear the Metro cache and restart. Skip this and an old resolution lingers, making a fixed setup look broken.

npx expo start --clear

Now that same import TabIcon from "../assets/icons/home.svg" renders directly as a component.

Fix 2: follow the theme with currentColor

If it renders but the color never changes, replace the SVG's fixed fill with currentColor. react-native-svg-transformer bridges currentColor inside the SVG to the color prop you pass the component.

If your exported path looks like this,

<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  <path fill="#111111" d="M12 3l9 7v11h-6v-6H9v6H3V10z" />
</svg>

swap the fixed color for currentColor:

<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  <path fill="currentColor" d="M12 3l9 7v11h-6v-6H9v6H3V10z" />
</svg>

On the call site, just pass color and it switches with your theme.

import { useColorScheme } from "react-native";
import HomeIcon from "../assets/icons/home.svg";
 
export function HomeTab() {
  const scheme = useColorScheme();
  const tint = scheme === "dark" ? "#F2F2F7" : "#1C1C1E";
  return <HomeIcon width={24} height={24} color={tint} />;
}

For multi-color illustrations, set only the parts you want to recolor to currentColor and leave accent colors fixed. For single-color icons, unifying every path to currentColor means a palette change later happens in one place.

Which approach to choose

SituationBest fit
Many designer-exported SVGsFix 1 (import via transformer)
A few icons, or shapes that change dynamicallyHand-write with Svg / Path from react-native-svg
Colors should follow the themeAdd Fix 2 (currentColor)

I settled on loading small tab-bar and list-row icons as .svg via the transformer, with colors unified to currentColor. Swapping a design becomes a matter of replacing the .svg file, which keeps day-to-day maintenance very light.

Prevention

To avoid the same trap, I now lock down three things up front.

First, add metro.config.js and the type declaration on day one of a project. Adding them later steals time on "why won't this show" investigations.

Second, whenever I add an SVG, I check it once in a development build (not Expo Go). Expo Go can behave differently because of its bundled libraries, so working there is no guarantee it works in production.

Third, I made --clear a reflex after touching config. Most "I fixed it but nothing changed" moments around SVG came down to Metro holding a stale resolution.

References

Even a single small icon becomes far easier to maintain once you understand how it renders. I hope this saves someone the hour it cost me. Thank you for reading.

Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Dev Tools2026-05-25
Fixing Layout Bleed on Android 15 (API 35) in Rork Apps
Once you bump targetSdkVersion to 35, Android 15 enforces edge-to-edge display, and Rork-generated tab bars and headers start sliding under the system bars. Here are the patterns I use with react-native-edge-to-edge and useSafeAreaInsets to fix it properly.
Dev Tools2026-05-03
5 Things to Check First When Rork Shows 'Unable to Resolve Module'
Walk through the five most common causes of the 'Unable to resolve module' error in Rork, React Native, and Expo projects, with the exact commands and the order in which to check them.
Dev Tools2026-04-24
Diagnosing Metro Bundler Freezes and Broken Fast Refresh in Rork Apps
When your Rork-generated Expo app stops picking up code changes or Metro freezes mid-bundle, here is the diagnostic order and the safe reset steps that actually work.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →