code/tamagui.dev/data/docs/guides/expo.mdx
We've created a new template repo for starting an Expo Router app based on the Expo starter repo.
<Notice theme="blue"> This template requires Yarn 4.4.0 or greater. You can set yarn to the latest version by running `yarn set version stable`. </Notice>yarn create tamagui@latest --template expo-router
There are also pre-made community Expo starters.
Use this guide to set up Tamagui with Expo Native and Web.
<Notice theme="blue"> To support dark mode, update your `app.json` to `app.config.ts` and set `userInterfaceStyle` to `"automatic"`. </Notice>Create a new Expo project:
yarn dlx create-expo-app -t expo-template-blank-typescript
The following steps are optional but useful for many apps. They enable the optimizing compiler, Reanimated, and support for process.env.XYZ environment variables.
Add @tamagui/babel-plugin:
yarn add @tamagui/babel-plugin
If you have a tamagui.build.ts (recommended — see
compiler install docs),
no options are needed:
Update your babel.config.js to include the optional @tamagui/babel-plugin:
module.exports = function (api) {
api.cache(true)
return {
presets: ['babel-preset-expo'],
plugins: [
'@tamagui/babel-plugin',
],
}
}
Add @tamagui/config and tamagui to your package.json and install them. Then create a tamagui.config.ts:
import { defaultConfig } from '@tamagui/config/v5'
import { createTamagui } from 'tamagui'
export const tamaguiConfig = createTamagui(defaultConfig)
export default tamaguiConfig
export type Conf = typeof tamaguiConfig
declare module 'tamagui' {
interface TamaguiCustomConfig extends Conf {}
}
Then update app/_layout.tsx:
import '../tamagui.generated.css'
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native'
import { Stack } from 'expo-router'
import { useColorScheme } from 'react-native'
import { TamaguiProvider } from 'tamagui'
import { tamaguiConfig } from '../tamagui.config'
export default function RootLayout() {
const colorScheme = useColorScheme()
return (
// add this
<TamaguiProvider config={tamaguiConfig} defaultTheme={colorScheme!}>
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="modal" options={{ presentation: 'modal' }} />
</Stack>
</ThemeProvider>
</TamaguiProvider>
)
}
From here on out you can follow the Installation and Configuration docs.
Install the expo-font package:
npx expo install expo-font
Load your fonts so React Native can recognize them. There are several ways to do this:
<Spacer size="$6" /> <InlineTabs id="font" defaultValue="tamagui"> <InlineTabs.List> <InlineTabs.Tab value="tamagui">Tamagui</InlineTabs.Tab> <InlineTabs.Tab value="expo">Expo Google Fonts</InlineTabs.Tab> </InlineTabs.List><InlineTabs.Content value="tamagui">
Use the @tamagui/font-inter package, a pre-configured version of the Inter font that works with Tamagui:
Import the useFonts hook and load the fonts:
import { useFonts } from 'expo-font'
function App() {
const [loaded] = useFonts({
Inter: require('@tamagui/font-inter/otf/Inter-Medium.otf'),
InterBold: require('@tamagui/font-inter/otf/Inter-Bold.otf'),
})
useEffect(() => {
if (loaded) {
// can hide splash screen here
}
}, [loaded])
if (!loaded) {
return null
}
return <MyApp />
}
</InlineTabs.Content>
<InlineTabs.Content value="expo">
Use the @expo-google-fonts package, a collection of Google Fonts that work with Expo:
Install the font package:
npx expo install @expo-google-fonts/inter
Import the useFonts hook and load the fonts:
import { useFonts, Inter_400Regular, Inter_900Black } from '@expo-google-fonts/inter'
function App() {
const [loaded] = useFonts({
Inter_400Regular,
Inter_900Black,
})
useEffect(() => {
if (loaded) {
// can hide splash screen here
}
}, [loaded])
if (!loaded) {
return null
}
return <MyApp />
}
</InlineTabs.Content> </InlineTabs>
<Notice> For more information on loading fonts in Expo, see the [Expo documentation](https://docs.expo.dev/develop/user-interface/fonts/). </Notice>The first time running your project with Tamagui, be sure to clear the cache:
npx expo start -c
Your package.json scripts should look something like this:
{
"scripts": {
"start-native": "expo start -c",
"start-web": "expo start -c",
"android": "yarn expo run:android",
"ios": "yarn expo run:ios",
"web": "expo start --web"
}
}