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:
@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:
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:
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.
| Situation | Behavior |
|---|---|
| Session is loading or refreshing | Wait; do not update the user. |
| Visitor is signed out | Keep the browser language; do not update a user. |
| Session is impersonating another user | Do not change the impersonated user's saved preference. |
| Saved locale matches the context | Do not send an update request. |
| Signed-in user's saved locale differs or is missing | Save the context locale with an optimistic update, then revalidate session queries. |
| Saving fails | Roll 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.
Public pages and localized links
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
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.