How to build TV apps with Expo and React Native

Product5 minutes read

Doug Lowder

Doug Lowder

Engineering

In this article you will learn how to build a TV app with Expo modules starting with the Ignite CLI.

How to build TV apps with Expo SDK 50

As a part of SDK 50, we are (for the first time) introducing the ability to build applications for Apple TV and Android TV that include Expo modules.

To illustrate the kinds of apps that are being built for TV platforms, here are some examples (including a few built with React Native) that can be found today on the Apple App Store and Google Play Store.

Support for TV in React Native itself already exists and some developers have already shipped applications for both Apple TV and Android TV using the React Native for TV package; however, until recently, developers could not include Expo SDK modules in their TV applications. As of SDK 50 we have now removed that limitation, and TV developers can use many of the same Expo SDK features that are available to mobile developers.

You can start developing TV apps with Expo with our guide. It shows how to create a bare-bones Expo app and configure it for TV development, and it lists the Expo SDK features that are supported on TV.

In this article we're going to demonstrate something a little different. We want to show a more sophisticated example of how to build a TV app starting with the Ignite CLI.

ℹ️ Note: At this time, TV applications cannot be built with expo-router or expo-dev-client.

Let’s build a TV app

We’re going to get started with Ignite CLI. The default project created by Ignite is a good test of TV support, since it includes many commonly used libraries: react-navigation, react-native-reanimated, MobX state tree libraries, async storage, FlashList, etc. We think it’s a great example to get started with.

Code
npx ignite-cli@9.5.0 new IgniteTV --workflow=prebuild --yes

This will create a new Expo SDK 50 app called IgniteTV, set up to use Expo prebuild.

Now, we need to make some changes to make it possible to build this app for TV:

  • Replace the react-native dependency with the React Native for TV package. This is a full fork of the core React Native package, and provides support for both mobile (Android and iOS) and TV (Android TV and Apple TV) targets: yarn add react-native@npm:react-native-tvos@0.73.2-0
  • Since TV does not support it, remove the expo-dev-client dependency: yarn remove expo-dev-client
  • Add a dev dependency on the TV config plugin. This automatically takes certain native files (Android manifest, splash screen, Xcode project) and makes small changes that are required for your app to build correctly for TV: yarn add --dev @react-native-tvos/config-tv
  • The plugin also needs to be added to app.json in the plugins list.
  • Since we are not using the react-native package that Expo CLI expects, we modify package.json to exclude it from the automatic checks made by the npx expo install command.
Code
diff --git a/app.json b/app.json
index 0e0efde..df7a49d 100644
--- a/app.json
+++ b/app.json
@@ -54,6 +54,8 @@
"bundler": "metro"
},
"plugins": [
+ "@react-native-tvos/config-tv",
+ "expo-font",
"expo-localization",
[
"expo-build-properties",
@@ -66,8 +68,7 @@
"newArchEnabled": false
}
}
- ],
- "expo-font"
+ ]
],
"experiments": {
"tsconfigPaths": true
diff --git a/package.json b/package.json
index b0fafc2..7c96374 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,6 @@
"expo": "^50.0.0",
"expo-application": "~5.8.3",
"expo-build-properties": "~0.11.0",
- "expo-dev-client": "~3.3.6",
"expo-font": "~11.10.2",
"expo-linking": "~6.2.2",
"expo-localization": "~14.8.3",
@@ -55,7 +54,7 @@
"mobx-state-tree": "5.3.0",
"react": "18.2.0",
"react-dom": "18.2.0",
- "react-native": "0.73.4",
+ "react-native": "npm:react-native-tvos@^0.73.4-0",
"react-native-drawer-layout": "4.0.0-alpha.1",
"react-native-gesture-handler": "~2.14.0",
"react-native-reanimated": "~3.6.0",
@@ -73,6 +72,7 @@
"@babel/plugin-transform-template-literals": "^7.0.0",
"@babel/preset-env": "^7.20.0",
"@babel/runtime": "^7.20.0",
+ "@react-native-tvos/config-tv": "^0.0.5",
"@types/i18n-js": "3.8.2",
"@types/jest": "^29.2.1",
"@types/react": "~18.2.14",
@@ -103,6 +103,13 @@
"ts-node": "^10.9.2",
"typescript": "5.3.2"
},
+ "expo": {
+ "install": {
+ "exclude": [
+ "react-native"
+ ]
+ }
+ },
"engines": {
"node": ">=18"
},

Now, we are ready to build and run the app locally. Set the EXPO_TV environment variable, and run a clean prebuild. The config plugin will modify the generated native files to build for Apple TV or Android TV, and the app will run with a local development server on a TV simulator instead of a mobile device simulator:

Code
export EXPO_TV=1
npx expo prebuild --clean
yarn ios

This is a good example of the power of continuous native generation! We are not attempting to maintain complex native code, but instead regenerating that code for different target platforms as needed, in this case: mobile and TV platforms. Only your application JavaScript or TypeScript code, and your configuration files, need to be maintained in your source repository.

The above screenshot is from our IgniteTV example repo, where we have taken this starter TV project, and gone further, adding:

  • TV-specific focus APIs, to highlight controls when the user navigates the screen using a remote control
  • Scaling of component sizes for TV
  • Better TV layout with a top bar navigation component

You can try this out as a reference, or as inspiration for your TV project.

What’s next for Expo TV apps?

While we’re thrilled to see people building TV apps with Expo today or just demonstrating interest in the idea of building TV apps with Expo:

But we know there are some important capabilities we need to add. We are considering some or all of the following features and guides for possible inclusion in a future SDK version:

  • Support for Expo Router
  • Support for expo-dev-client
  • Migration guide for existing React Native TV apps not built with Expo
  • Support for additional Expo modules
  • Support for some other 3rd party React Native libraries not mentioned above

TV app feedback

If you are building a TV app, we’d like to hear more about your experience! Send us a note on social or in our Discord to connect. And please take a look at the livestream in which we demo'd "how to build a tv app from scratch" and "how to build a tv app with IgniteTV":

How to build TV apps with Expo SDK 50
SDK 50
tv apps

Get there faster with Expo Application Services

Learn more