React Native in the browser
How the phone-frame demo on the homepage works — a real React Native app compiled to web and embedded in an iframe.
Summary
The homepage embeds a real @daltonr/pathwrite-react-native app running inside a CSS phone frame. It is not a mockup or a separate web implementation — it is the same React Native source code that runs on iOS and Android, compiled to a browser-compatible bundle using Expo Web and react-native-web.
How Expo Web works
react-native-web provides browser equivalents for every core React Native primitive:
View→<div>Text→<span>Pressable→<div role="button">ScrollView,KeyboardAvoidingView,StyleSheet,Platform— all shimmed
When Expo bundles for web it aliases react-native → react-native-web, so the app and every library it imports (including @daltonr/pathwrite-react-native) transparently pick up the web implementations with no code changes.
Building the web bundle
From the showcase app directory:
npx expo export --platform web
This produces a static dist/ folder — an index.html and a single JS bundle. Because the app is served from a subdirectory on this site, the baseUrl must be set so asset paths resolve correctly:
// app.json
{
"expo": {
"experiments": {
"baseUrl": "/apps/react-native-demos/demo-rn-showcase/dist"
}
}
}
Without this, Expo emits absolute paths like /_expo/static/js/web/index.js which resolve to the site root instead of the subdirectory.
Embedding in the page
The static bundle is served as a standalone page and embedded in an <iframe> inside a CSS phone frame:
<div class="phone-frame">
<div class="phone-frame__screen">
<iframe src="apps/react-native-demos/demo-rn-showcase/dist/"
title="React Native showcase"></iframe>
</div>
</div>
The phone shape is pure CSS — rounded corners, a dark bezel, a notch bar, and a box-shadow stack to give depth. No images or icon fonts required.
The Pathwrite adapter
The showcase uses @daltonr/pathwrite-react-native exactly as it would on a real device. PathShell renders its step content inside a ScrollView with KeyboardAvoidingView, and the stepper and navigation buttons use View, Text, and Pressable. All of that maps to DOM elements via react-native-web at build time — the adapter itself has no web-specific code.
import { PathShell } from "@daltonr/pathwrite-react-native";
export default function App() {
return (
<PathShell
path={myPath}
initialData={INITIAL_DATA}
onComplete={handleComplete}
steps={{ welcome: <WelcomeStep />, ... }}
/>
);
}
Limitations
- Visual fidelity: react-native-web renders to DOM, so it looks slightly different from a native app — fonts, shadows, and touch feedback are browser equivalents, not platform-native.
- Native modules: any library that requires a native module (e.g. camera, biometrics) will not work on web. The Pathwrite adapter has no native dependencies, so this is not an issue here.
- Bundle size: react-native-web ships the full RN primitives layer, so the bundle is larger than a typical web app (~445 kB in this case).