RORK LABJP
TOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude CodeSIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App StoreMAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessageNATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the roundTOOLING — Rork's developer repos keep moving: rork-xcode was updated on July 16, rork-device on July 15, and rork-plist on July 13OPUS46 — Claude Opus 4.6 is live in Rork, and Rork Max is built to assemble apps on top of Claude CodeSIM — A cloud iOS simulator runs in the browser, with one click to install on a device and two clicks to publish to the App StoreMAX — Rork Max emits pure Swift rather than React Native, reaching iPhone, iPad, Apple Watch, Apple TV, Vision Pro, and even iMessageNATIVE — That opens up HealthKit, ARKit and LiDAR, NFC, Dynamic Island, Live Activities, 3D through Metal, and on-device inference with Core MLSEED — Rork raised a $15M seed led by Left Lane Capital, with Peak XV and a16z Speedrun joining the round
Articles/Dev Tools
Dev Tools/2026-04-08Intermediate

Rork Max App Works in Expo Go But Breaks in Production Build: Fix Guide

Fix common issues where Rork Max apps work in Expo Go preview but fail in real device builds. Covers custom fonts, native modules, environment variables, and dynamic assets that behave differently between Expo Go and production builds.

Rork Max229Expo GoBuild Errors2Troubleshooting38React Native209Device Testing6EAS Build14

Rork Max App Works in Expo Go But Breaks in Production Build: Fix Guide

"It worked perfectly in the preview." This is one of the most common things developers say right before a stressful release. Your Rork Max app looks great in Expo Go, you submit it, and then users start reporting crashes or missing features.

The reason is almost always the same: Expo Go and native builds run in fundamentally different environments, and some things that work in one don't automatically work in the other.

This guide walks through the most common mismatches and how to fix each one.

Why Expo Go and Native Builds Behave Differently

Expo Go is a pre-compiled shell app that runs your JavaScript code. It includes the Expo SDK's built-in modules, but nothing else. It's fast to test with, but it doesn't represent your actual production app.

EAS Build / Native Build produces the real binary that goes to the App Store or Google Play. All your app.json configuration is applied, custom native code is compiled in, and it runs exactly as users will experience it.

The gap between these two environments is the source of "works in preview, broken in production" bugs.

Issue #1: Custom Fonts Don't Show in Builds

Symptom: Custom fonts appear in Expo Go but fall back to system defaults in the production build.

// Wrong: loading fonts without waiting for completion
import * as Font from 'expo-font';
 
export default function App() {
  Font.loadAsync({
    'NotoSans': require('./assets/fonts/NotoSans-Regular.ttf'),
  });
  // This renders before fonts are loaded — unreliable in builds
  return <Text style={{ fontFamily: 'NotoSans' }}>Hello</Text>;
}
 
// Correct: use useFonts hook and wait for loading to complete
import { useFonts } from 'expo-font';
import * as SplashScreen from 'expo-splash-screen';
import { useEffect } from 'react';
 
SplashScreen.preventAutoHideAsync();
 
export default function App() {
  const [fontsLoaded, fontError] = useFonts({
    'NotoSans': require('./assets/fonts/NotoSans-Regular.ttf'),
    'NotoSans-Bold': require('./assets/fonts/NotoSans-Bold.ttf'),
  });
  
  useEffect(() => {
    if (fontsLoaded || fontError) {
      SplashScreen.hideAsync();
    }
  }, [fontsLoaded, fontError]);
  
  if (!fontsLoaded && !fontError) {
    return null; // show splash screen while loading
  }
  
  return <Text style={{ fontFamily: 'NotoSans' }}>Hello</Text>;
}

Also verify your font files are declared in app.json:

{
  "expo": {
    "assets": [
      "./assets/fonts/NotoSans-Regular.ttf",
      "./assets/fonts/NotoSans-Bold.ttf"
    ]
  }
}

Issue #2: Native Modules Crash in Builds

Symptom: A feature works in Expo Go but crashes the app in production. Often happens with camera, maps, payments, or Bluetooth.

# Diagnose compatibility issues
npx expo-doctor
 
# Common culprits:
# react-native-camera → use expo-camera instead
# react-native-maps version mismatches → use v1.7+
# @stripe/stripe-react-native → needs custom dev client in Expo Go

Option A: Switch to Expo-managed equivalents

// Before: native module that isn't in Expo Go
import { Camera } from 'react-native-camera';
 
