> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trylath.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Every Lath operation is POST https://platform.trylath.com/<operation name with dots replaced by slashes>, with a JSON body and `Authorization: Bearer <key>`. `email.send` is POST /email/send.
> Branch on `error.code`, never on `error.message`. Every refusal also carries `error.fix`, which names the next step.
> Send an `Idempotency-Key` header on any operation that is not retry-safe, so a retry cannot run it twice.
> A `lath_test_` key emails only the account's own members and sends no SMS; a `lath_live_` key reaches real recipients and is billed.
> The OpenAPI document, generated from the same registry as the routes, is at https://platform.trylath.com/openapi.json.

# React and React Native

> Sign-in, profile and organization components that wear the theme you published, on two packages over one headless engine. What they do for you, and — stated as plainly — what they leave to you.

## Two packages, one engine

`@trylath/react` and `@trylath/react-native` both sit on `@trylath/auth-ui`, which is the sign-in state machine with no user interface at all. If you want the flow and none of the markup, that is the package to take.

Both component packages export the same set: `LathProvider`, `SignIn`, `SignUp`, `Profile`, `MfaEnrol`, `RecoveryCodes`, `OrganizationSwitcher`, `OrganizationSettings`, `UserButton`, `SignedIn` and `SignedOut`, and one hook, `useLath`. Web adds `browserWebAuthn` and `lathCss`; React Native adds `rnTokens` instead.

There is one hook, deliberately, not a family of them. `useLath` is the client the components themselves use.

## The provider holds the key, and only the provider

`LathProvider` needs two things: a **publishable** key and an environment id. Everything else — the base URL, storage, a `fetch`, a redirect — is optional.

The key is a prop and nothing else. These packages read no environment variables at all: names like `NEXT_PUBLIC_LATH_KEY` appear in the examples because they are *your* variable, not one the package knows to look for. Nothing is picked up implicitly, which is the behaviour you want from the thing holding your credential.

A publishable key is the right key here — it carries only the public sign-in permission, so shipping it to a browser is the intended use rather than a compromise. Session state is kept under a key named for the environment, so two environments on one origin do not collide.

```tsx theme={null}
import { LathProvider, SignIn } from "@trylath/react";

export default function App() {
  return (
    <LathProvider publishableKey={process.env.NEXT_PUBLIC_LATH_KEY!} environmentId={process.env.NEXT_PUBLIC_LATH_ENV!}>
      <SignIn />
    </LathProvider>
  );
}
```

## SignIn takes nothing, and takes six things

Every prop on `SignIn` is optional: it reads your published sign-in settings and offers what is both enabled and available, so the default is the sign-in page you already configured.

Narrow it with `methods` when one surface should offer fewer ways in than the environment allows — the five are email\_code, email\_link, sms\_code, password and passkey. `mode` switches the same component between signing in and signing up. `header` and `footer` take your own nodes, `onSignedIn` hands you the session, and styling is `className` on web or `style` on React Native.

A method you name that the environment has switched off is not shown. The settings are the authority; the prop only ever subtracts.

## They wear the theme you published

On mount the client fetches the environment's published theme from the same public endpoint the hosted pages read — no key required, because a sign-in screen is read by people who have not signed in yet.

On the web the tokens become CSS custom properties and the stylesheet reads only those, so overriding one colour is a one-line override rather than a fight with specificity. On React Native the same token names are mapped to style values, since there are no custom properties to set.

This is the same theme as your hosted pages and your email: publish once, and the component, the hosted page and the mail agree. Drafts do not appear here — the components read what is published.

## What React Native leaves to you, on purpose

**Storage is a required prop, and the package bundles none.** That is deliberate rather than unfinished: where a session token rests is a decision about your app's security, and a default would make it quietly. A secure store is the usual answer; the package will not choose one for you.

**Passkeys need an implementation you supply.** On the web they work out of the box through the browser. On React Native the option hides itself unless you pass one, so the sign-in screen never offers a method that cannot complete.

**There is no biometric unlock, and no navigation.** The components never push a screen or take a back gesture — your navigator owns both. A component library that moved you between screens would be fighting the one part of a mobile app that is most yours.

The web package does one thing its mobile twin cannot: it keeps tabs in step, so signing out in one signs out the rest.

## What proves this works

Both packages have render tests against a real API in-process, not mocks: a themed form appears, a wrong code is reported inline with the attempts left, the right one signs in, the session survives a remount, and signing out revokes it on the server rather than only forgetting it locally.

The React Native test also asserts the announcement a screen reader receives, which is the part of a sign-in screen most likely to be broken and least likely to be noticed.
