Files
2026-09-04 09:04:51 -07:00

242 lines
5.8 KiB
Plaintext

---
title: Expo Guide
description: How to set up Gui with Expo
---
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>
```bash
yarn create hanzogui@latest --template expo-router
```
There are also [pre-made community Expo starters](/community).
## Install
Use this guide to set up Gui 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>
### Native
Create a new [Expo](https://docs.expo.dev/get-started/create-a-project/#initialize-a-new-project) project:
```bash
yarn dlx create-expo-app -t expo-template-blank-typescript
```
<Notice theme="blue">
This guide assumes Expo is configured with TypeScript support.
</Notice>
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 `@hanzogui/babel-plugin`:
```bash
yarn add @hanzogui/babel-plugin
```
If you have a `hanzogui.build.ts` (recommended — see
[compiler install docs](/docs/intro/compiler-install#configuration-with-hanzoguibuildts)),
no options are needed:
Update your `babel.config.js` to include the optional `@hanzogui/babel-plugin`:
```js fileName="babel.config.js"
module.exports = function (api) {
api.cache(true)
return {
presets: ['babel-preset-expo'],
plugins: ['@hanzogui/babel-plugin'],
}
}
```
<Notice>
If you're using a monorepo you probably want to use [this Metro
configuration](/docs/guides/metro#native).
</Notice>
### Expo Router / Web
- First, follow the [Metro configuration guide](/docs/guides/metro#web-support) to enable web support.
Add `@hanzogui/config` and `hanzogui` to your `package.json` and install them. Then create a `hanzogui.config.ts`:
```tsx fileName="hanzogui.config.ts"
import { defaultConfig } from '@hanzogui/config/v5'
import { createGui } from '@hanzo/gui'
export const hanzoguiConfig = createGui(defaultConfig)
export default hanzoguiConfig
export type Conf = typeof hanzoguiConfig
declare module 'hanzogui' {
interface GuiCustomConfig extends Conf {}
}
```
Then update `app/_layout.tsx`:
```tsx showMore fileName="app/_layout.tsx"
import '../hanzogui.generated.css'
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native'
import { Stack } from 'expo-router'
import { useColorScheme } from 'react-native'
import { GuiProvider } from '@hanzo/gui'
import { hanzoguiConfig } from '../hanzogui.config'
export default function RootLayout() {
const colorScheme = useColorScheme()
return (
// add this
<GuiProvider config={hanzoguiConfig} 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>
</GuiProvider>
)
}
```
### Setup Gui
From here on out you can follow the [Installation](/docs/intro/installation) and [Configuration](/docs/core/configuration) docs.
## Loading fonts
Install the `expo-font` package:
```bash
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="hanzogui">
<InlineTabs.List>
<InlineTabs.Tab value="hanzogui">Gui</InlineTabs.Tab>
<InlineTabs.Tab value="expo">Expo Google Fonts</InlineTabs.Tab>
</InlineTabs.List>
<InlineTabs.Content value="hanzogui">
Use the `@hanzogui/font-zen` package, which binds Zen — the Hanzo typeface — to
the Gui font tokens. `@hanzo/font` ships the files themselves:
Import the `useFonts` hook and load the fonts:
```tsx fileName="App.tsx"
import { useFonts } from 'expo-font'
function App() {
const [loaded] = useFonts({
Zen: require('@hanzo/font/dist/fonts/zen-sans/Zen-Medium.ttf'),
ZenBold: require('@hanzo/font/dist/fonts/zen-sans/Zen-Bold.ttf'),
})
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:
<Notice theme="green">
You can find the [full list of
fonts](https://github.com/expo/google-fonts/tree/master/font-packages) and usage
instructions in the [Expo documentation](https://github.com/expo/google-fonts).
</Notice>
Install the font package:
```bash
npx expo install @expo-google-fonts/roboto
```
Import the `useFonts` hook and load the fonts:
```tsx fileName="App.tsx"
import { useFonts, Roboto_400Regular, Roboto_900Black } from '@expo-google-fonts/roboto'
function App() {
const [loaded] = useFonts({
Roboto_400Regular,
Roboto_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>
## First time starting Expo
The first time running your project with Gui, be sure to clear the cache:
```bash
npx expo start -c
```
Your `package.json` scripts should look something like this:
```json fileName="package.json"
{
"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"
}
}
```