---
title: "Getting started with React"
description: "Compose Playstack auth state and error reporting around a React application using application-owned transports and recovery UI."
tags: ["frameworks","react","getting-started","auth","errors"]
---

Start with one client capability and one operational boundary. This guide supplies session state to the component tree and reports render failures without coupling the application to a particular auth server, router, or monitoring vendor.

## 1. Install the core and binding pairs

**Before you start:** use an existing React app and a working authentication API. This guide wires that API to React; it does not create a backend. For a complete first program without a server, try the [storage quickstart](/docs/getting-started#your-first-working-example). Confirm [package access](/docs/packages#access-policy) before installing.

The composition example assumes `errors` is a configured [Errors service](/docs/packages/foundation/errors), `ErrorScreen` is your recovery UI, and `initialSession` is the safe session value from your server. `readCsrfCookie` is your cookie-reading helper for the same-origin option, not a Playstack export. Choose one transport using the [Auth React guide](/docs/packages/identity/auth-react); the example API hostname is a placeholder for your own service.

```sh
npm install @playstack/auth @playstack/auth-react @playstack/errors @playstack/errors-react react
```

Keep all `@playstack/*` dependencies on the same fixed version. The React packages are bindings, so their portable core peers remain explicit application dependencies.

## 2. Configure application-owned edges

Create the error reporter with the drivers your application already uses. Create the auth transport that matches where the API lives. When the API is served from the same origin as the page, the cookie transport carries the session cookie and echoes the CSRF cookie your routes issue; when the API is a different origin, the bearer transport keeps a short-lived access token in memory and needs no CSRF header, because the API checks `Origin` and `Sec-Fetch-Site` instead:

```tsx
import {
  PlaystackAuthProvider,
  createBearerAuthTransport,
  createFetchAuthTransport,
} from '@playstack/auth-react'
import { ErrorsBoundary, ErrorsProvider } from '@playstack/errors-react'

// Same origin: cookies plus the synchronizer header your routes require.
const sameOriginTransport = createFetchAuthTransport({
  headers: () => ({ 'x-csrf-token': readCsrfCookie() }),
})

// Split origin: HTTPS (or loopback in development), no CSRF header.
const transport = createBearerAuthTransport({
  baseUrl: 'https://api.example.com',
})

export function ApplicationRoot({ children, initialSession }) {
  return (
    <ErrorsProvider errors={errors}>
      <ErrorsBoundary
        fallback={({ error, reset }) => (
          <ErrorScreen error={error} onRetry={reset} />
        )}
      >
        <PlaystackAuthProvider
          transport={transport}
          initialSession={initialSession}
        >
          {children}
        </PlaystackAuthProvider>
      </ErrorsBoundary>
    </ErrorsProvider>
  )
}
```

Either transport includes cookies but never reads an HTTP-only cookie. The application supplies the synchronizer header only for the same-origin cookie transport and may replace the endpoint paths or fetch implementation on both. After an account switch with the bearer transport, call `refresh` from `useAuth()` so the transport adopts the rotated refresh cookie.

## 3. Read state without hiding loading

```tsx
import { RequireSession, useAuth, useSession } from '@playstack/auth-react'

function AccountArea() {
  const { status, user, error } = useSession()
  const { signOut } = useAuth()

  if (status === 'loading') return <LoadingAccount />
  if (error) return <SessionProblem error={error} />

  return (
    <RequireSession fallback={<SignInPrompt />}>
      <p>Signed in as {user?.name}</p>
      <button onClick={() => signOut()}>Sign out</button>
    </RequireSession>
  )
}
```

Treat `RequireSession` as navigation UX. The API serving the protected data must independently verify the session and authorization context.

## 4. Add providers as capabilities appear

- Add [`@playstack/accounts-react`](/docs/packages/identity/accounts-react) when users can switch account context. The server still validates membership on each scoped request.
- Add [`@playstack/analytics-react`](/docs/packages/events-operations/analytics-react) after the core analytics instance has restored durable consent.
- Use `useErrors()` for event-handler and effect failures so they pass through the same scrubbed reporter as render errors.

Keep provider configuration in one application composition module. Components should consume the narrow hooks, while infrastructure clients and secrets stay outside the React tree.

## Optional application UI

[Chakra](/docs/packages/ui/chakra), [App UI](/docs/packages/ui/app-ui) and [Admin UI](/docs/packages/ui/admin-ui) add themes, controlled application compositions and the initial scoped members section. These are independent of auth/backend adoption. The host owns routes, data, mutations and authorization; Next Client Components hold callbacks and the Chakra system. See [Application interfaces](/features/application-ui).
