Skip to content
chornous.dev

Type two or more letters. Esc closes.

Index of sheets
Theme

Sheet 03 · Writing

All notes

React Native on Meta Quest: Expo Go on the headset, one config plugin, no Google services

Meta and Callstack published the setup for React Native on Meta Quest on February 24, 2026. Horizon OS is Android without Google Mobile Services, Expo Go runs on the headset, and the expo-horizon-core plugin adds a Quest build flavor next to your phone build.

Pl. 22 · device drawing generated from the slug “react-native-meta-quest-platform-expansion”

Meta announced official React Native support for Meta Quest at React Conf 2025. On February 24, 2026, the React Native blog published the setup guide, written by Łukasz Chludziński and Jan Jaworski from Callstack with Markus Leyendecker, a product manager at Meta. Quest joins Android, iOS, Apple TV, Windows, macOS and the web on the list of React Native targets.

The guide adds no new runtime and no new programming model. Quest runs Meta Horizon OS, which builds on the Android Open Source Project, so your Android toolchain, Gradle builds and debugger work with small changes.

The fastest path: Expo Go on the headset

Expo Go is on the Meta Horizon Store. Install it on the Quest, then start a normal Expo project:

npx create-expo-app@latest my-quest-app
cd my-quest-app
npx expo start

Open Expo Go on the headset and scan the QR code with the headset camera. Your app opens in a window in your room, with live reload. You need no special template.

Expo Go covers UI work. Native modules need a development build, which follows the standard Expo workflow and installs on the headset.

Config: one plugin, two build flavors

The expo-horizon-core config plugin applies Quest requirements at build time. It adds product flavors, so the same repo produces a phone build and a Quest build:

{
  "expo": {
    "orientation": "default",
    "plugins": [
      [
        "expo-horizon-core",
        {
          "horizonAppId": "your-horizon-app-id",
          "defaultWidth": "1024dp",
          "defaultHeight": "640dp",
          "supportedDevices": "quest2|quest3|quest3s"
        }
      ]
    ]
  }
}
{
  "scripts": {
    "android": "expo run:android --variant mobileDebug",
    "quest": "expo run:android --variant questDebug",
    "quest:release": "expo run:android --variant questRelease"
  }
}

defaultWidth and defaultHeight set the starting size of your app's panel. Without Expo, you make the same edits by hand: a Quest flavor in android/app/build.gradle, the app ID, the panel size in the manifest, the device list, a raised minimum SDK and the removal of permissions Horizon OS forbids. The guide suggests reading the plugin's source as the checklist.

At runtime you branch on the build or the device:

import ExpoHorizon from "expo-horizon-core";

if (ExpoHorizon.isHorizonDevice) {
  // larger targets, hover states, no SMS
}

What breaks: Google services and phone hardware

Horizon OS ships without Google Mobile Services. No Play Services, no Play Store integrations. Cellular features such as SMS, sensors such as GPS and a set of restricted permissions don't exist on the headset.

Library compatibility on Horizon OS, per the guide
Library typeStatus
Pure JS, or standard React Native and Android APIsWorks unchanged
Assumes touch-only input or phone hardwareNeeds adaptation or a conditional import
Depends on Google Mobile ServicesNeeds a replacement
Needs a restricted permissionNot supported

Expo offers Horizon drop-ins for location and notifications in the expo-horizon repo from Software Mansion Labs. Firebase Cloud Messaging, Google Sign-In and Play Billing are the usual suspects in a phone app's package.json. Audit those before you promise anyone a Quest release.

Design for a pointer you can't see

Quest users drive apps with controllers, hand tracking, and sometimes a mouse and keyboard. Controllers act like pointers, so hover and focus states carry the interface. A button that only reacts to press gives no feedback until the click lands.

People also read a Quest panel from a distance. The guide asks for larger hit targets, more spacing and type that stays readable as the panel moves away. It gives no numbers, and Meta's Horizon design requirements page holds the specifics.

Much of this work pays off elsewhere. Tablets, foldables and desktop windows reward the same resizable layouts and focus handling.

<Pressable
  onHoverIn={() => setFocused(true)}
  onHoverOut={() => setFocused(false)}
  style={[styles.card, focused && styles.cardFocused]}
>
  <Text>{title}</Text>
</Pressable>

What the guide leaves out

The post gives no performance budget, no store submission walkthrough and no hand-tracking API. It mentions store eligibility requirements without listing them. For working code, Callstack publishes expo-meta-horizon-os-demo, which matches the article's setup, and the react-native-horizonos-example app it showed at React Conf.

This week

  1. Install Expo Go on a Quest and run your existing app in it. Note which screens break before you write any Quest code.
  2. Grep package.json for Google Play Services, Firebase Messaging and SMS libraries. That list sizes the port.
  3. Add hover and focus styles to your shared button and card components. Tablet and desktop users benefit too.
  4. Add expo-horizon-core on a branch and confirm the questDebug flavor builds in CI next to your phone build.

Volodymyr Chornous