<authui />

React

Hooks and wrapper components from @getauthui/core/react.

npm install @getauthui/core appwrite lit
import {
  AuthUIProvider,
  AuthUIButton,
  AuthUIUserButton,
  Show,
  useAuthUI,
} from "@getauthui/core/react";

const config = {
  endpoint: "https://cloud.appwrite.io/v1",
  project: "YOUR_PROJECT_ID",
  methods: { emailPassword: true, oauth: ["google"] },
};

export function App() {
  return (
    <AuthUIProvider config={config}>
      <Header />
    </AuthUIProvider>
  );
}

function Header() {
  const { status, user, open, signOut } = useAuthUI();
  return (
    <header>
      <Show when="signed-out">
        <AuthUIButton>Sign in</AuthUIButton>
      </Show>
      <Show when="signed-in">
        <span>{user?.name}</span>
        <AuthUIUserButton />
      </Show>
      {status === "signed-in" && <button onClick={signOut}>Sign out</button>}
      <button onClick={() => open("account")}>Account</button>
    </header>
  );
}

useAuthUI()

Returns the current state plus helpers, and re-renders on every change.

FieldTypeDescription
status"loading" / "signed-out" / "signed-in" / "mfa-required"Current state.
userModels.User | nullThe signed-in user.
mfaFactorsModels.MfaFactors | nullAvailable factors while status is mfa-required.
pendingpending action or nullA redirect flow waiting to be finished.
configuredbooleanWhether a complete config (endpoint and project) was applied.
configErrorstring | nullDeveloper-facing config problem, or null.
open(view?)functionOpen the modal.
close()functionClose the modal.
signOut()functionEnd the current session.
storeAuthStoreFull imperative API.

Components

ComponentWrapsProps
AuthUIProviderconfigures the store synchronouslyconfig
AuthUIModal<authui-modal>view, open, closeOnSuccess, onOpenChange, onSignedIn, onClose
AuthUIButton<authui-button>view, variant, size, children
AuthUIUserButton<authui-user-button>src, showTeams, menuItems, onMenuAction, children
AuthUISignIn<authui-sign-in>view, email, loginHint, onSuccess
AuthUIAccount<authui-account>tab
Showconditional render (not Lit slot)when, unless, children

Show vs <authui-show>

The React Show wrapper returns null when the status does not match, so children are not mounted and their effects do not run. That is what you want when a child calls store.getClient() on mount.

The Lit <authui-show> element only skips its slot. Children stay in the DOM (hidden). Prefer the React Show in React apps; keep <authui-show> for plain HTML.

AuthUIProvider configuration timing

AuthUIProvider calls configure() during render, so the first paint already sees configured: true and a non-null getClient() when endpoint and project are set. If either is empty, it mirrors <authui-config>: configured stays false and configError explains what is missing. Changing any field on config (methods, branding, preview, strings, and so on) reconfigures the store. Passing a new object every render with the same values is fine; the provider fingerprints a canonical (sorted-key) JSON of the config, so key insertion order does not matter.

closeOnSuccess={false}

Pass closeOnSuccess={false} to AuthUIModal to keep the modal open after sign in. In HTML use close-on-success="false" on <authui-modal> (the string "false" is required; a bare boolean attribute would stay on).

Controlled open

Pass open as a boolean to drive the dialog from React state. open={true} opens it; open={false} force-closes it (including after the user opened it another way). Omit open to leave the modal uncontrolled.

When the user closes via Escape, backdrop click, or the X button, Lit hides the dialog. Wire onOpenChange so parent state stays in sync; otherwise the next setOpen(true) is a no-op because React still thinks the dialog is open.

const [modalOpen, setModalOpen] = useState(false);

<>
  <button onClick={() => setModalOpen(true)}>Open</button>
  <AuthUIModal open={modalOpen} onOpenChange={setModalOpen} />
</>;

onOpenChange(false) runs when the dialog closes. onClose is a convenience alias for that case. onSignedIn bridges the Lit authui-signed-in event so Modal + Button apps do not need to subscribe to the store by hand.

<AuthUIModal
  open={modalOpen}
  onOpenChange={setModalOpen}
  onSignedIn={(user) => console.log(user.$id)}
  onClose={() => console.log("closed")}
/>

Setting open to false writes through to the element so the dialog closes even when it was opened via AuthUI.open() or a button.

Typing custom elements in JSX

If you prefer to use the elements directly in TSX, add a declaration:

import type { AuthUIView } from "@getauthui/core";

declare module "react" {
  namespace JSX {
    interface IntrinsicElements {
      "authui-button": React.DetailedHTMLProps<
        React.HTMLAttributes<HTMLElement> & {
          view?: AuthUIView;
          variant?: string;
          size?: "sm" | "md" | "lg";
        },
        HTMLElement
      >;
      "authui-modal": React.DetailedHTMLProps<
        React.HTMLAttributes<HTMLElement> & {
          view?: AuthUIView;
          open?: boolean;
          "close-on-success"?: boolean | string;
        },
        HTMLElement
      >;
      "authui-sign-in": React.DetailedHTMLProps<
        React.HTMLAttributes<HTMLElement> & {
          view?: AuthUIView;
          email?: string;
          "login-hint"?: string;
        },
        HTMLElement
      >;
      "authui-account": React.DetailedHTMLProps<
        React.HTMLAttributes<HTMLElement> & { tab?: string },
        HTMLElement
      >;
      "authui-user-button": React.DetailedHTMLProps<
        React.HTMLAttributes<HTMLElement> & {
          src?: string;
          "show-teams"?: boolean | string;
        },
        HTMLElement
      >;
      "authui-show": React.DetailedHTMLProps<
        React.HTMLAttributes<HTMLElement> & { when?: string; unless?: string },
        HTMLElement
      >;
      "authui-config": React.DetailedHTMLProps<
        React.HTMLAttributes<HTMLElement> & { endpoint: string; project: string },
        HTMLElement
      >;
    }
  }
}

FOUC CSS in React

Import @getauthui/core/fouc.css (or the CDN dist/fouc.css link). Prefer authui-show:not([ready]) over :defined for FOUC CSS. React can define custom elements before Auth UI sets ready, so [ready] is the reliable gate. See <authui-show>.

Next.js

The components touch window, so import the package from a client component or inside useEffect. The wrappers in @getauthui/core/react are safe to import in client components.

On this page