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-24Intermediate

Rork WebView Is Blank or Won't Load: 6 Causes to Check Before You Ship

Dropped a WebView into your Rork app and got a silent blank screen on device? Here's the checklist I run through, in the order that catches the most bugs first.

Rork515WebView2Troubleshooting38React Native209iOS109Android43

Rork apps tend to reach a point where you need to embed a web view — an internal dashboard, a third-party login page, a live docs preview. It works in the simulator, it works in Companion, and then you install a real build on a real phone and the view is completely, silently, blank. I've personally lost half a day to this right before a release, when an Android device wouldn't render anything I threw at it.

What makes WebView failures painful is that the component rarely throws a loud error. Instead it just... stays empty. The good news is the failure modes are a small, well-known set. Here are the six causes I walk through in order whenever a react-native-webview ends up blank in a Rork-generated Expo project.

Before anything else: figure out where it actually stopped

A blank WebView is actually three different failures wearing the same costume:

  • The native WebView component isn't mounted at all
  • It's mounted, but the URL failed to load
  • It loaded fine, but the HTML body is empty or the SPA is still waiting to render

Telling these apart up front saves an hour of guessing later. The simplest trick is to wire up every relevant event and surface the state on screen.

// components/DebugWebView.tsx
import { WebView, type WebViewNavigation } from "react-native-webview";
import { View, Text, StyleSheet } from "react-native";
import { useState } from "react";
 
type Props = { uri: string };
 
export default function DebugWebView({ uri }: Props) {
  const [status, setStatus] = useState<"idle" | "loading" | "loaded" | "error">("idle");
  const [lastUrl, setLastUrl] = useState<string>("");
  const [errorText, setErrorText] = useState<string>("");
 
  return (
    <View style={styles.container}>
      {/* Dev-only status bar. Hide behind a flag for production. */}
      <Text style={styles.status}>
        status: {status} / url: {lastUrl}
        {errorText ? ` / error: ${errorText}` : ""}
      </Text>
      <WebView
        source={{ uri }}
        style={styles.webview}
        onLoadStart={(e) => {
          setStatus("loading");
          setLastUrl(e.nativeEvent.url);
        }}
        onLoad={() => setStatus("loaded")}
        onError={(e) => {
          setStatus("error");
          setErrorText(e.nativeEvent.description ?? "unknown");
        }}
        onNavigationStateChange={(nav: WebViewNavigation) => {
          setLastUrl(nav.url);
        }}
      />
    </View>
  );
}
 
const styles = StyleSheet.create({
  container: { flex: 1 },
  status: { padding: 8, backgroundColor: "#111", color: "#0f0", fontSize: 12 },
  webview: { flex: 1 },
});

Drop this in for sixty seconds and you'll immediately see whether the view is stuck on loading, bailed out with error, or reached loaded and is still empty. Everything below assumes you know which bucket you're in.

Cause 1: iOS App Transport Security is blocking HTTP

If the device is an iPhone, onError fires on iOS but the same URL works on Android, you're almost certainly being blocked by App Transport Security. Anything served over http:// is silently refused on iOS — no dialog, no crash, just nothing.

For a Rork-exported Expo project, the clean fix is either HTTPS on the other end, or an allow-list entry in app.json. I strongly prefer the allow-list: setting NSAllowsArbitraryLoads to true tends to raise questions during App Store review, and limiting the exception to one domain passes without friction.

{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSAppTransportSecurity": {
          "NSAllowsArbitraryLoads": false,
          "NSExceptionDomains": {
            "staging.example.internal": {
              "NSTemporaryExceptionAllowsInsecureHTTPLoads": true,
              "NSTemporaryExceptionMinimumTLSVersion": "TLSv1.0",
              "NSIncludesSubdomains": true
            }
          }
        }
      }
    }
  }
}

Certificate and TLS issues often show up on the API side of the app at the same time, so if you're fighting ATS it's worth sanity-checking your request layer against the Rork network and API request debugging guide.

Cause 2: Android cleartext traffic and mixed content

