# Getting started

URL: https://developers.uidu.org/docs/tools/react/getting-started

> React provider and conventions for using @uidu/client in React applications.

`@uidu/react` is a thin React layer over [`@uidu/client`](https://developers.uidu.org/docs/paths/public-website.md). It exposes a provider so Client Components can reach the client, a small set of pure-transform hooks for normalizing CMS data, and components for rendering dynamic CMS pages.

<Callout type="info" title="Server-first by default">
  Most uidu data fetching happens in **Server Components** using `@uidu/client` directly — no provider needed. Reach for `@uidu/react` only when you need interactivity on the client (form submission, search-as-you-type, etc.) or want the prebuilt renderers.
</Callout>

## What's inside

| Area                                       | Exports                                   |
| ------------------------------------------ | ----------------------------------------- |
| [Provider](#provider)                      | `UiduProvider`                            |
| [Hooks](https://developers.uidu.org/docs/tools/react/hooks.md)           | `useUiduClient`, `useUidu`, `useFields`   |
| [Components](https://developers.uidu.org/docs/tools/react/components.md) | `PageBlocks`, `BlockRenderer`, `RichText` |
| Utilities                                  | `toText`, `getBlockShortname`             |

## Install

```bash
npm install @uidu/react @uidu/client
```

`@uidu/client` is a peer-style runtime dependency — install both.

## Provider

`UiduProvider` is the only piece of `@uidu/react` that needs to be wired into your app. Wrap any subtree that contains Client Components needing access to the uidu client.

```tsx
// app/layout.tsx
import { UiduProvider } from '@uidu/react';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <UiduProvider
          workspace={process.env.NEXT_PUBLIC_UIDU_WORKSPACE!}
          publicToken={process.env.NEXT_PUBLIC_UIDU_PUBLIC_TOKEN!}
        >
          {children}
        </UiduProvider>
      </body>
    </html>
  );
}
```

`UiduProvider` accepts the same options as [`createClient`](https://developers.uidu.org/docs/paths/public-website.md#create-a-client), minus `apiKey` (mutations should go through Server Actions, not the browser client). You can also pass an existing client instance:

```tsx
import { createClient } from '@uidu/client';
import { UiduProvider } from '@uidu/react';

const client = createClient({ workspace: 'my-org', publicToken: 'pk_...' });

<UiduProvider client={client}>{children}</UiduProvider>
```

The provider also wires SWR with a fetcher bound to the client, so [`useQuery`](https://developers.uidu.org/docs/tools/react/hooks.md#usequerydocument-variables-options) and any SWR hook of your own use the same client and cache.

## Two clients, by design

Most uidu apps end up with **two client instances**:

1. **Server client** — created in `lib/uidu.ts` with `createClient()` including the API key. Used in Server Components for data fetching and from Server Actions for mutations.
2. **Browser client** — created inside `UiduProvider` from the `workspace` + `publicToken` props. Reachable from Client Components via [`useUiduClient`](https://developers.uidu.org/docs/tools/react/hooks.md#useuiduclient). Never has the API key.

Don't try to share a single client between server and browser — the API key would leak.

## What's next

* [Hooks](https://developers.uidu.org/docs/tools/react/hooks.md) — `useUiduClient`, `useFields`, and friends
* [Components](https://developers.uidu.org/docs/tools/react/components.md) — `PageBlocks`, `BlockRenderer`, `RichText`
* [Demo app](https://developers.uidu.org/docs/recipes/demo-app.md) — a Next.js project exercising everything in one place
