Skip to content

Frontend · Reference

React components and CSS

Install the provider, forms, account controls, access guards, and Tailwind source required by the component package.

The package exports pre-wired Better Auth components while leaving layout and application navigation under your control.

Tailwind CSS setup

Import the package source in your global CSS so Tailwind can detect classes used in the compiled package:

css
@import "tailwindcss";
@import "@krak-stack/auth/tailwind.css";

The components use shadcn design tokens such as --background, --foreground, --primary, --border, and --radius. Define those variables in :root and .dark, normally through your existing shadcn theme.

Provider

Wrap component consumers once near the application root:

tsx
import { KrakstackAuthProvider } from "@krak-stack/auth/components";
import { KrakstackProvider } from "@krak-stack/registry/krakstack-provider";
import { getLocale, locales } from "@/paraglide/runtime";

<KrakstackProvider locale={getLocale()} locales={locales}>
  <KrakstackAuthProvider
    projectId={import.meta.env.VITE_KRAKSTACK_AUTH_PROJECT_ID}
  >
    {children}
  </KrakstackAuthProvider>
</KrakstackProvider>;

Pass baseUrl when the default same-origin endpoint is not appropriate. The provider and components use the owned Effect HttpApi client internally; they do not accept a Better Auth client.

Locale syncing

KrakstackAuthProvider reads the interface language from its enclosing KrakstackProvider. It does not accept a locale prop. The context language is authoritative: the provider saves it to the signed-in user's locale for emails and other asynchronous communications. It does not restore the interface language from the saved account preference on sign-in.

Use the language selector directly from the registry. It only changes the interface language; account persistence belongs to the auth provider, not a custom selector wrapper:

tsx
import { LocaleSwitcher } from "@krak-stack/registry/locale-switcher";
import { setLocale } from "@/paraglide/runtime";

<LocaleSwitcher
  onLocaleChange={(locale) => setLocale(locale === "fr" ? "fr" : "en")}
/>;

The flow is LocaleSwitcher → Paraglide → KrakstackProvider → KrakstackAuthProvider → user.locale. With Paraglide's default reload behavior, the new page supplies the updated context locale and synchronization runs after its session loads. If your application changes language without a reload, it must rerender KrakstackProvider with the new locale value.

SituationBehavior
Session is loading or refreshingWait; do not update the user.
Visitor is signed outKeep the browser language; do not update a user.
Session is impersonating another userDo not change the impersonated user's saved preference.
Saved locale matches the contextDo not send an update request.
Signed-in user's saved locale differs or is missingSave the context locale with an optimistic update, then revalidate session queries.
Saving failsRoll back optimistic state, log the failure, and call onLocaleSyncError if provided. Do not continuously retry the same user/locale pair.

Use the optional onLocaleSyncError callback on KrakstackAuthProvider to show a localized, application-owned error notice. The callback receives the failure cause; changing its reference does not retry a failed save.

Place KrakstackProvider around the whole site and KrakstackAuthProvider only around the routes that should sync account language. A selector on a public page outside the auth provider changes only the browser locale, even if the visitor has a session. Entering a provider-wrapped route later syncs that current locale to the account.

Synchronization follows context, not explicit selector clicks. Opening a localized URL inside the auth provider can therefore update the saved preference. Opening a localized public page outside it does not. If you wrap the entire site in the auth provider, public pages will sync too.

Signup and recipient communications

New accounts initialize their language from the validated signup flow, falling back to English. Existing accounts without a previously recorded preference default to English after migration. English (en) and French (fr) are currently supported; the database locale column has no language constraint, while API writes validate supported values.

Krakstack Auth's email senders prefer the recipient's saved locale. If no valid saved preference exists, they use the request locale when available, otherwise English. This works without a browser request for known recipients. For application-owned background notifications, resolve the recipient's saved language too—not the initiating administrator's or worker's locale. Delivery channels do not need a separate language preference.

Account controls

tsx
import {
  OrganizationSwitcher,
  UserButton,
} from "@krak-stack/auth/components";

<OrganizationSwitcher side="bottom" />
<UserButton signOutRedirect="/" side="bottom" />

OrganizationSwitcher supports custom menu actions for links into your application's workspace settings. UserButton provides account actions and sign-out behavior. Its profile editor also manages localized public contact emails, phone numbers, websites, and social profiles; these values are separate from the email used to sign in and are available to trusted server API clients.

Forms

The package exports Signin, VerifyEmail, ForgotPassword, ResetPassword, and TwoFactor. ResetPassword renders the email request step without a token and the new-password step with one; ForgotPassword remains available when only the email step is needed. Render forms in application-owned routes so URLs, page chrome, and error boundaries remain under your control.

Authorization guard

MemberRequired gates UI on organization membership. Treat it as a presentation guard, not the only authorization layer. Every protected backend endpoint must independently validate the session, organization, and role.

Hooks, atoms, and contract

Import useKrakstackAuth, useKrakstackAuthProjectConfig, and usePermissions from @krak-stack/auth/components inside the provider. For direct Effect state access, use authSessionAtom, authOrganizationsAtom, and activeAuthOrganizationAtom from the same subpath with @effect/atom-react. Use the @krak-stack/auth/auth HttpApi contract when a custom Effect client is required.