wwwwwwwwwwwwwwwwwww

Expo Guide

How to set up Tamagui with Expo

We've created a new template repo for starting an Expo Router based app based on the Expo 3 starter repo.

npm create tamagui@latest --template expo-router

There are also pre-made community Expo starters.

Install

To support dark mode, update your app.json to app.config.ts and set userInterfaceStyle to "automatic".

Expo Router / Web

We have beta support via @tamagui/metro-plugin. Install:

yarn add @tamagui/metro-plugin

Then adjust your metro.config.js:

// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require('expo/metro-config')
/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname, {
// [Web-only]: Enables CSS support in Metro.
isCSSEnabled: true,
})
const { withTamagui } = require('@tamagui/metro-plugin')
module.exports = withTamagui(config, {
components: ['tamagui'],
config: './tamagui.config.ts',
outputCSS: './tamagui.css',
})

Add your tamagui.config.ts:

import { config as configBase } from '@tamagui/config'
import { createTamagui } from 'tamagui'
export const config = createTamagui(configBase)
export default config
export type Conf = typeof config
declare module 'tamagui' {
interface TamaguiCustomConfig extends Conf {}
}

Then update app/_layout.tsx:

import '../tamagui.css'
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native'
import { Stack } from 'expo-router'
import { useColorScheme } from 'react-native'
import { TamaguiProvider } from 'tamagui'
import { config } from '../tamagui.config'
export default function RootLayout() {
const colorScheme = useColorScheme()
return (
// add this
<TamaguiProvider config={config} 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>
)
}

Native

This guide assumes Expo is configured with TypeScript support.

npx create-expo-app -t expo-template-blank-typescript

The following steps are optional but useful for many apps, they enable the optimizing compiler, reanimated, as well as using process.env.XYZ for environment variables.

yarn add @tamagui/babel-plugin

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",
{
components: ["tamagui"],
config: "./tamagui.config.ts",
logTimings: true,
disableExtraction: process.env.NODE_ENV === 'development'
},
],
// NOTE: this is only necessary if you are using reanimated for animations
"react-native-reanimated/plugin",
],
};
}

If you're using a monorepo you probably want to use this Metro configuration:

// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require('expo/metro-config');
/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname, {
// [Web-only]: Enables CSS support in Metro.
isCSSEnabled: true,
});
// Expo 49 issue: default metro config needs to include "mjs"
// https://github.com/expo/expo/issues/23180
config.resolver.sourceExts.push('mjs');
module.exports = config;

Setup Tamagui

From here on out you can follow the Installation and Configuration docs.

Loading fonts

You need to load your fonts for React Native to recognize them. Typically this looks something like if using Expo, (or you can follow a React Native guide here ):

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 />
}

First time starting Expo

The first time running your project with Tamagui, be sure to clear the cache:

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"
}
}

Previous

Next.js

Next

Vite