---
title: "Set up beUI Native"
description: "One-time setup for beUI Native: install Reanimated, Gesture Handler and Uniwind, configure Metro, add the theme tokens, then copy in any component."
documentation: "https://beui.dev/docs/native-setup"
markdown: "https://beui.dev/docs/native-setup.md"
---

# Set up beUI Native

> One-time setup for beUI Native: install Reanimated, Gesture Handler and Uniwind, configure Metro, add the theme tokens, then copy in any component.

beUI Native components are plain source you copy into your app. Do this setup once per app; after that, adding a component is copying its files. It works in Expo and in bare React Native.

## Requirements

| Library | Tested with |
| --- | --- |
| [Expo SDK, React Native](https://docs.expo.dev) | 57, 0.86 with React 19 |
| [Reanimated and Worklets](https://docs.swmansion.com/react-native-reanimated/) | 4.5 and 0.10 |
| [Gesture Handler](https://docs.swmansion.com/react-native-gesture-handler/) | 2.32 |
| [Uniwind with Tailwind CSS](https://docs.uniwind.dev) | 1.12 with 4.3 |

## 1. Install the libraries

```bash
npx expo install react-native-reanimated react-native-worklets react-native-gesture-handler
npm install uniwind tailwindcss
```

Expo's Babel preset already includes the Worklets plugin that Reanimated 4 needs. In a bare React Native app, add it to `babel.config.js`:

```js
module.exports = {
  presets: ["module:@react-native/babel-preset"],
  // Reanimated 4 runs animations as worklets. Keep this plugin last.
  plugins: ["react-native-worklets/plugin"],
};
```

## 2. Set up Uniwind

Create `global.css` in the project root:

```css
@import "tailwindcss";
@import "uniwind";
@import "./src/styles/theme.css";
```

Point Metro at it. `withUniwindConfig` must be the outermost wrapper, and `cssEntryFile` must be a relative path.

```js
const { getDefaultConfig } = require("expo/metro-config");
const { withUniwindConfig } = require("uniwind/metro");

const config = getDefaultConfig(__dirname);

// Uniwind must be the outermost wrapper.
module.exports = withUniwindConfig(config, {
  cssEntryFile: "./global.css",
  dtsFile: "./src/uniwind-types.d.ts",
});
```

In a bare React Native app, the default config comes from `@react-native/metro-config`:

```js
const { getDefaultConfig } = require("@react-native/metro-config");
const { withUniwindConfig } = require("uniwind/metro");

const config = getDefaultConfig(__dirname);

// Uniwind must be the outermost wrapper.
module.exports = withUniwindConfig(config, {
  cssEntryFile: "./global.css",
  dtsFile: "./src/uniwind-types.d.ts",
});
```

Uniwind writes the class name types to `dtsFile` when Metro starts. If TypeScript can't find the `global.css` import, declare CSS files in `src/env.d.ts`:

```ts
declare module "*.css";
```

## 3. Add the theme tokens

Components use semantic colors defined for light and dark mode. Save this as `src/styles/theme.css` and change the values to match your brand:

```css
/* Matches the default beUI palette in ui-components/lib/themes.ts.
   Native surface maps to card; muted maps to muted-foreground. */
@layer theme {
  :root {
    @variant light {
      --color-background: oklch(99% 0 0);
      --color-surface: oklch(97% 0 0);
      --color-foreground: oklch(15% 0 0);
      --color-muted: oklch(50% 0 0);
      --color-border: oklch(15% 0 0 / 0.06);
      --color-border-strong: oklch(15% 0 0 / 0.16);
      --color-primary: #0285f7;
      --color-on-primary: #ffffff;
      --color-destructive: #dc2626;
      --color-success: #059669;
      --color-warning: #d97706;
    }
  }

  :root {
    @variant dark {
      --color-background: #151515;
      --color-surface: #1c1c1c;
      --color-foreground: oklch(96% 0 0);
      --color-muted: oklch(62% 0 0);
      --color-border: rgb(255 255 255 / 0.05);
      --color-border-strong: rgb(255 255 255 / 0.14);
      --color-primary: #0285f7;
      --color-on-primary: #ffffff;
      --color-destructive: #f87171;
      --color-success: #34d399;
      --color-warning: #fbbf24;
    }
  }
}
```

## 4. Wrap your app

Import `global.css` from the root component, not from the file that registers the app. Wrap the app in `GestureHandlerRootView`. With Expo Router:

```tsx
import "../global.css";

import { Stack } from "expo-router";
import { GestureHandlerRootView } from "react-native-gesture-handler";

export default function RootLayout() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <Stack />
    </GestureHandlerRootView>
  );
}
```

In a bare app, do the same in `App.tsx`. For forms, also wrap the app in `KeyboardProvider` from [react-native-keyboard-controller](https://docs.expo.dev/versions/v57.0.0/sdk/keyboard-controller/).

## 5. Add a component

Run the beUI Native CLI from the app's root. It copies the component and the shared files it needs into `src/` and installs any missing libraries:

```bash
npx beui-native add tabs
```

To copy by hand instead, each component lists its libraries, its files and the shared files it needs, on its page at `https://beui.dev/react-native/{slug}` and at `https://beui.dev/native/r/{slug}`. Keep the folder layout, since components import shared files by relative path. Tabs, for example:

```text
global.css
metro.config.js
src/
  components/
    tabs/
      index.ts
      tabs.tsx
  hooks/
    use-reduced-motion.ts
  primitives/
    render-icon.tsx
  styles/
    motion.ts
    theme.css
```

```tsx
import { Text } from "react-native";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../src/components/tabs";

export default function Screen() {
  return (
    <Tabs defaultValue="overview" className="p-4">
      <TabsList>
        <TabsTrigger value="overview">Overview</TabsTrigger>
        <TabsTrigger value="activity">Activity</TabsTrigger>
      </TabsList>
      <TabsContent value="overview">
        <Text className="text-foreground">High-level summary.</Text>
      </TabsContent>
      <TabsContent value="activity">
        <Text className="text-foreground">Recent events.</Text>
      </TabsContent>
    </Tabs>
  );
}
```

Tailwind finds class names under the folder that holds `global.css`. If it lives elsewhere, like `app/`, add an `@source` for the components:

```css
@import "tailwindcss";
@import "uniwind";
@import "../src/styles/theme.css";

/* This file is in app/, so the components in src/ need an explicit source. */
@source "../src";
```

## Try before you copy

Every React Native component page (https://beui.dev/react-native) has a QR code that opens it in Expo Go (SDK 57). Agents can fetch components from https://beui.dev/native/r or the beUI MCP server. Every component follows the system Reduce Motion setting and takes a `disableAnimation` prop. Source: https://github.com/starc007/beui-native
