Skip to main content

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.

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.
Last modified on September 16, 2026