Android 9 (API 28) disabled cleartext HTTP by default. Same story as iOS: ideally everything is HTTPS, but the reality of internal tools and LAN IPs (http://192.168.x.x) isn't going away.

For an Expo-managed project, flip android.usesCleartextTraffic to true in app.json to get past the network layer. Then, on the WebView itself, set mixedContentMode explicitly. If you don't, an HTTPS page that references HTTP images or iframes will render, but with most of its media silently missing — which reads as a half-empty screen.

<WebView
  source={{ uri: "http://192.168.10.5:3000" }}
  mixedContentMode="compatibility" // "always" / "compatibility" / "never"
  javaScriptEnabled
  domStorageEnabled
  // Scope this to specific hosts in production builds
/>

Don't ship mixedContentMode="always" to production unless you really mean it. The cleaner pattern is an EAS profile-driven env flag that ships compatibility (or tighter) to release builds and opens things up only in dev.

Cause 3: Login loops because cookies and redirects aren't being preserved

Embedding an OAuth or SAML login in a WebView and ending up right back at the sign-in screen — or stuck on a loading spinner — usually comes down to cookies not persisting, or a redirect going to about:blank.

The minimum viable setup I reach for is:

  • Set sharedCookiesEnabled to true so iOS shares cookies with its native store
  • Set thirdPartyCookiesEnabled to true on Android (keep in mind iOS 14+ ITP-style behavior)
  • Intercept the callback URL scheme in onShouldStartLoadWithRequest and let native finish the flow
<WebView
  source={{ uri: loginStartUrl }}
  sharedCookiesEnabled
  thirdPartyCookiesEnabled
  incognito={false}
  onShouldStartLoadWithRequest={(req) => {
    if (req.url.startsWith("yourapp://callback")) {
      // Detected the custom scheme — hand the URL off to native auth
      handleAuthCallback(req.url);
      return false; // Don't let the WebView try to load it
    }
    return true;
  }}
/>

If you skip this intercept, the WebView hits a URL it can't open and goes blank. When OAuth is the last thing you remember touching and the screen is now white, this is the first place to look.

Cause 4: The page loaded, it just hasn't painted yet

When onLoad fires but the view is still blank, you're usually looking at an SPA that's waiting on something — fonts, requestIdleCallback, an API call — or a viewport issue that's collapsing the layout to zero height.

The fastest way to confirm is to inject a small probe and report back over onMessage.

<WebView
  source={{ uri }}
  onMessage={(e) => console.log("[webview]", e.nativeEvent.data)}
  injectedJavaScriptBeforeContentLoaded={`
    window.addEventListener('DOMContentLoaded', () => {
      window.ReactNativeWebView.postMessage(JSON.stringify({
        ready: document.readyState,
        bodyLength: document.body ? document.body.innerHTML.length : 0,
        title: document.title,
      }));
    });
    true; // Keeps the RN bridge happy (return value must be undefined)
  `}
/>

If bodyLength is a healthy number but the screen is still empty, you're probably looking at a CSS height bug (100vh miscomputed), a dark theme painting black text on a black background, or a font that never arrives. If the issue is specifically with missing images, that's a different rabbit hole — I've written it up separately in Rork image and media loading error fixes.

Cause 5: The Android render process died

Since 2023, Android runs the WebView renderer in a separate process. If the OS kills it under memory pressure, or the System WebView is being updated mid-session, the page goes white and doesn't come back. If you don't listen for onRenderProcessGone, your app has no idea anything happened.

The handler is short:

<WebView
  source={{ uri }}
  onRenderProcessGone={(e) => {
    console.warn("[webview] render process gone", e.nativeEvent);
    // Auto-reload, or swap to an error fallback UI
    webRef.current?.reload();
  }}
/>

This tends to hit budget Android devices the hardest, and is the source of most "the screen just freezes" complaints in app reviews. It's also one of the cheapest wins — five lines of code and a noticeable drop in bad-review rate. If broader device crashes are also a problem, it's worth pairing this with the approach in debugging Rork apps that crash on real devices.

Cause 6: "It worked in Companion, but TestFlight is blank"

Rork's Companion is generous about certain native settings during development. The surprise usually comes at TestFlight time, when the production build applies the strict configuration your release profile actually has.

The quick audit list:

  • react-native-webview is listed in app.json's plugins array
  • eas.json dev and production profiles aren't diverging on usesCleartextTraffic or infoPlist entries
  • Any ATS exception you added during development is also present in the release profile

The fastest way to confirm whether the problem is Companion-specific is eas build --profile preview --platform ios — a build that mirrors production closely but doesn't require a full TestFlight round trip.

What to do next

A blank WebView feels unfixable because it hides the error, but adding a single layer of instrumentation almost always surfaces the cause within a minute. If you're staring at one right now, drop the DebugWebView snippet above into your screen, watch how status and errorText evolve on a real device, and let that decide which of the six sections is yours.

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-02
Why StatusBar Colors Won't Apply in Rork — and How to Fix It
A practical, case-by-case guide to fixing StatusBar color and style issues in Rork apps across iOS and Android, based on real shipping experience.
Dev Tools2026-05-29
Diagnosing 'Network request failed' That Only Hits Android Emulator in Rork
Your fetch returns fine in the iOS simulator but throws 'Network request failed' the moment you switch to Android. Here is the diagnosis order I use to separate localhost, cleartext, certificate, and proxy issues, with code that actually compiles.
Dev Tools2026-05-19
Fixing 'Row too big to fit into CursorWindow' on Android When AsyncStorage Holds Too Much in Rork
When a React Native app generated with Rork stores large JSON or image metadata in AsyncStorage, Android can throw a Row too big to fit into CursorWindow exception. Here are the practical fixes — MMKV migration, chunked keys, payload trimming, and compression — explained from real wallpaper-app experience.
📚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 →