Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@suaveplan/react-auth - React authentication core: Better-Auth client wrapper, AuthProvider context, AuthGuard, useAuthGuard/usePermission hooks, locale packs.
React authentication core for Suaveplan apps — a typed wrapper around better-auth/client, an AuthProvider React context, an AuthGuard route component, useAuthGuard and usePermission hooks, a betterAuthAdapter response bridge, OTel instruments, a REACT_AUTH_CODES error registry, and shipped translation packs for en-GB, cy-GB, and zh-CN. Wave 1 (this package) ships the foundational core that downstream packages (the parallel react-auth-whitelabel, and consumer apps) build on; form components (Wave 2) and page components (Wave 3) layer on top without changing this surface.
Documentation tree
- client —
auth-client.tsships a typedAuthClientclass plus thecreateAuthClient(config)factory that wraps `better-auth/c…- auth-client —
auth-client.tsships a typedAuthClientclass plus thecreateAuthClient(config)factory that wraps `better-auth/c…
- auth-client —
- components — Internal test helper consumed only by the Wave 2 form
.test.tsxfiles insrc/components/<form>/. The helper wraps a…- auth-guard —
<AuthGuard>is the declarative route gate. It reads the current auth state from the surroundingAuthProvider, evalu…- auth-guard —
<AuthGuard>is the declarative route gate. It reads the current auth state from the surroundingAuthProvider, evalu…
- auth-guard —
- auth-provider —
auth-provider.tsxis a thin back-compatibility re-export shim that forwardsAuthContext,AuthProvider,useAuth,…- auth-provider —
auth-provider.tsxis a thin back-compatibility re-export shim that forwardsAuthContext,AuthProvider,useAuth,…
- auth-provider —
- email-verification-view —
<EmailVerificationView>is the pure-UI surface that renders the four states of an email-verification flow — `verifyin…- email-verification-view —
<EmailVerificationView>is the pure-UI surface that renders the four states of an email-verification flow — `verifyin…
- email-verification-view —
- forgot-password-form —
<ForgotPasswordForm>is the pure-UI surface for requesting a password-reset email. It owns the email input, the Zod v…- forgot-password-form —
<ForgotPasswordForm>is the pure-UI surface for requesting a password-reset email. It owns the email input, the Zod v…
- forgot-password-form —
- login-form —
<LoginForm>is a pure-UI sign-in form used by the Wave 3<Login>page (and any custom consumer). It owns the render…- login-form —
<LoginForm>is a pure-UI sign-in form used by the Wave 3<Login>page (and any custom consumer). It owns the render…
- login-form —
- permission-gate —
<PermissionGate>is a declarative conditional renderer that consumes the Wave 1usePermission()hook and decides wh…- permission-gate —
<PermissionGate>is a declarative conditional renderer that consumes the Wave 1usePermission()hook and decides wh…
- permission-gate —
- register-form —
<RegisterForm>is the pure-UI surface for account creation. It renders an identity grid (email + username + password…- register-form-fields —
<RegisterFormFields>is an internal helper that owns the responsive identity-grid layout used by<RegisterForm>. It… - register-form —
<RegisterForm>is the pure-UI surface for account creation. It renders an identity grid (email + username + password…
- register-form-fields —
- reset-password-form —
<ResetPasswordForm>is the pure-UI surface for setting a new password after the user clicks a reset link. It owns thr…- reset-password-form —
<ResetPasswordForm>is the pure-UI surface for setting a new password after the user clicks a reset link. It owns thr…
- reset-password-form —
- test-wrap — Internal test helper consumed only by the Wave 2 form
.test.tsxfiles insrc/components/<form>/. The helper wraps a…
- auth-guard —
- context —
auth-context.tsxexposes the React Context surface for the auth flow. It definesAuthContext, theAuthProviderco…- auth-context —
auth-context.tsxexposes the React Context surface for the auth flow. It definesAuthContext, theAuthProviderco…
- auth-context —
- error-codes —
error-codes.tsdefines the stable error-code registry for@suaveplan/react-authplus the ten typedReactAuthError…- error-codes —
error-codes.tsdefines the stable error-code registry for@suaveplan/react-authplus the ten typedReactAuthError…
- error-codes —
- use-auth-guard —
useAuthGuard(options)is the imperative counterpart to the declarative<AuthGuard>component. It reads the current… - use-permission —
usePermission()exposes a bitwise permission-check API over the currentuser.rolesbitmask. The package ships a clo… - lib —
better-auth-adapter.tsprovides the response-narrowing bridge betweenbetter-auth/client(which returns a `BetterAu…- better-auth-adapter —
better-auth-adapter.tsprovides the response-narrowing bridge betweenbetter-auth/client(which returns a `BetterAu…
- better-auth-adapter —
- observability —
react-auth-metrics.tsbuilds the OTel instrument set for@suaveplan/react-auth. Instruments are constructed lazily…- react-auth-metrics —
react-auth-metrics.tsbuilds the OTel instrument set for@suaveplan/react-auth. Instruments are constructed lazily…
- react-auth-metrics —
- email-verification —
<EmailVerificationPage>is the routing-aware adapter that wraps the Wave 2<EmailVerificationView>for the `?token=…- email-verification —
<EmailVerificationPage>is the routing-aware adapter that wraps the Wave 2<EmailVerificationView>for the `?token=…
- email-verification —
- forgot-password —
<ForgotPasswordPage>is the routing-aware adapter that wraps the Wave 2<ForgotPasswordForm>with the navigation an…- forgot-password —
<ForgotPasswordPage>is the routing-aware adapter that wraps the Wave 2<ForgotPasswordForm>with the navigation an…
- forgot-password —
- login —
<LoginPage>is the routing-aware adapter that wraps the Wave 2<LoginForm>with the navigation and auth-context wir…- login —
<LoginPage>is the routing-aware adapter that wraps the Wave 2<LoginForm>with the navigation and auth-context wir…
- login —
- profile —
<ProfilePage>is the routing-aware profile-settings surface for an authenticated user. It renders three tabs — Profil…- profile-account-section —
profile-account-section.tsxhouses the delete-account tab renderer for<ProfilePage>. It is split out of `profile-s… - profile-sections —
profile-sections.tsxhouses the two read/write tab renderers for<ProfilePage>:<ProfileSection>(name + email up… - profile —
<ProfilePage>is the routing-aware profile-settings surface for an authenticated user. It renders three tabs — Profil…
- profile-account-section —
- register —
<RegisterPage>is the routing-aware adapter that wraps the Wave 2<RegisterForm>with the navigation and auth-conte…- register —
<RegisterPage>is the routing-aware adapter that wraps the Wave 2<RegisterForm>with the navigation and auth-conte…
- register —
- reset-password —
<ResetPasswordPage>is the routing-aware adapter that wraps the Wave 2<ResetPasswordForm>for the?token=…-beari…- reset-password —
<ResetPasswordPage>is the routing-aware adapter that wraps the Wave 2<ResetPasswordForm>for the?token=…-beari…
- reset-password —
- cy-gb —
cy-gb.tsships the Welsh (Cymraeg,cy-GB) translation pack for the auth surface. The file conforms structurally to… - en-gb —
en-gb.tsships the British-English string table consumed by the Wave 2 forms and Wave 3 page components. The file als… - zh-cn —
zh-cn.tsships the Simplified-Chinese (zh-CN) translation pack for the auth surface. The file conforms structurally…
Install
bun add @suaveplan/react-auth
Peer requirements: react@^19, react-dom@^19, react-router-dom@^7.
Quick start
import {
AuthProvider,
AuthGuard,
createAuthClient,
useAuth,
} from "@suaveplan/react-auth";
const client = createAuthClient({
baseURL: "https://auth.example.com",
siteDomain: "tenant-a",
});
export function App({ children }: { children: React.ReactNode }) {
return (
<AuthProvider config={{ baseURL: "https://auth.example.com" }} client={client}>
<AuthGuard requireAuth requireVerified fallback={<LoginRedirect />}>
{children}
</AuthGuard>
</AuthProvider>
);
}
function Profile() {
const { user, signOut } = useAuth();
return (
<>
<h1>{user?.email}</h1>
<button onClick={() => signOut()}>Sign out</button>
</>
);
}
Modules
src/client/auth-client.md— typed wrapper aroundbetter-auth/client, propagatesx-site-domain.src/context/auth-context.md—AuthProvider+useAuth+ 11 actions.src/components/auth-guard/auth-guard.md— declarative gate component.src/components/auth-provider/auth-provider.md— back-compat re-export of the context surface.src/hooks/use-auth-guard.md— imperativereact-router-domredirect counterpart.src/hooks/use-permission.md— bitwise permission check (16 flags).src/lib/better-auth-adapter.md— narrowsbetter-authresponse unions to internal shapes.src/error-codes/error-codes.md—REACT_AUTH_CODESregistry + 10 typed error classes.src/observability/react-auth-metrics.md— counters + histogram undersuaveplan.react-auth.src/translations/en-gb.md— British English locale pack +AuthTranslationPackshape.src/translations/cy-gb.md— Welsh locale pack.src/translations/zh-cn.md— Simplified Chinese locale pack.src/types/auth.types.md—User,Session, credential / response shapes.src/types/crud.types.md— multi-tenant CRUD shapes (Site, UserSettings, Friend, …).
Wave scope
This package is the Wave 1 core. The Wave 2 forms (LoginForm, RegisterForm, ForgotPasswordForm, ResetPasswordForm, EmailVerifyForm) and Wave 3 page components (Login, Register, ForgotPassword, ResetPassword, EmailVerify, Profile, PermissionGate) extend this core without changing it.
Observability
All instrumented call paths emit through metrics.getMeter("suaveplan.react-auth"). Counters: react_auth.sign_in.total, react_auth.sign_up.total, react_auth.sign_out.total, react_auth.guard.allow.total, react_auth.guard.deny.total. Histogram: react_auth.session_fetch.duration_ms.