// After: Expo-managed module with full build support
import { CameraView, useCameraPermissions } from 'expo-camera';

Option B: Use Development Build (Custom Dev Client)

A Development Build gives you a preview environment that matches your production build, with hot reload. This is the gold standard approach:

# Install EAS CLI if you haven't
npm install -g eas-cli
eas login
 
# Create a development build
eas build --profile development --platform ios
 
# Start the dev server in dev-client mode
npx expo start --dev-client

Once installed on your device, this Development Build works like Expo Go but includes all your native modules — eliminating the preview vs. production gap entirely.

Issue #3: Environment Variables Missing in Builds

Symptom: process.env.EXPO_PUBLIC_API_URL is undefined in the production build.

# .env file values don't always make it into the build
EXPO_PUBLIC_API_URL=https://api.example.com
// Unreliable: environment variable may be undefined in builds
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
 
// Reliable: use app.config.js to bake values in at build time
// app.config.js
export default {
  expo: {
    name: "My App",
    extra: {
      apiUrl: process.env.EXPO_PUBLIC_API_URL ?? "https://api.example.com",
      apiKey: process.env.EXPO_PUBLIC_API_KEY,
    }
  }
};
// Access in your app
import Constants from 'expo-constants';
 
const apiUrl = Constants.expoConfig?.extra?.apiUrl;

For EAS Build production environments:

// eas.json
{
  "build": {
    "production": {
      "env": {
        "EXPO_PUBLIC_API_URL": "https://api.production.example.com"
      }
    },
    "preview": {
      "env": {
        "EXPO_PUBLIC_API_URL": "https://api.staging.example.com"
      }
    }
  }
}

Use EAS Secrets for sensitive values:

eas secret:create --scope project --name STRIPE_KEY --value "sk_live_xxxxx"

Issue #4: Images or Assets Missing in Builds

Symptom: Images display in Expo Go but show broken icons in the production build.

// Wrong: dynamic require paths don't work in builds
const imageName = "cat";
const image = require(`./assets/images/${imageName}.png`); // breaks in builds!
 
// Correct: use static requires with an object map
const images = {
  cat: require('./assets/images/cat.png'),
  dog: require('./assets/images/dog.png'),
  bird: require('./assets/images/bird.png'),
};
 
// Then select dynamically from the map
const image = images[imageName]; // works in both environments

Declare your asset directories in app.json:

{
  "expo": {
    "assets": ["./assets/images/", "./assets/icons/"],
    "icon": "./assets/icon.png",
    "splash": {
      "image": "./assets/splash.png"
    }
  }
}

The Long-Term Fix: Adopt Development Build as Your Primary Test Environment

The single most effective change you can make is to stop using Expo Go as your primary test environment and switch to Development Build. Here's why:

  • Development Build = same native environment as production
  • Still has hot reload for fast iteration
  • Catches native module issues before release
  • Supports environment-specific configurations
# One-time setup
npm install -g eas-cli
eas login
eas build:configure
 
# Create development builds for both platforms
eas build --profile development --platform all
 
# Daily workflow: start with dev-client flag
npx expo start --dev-client

After installing the development build on your test devices, your day-to-day development experience is the same as using Expo Go — but what you see is what users will get.

Looking back

The most common Expo Go vs. production build inconsistencies:

  • Fonts missing → Use useFonts hook, declare fonts in app.json assets array
  • Native module crashes → Migrate to Expo equivalents or use Development Build
  • Environment variables undefined → Use app.config.js extra fields or EAS environment variables
  • Dynamic assets broken → Use static requires with object lookup maps

Switching to Development Build as your primary test environment eliminates the entire class of "worked in preview, broken in production" bugs. It's the single change with the highest return on investment in your Rork Max development workflow.

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-07-08
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.
Dev Tools2026-06-29
Rork × Vision Camera v4: A Production-Grade Camera Stack with QR, OCR, and ML Inference
Wire React Native Vision Camera v4 into a Rork project end-to-end — frame processors, ML inference, QR/OCR, plus battery and thermal tuning, a real-device test matrix, store review, and a staged rollout.
Dev Tools2026-06-27
Catch Real-Device Bugs Before You Ship: A Pre-Submission Checklist for Rork Share Links
Rork's editor preview runs in an ideal environment, so it hides bugs that only appear on real hardware. Here are the seven device differences to clear before you hand out a share link, in the order to check them, with the code to set up first.
📚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 →