This repository contains the source code for the FirebaseUI for Web project rewrite, focused on providing Authentication components for popular JavaScript frameworks.
FirebaseUI requires the firebase
package to be installed:
npm install firebase
Note: Since the packages are not yet published to npm, you must manually install them from GitHub releases. Once published, these steps will be simplified.
Packages have been created for both React
and Angular
. For now, they're only available as direct downloads from this repository. Add the following to your package.json
file:
React
{
"dependencies": {
"@firebase-ui/react": "https://github.com/firebase/firebaseui-web/raw/refs/heads/v7-alpha/releases/firebase-ui-react-0.0.1.tgz",
"@firebase-ui/core": "https://github.com/firebase/firebaseui-web/raw/refs/heads/v7-alpha/releases/firebase-ui-core-0.0.1.tgz",
"@firebase-ui/styles": "https://github.com/firebase/firebaseui-web/raw/refs/heads/v7-alpha/releases/firebase-ui-styles-0.0.1.tgz",
"@firebase-ui/translations": "https://github.com/firebase/firebaseui-web/raw/refs/heads/v7-alpha/releases/firebase-ui-translations-0.0.1.tgz"
}
}
Angular
FirebaseUI for Angular depends on the AngularFire package:
{
"dependencies": {
"@angular/fire": "^19.1.0",
"@firebase-ui/angular": "https://github.com/firebase/firebaseui-web/raw/refs/heads/v7-alpha/releases/firebase-ui-angular-0.0.1.tgz",
"@firebase-ui/core": "https://github.com/firebase/firebaseui-web/raw/refs/heads/v7-alpha/releases/firebase-ui-core-0.0.1.tgz",
"@firebase-ui/styles": "https://github.com/firebase/firebaseui-web/raw/refs/heads/v7-alpha/releases/firebase-ui-styles-0.0.1.tgz",
"@firebase-ui/translations": "https://github.com/firebase/firebaseui-web/raw/refs/heads/v7-alpha/releases/firebase-ui-translations-0.0.1.tgz"
}
}
FirebaseUI requires that your Firebase app is setup following the Getting Started with Firebase flow for Web:
import { initializeApp } from 'firebase/app';
const app = initializeApp({ ... });
Next, setup and configure FirebaseUI, import the initializeUI
function from @firebase-ui/core
:
import { initializeUI } from "@firebase-ui/core";
const ui = initializeUI();
To learn more about configuring FirebaseUI, view the configuration section.
React
FirebaseUI for React requires that your application be wrapped in the ConfigProvider
, providing the initialized UI configuration. React expects the FirebaseApp
instance be provided to the initializeUI
configuration:
import { initializeApp } from 'firebase/app';
import { initializeUI } from "@firebase-ui/core";
import { ConfigProvider } from '@firebase-ui/react';
const app = initializeApp({ .. });
const ui = initializeUI({ app });
createRoot(document.getElementById("root")!).render(
<StrictMode>
<ConfigProvider config={ui}>
<App />
</ConfigProvider>
</StrictMode>
);
Angular
FirebaseUI depends on AngularFire being configured to inject Firebase Auth into your Angular application. Additionally, the provideFirebaseUI
function is required to inject FirebaseUI into your application:
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { provideAuth, getAuth } from '@angular/fire/auth';
import { provideFirebaseUI } from '@firebase-ui/angular';
import { initializeUI } from '@firebase-ui/core';
export const appConfig: ApplicationConfig = {
providers: [
provideFirebaseApp(() => initializeApp({ .. })),
provideAuth(() => getAuth()),
provideFirebaseUI(() => initializeUI({}))
..
],
..
}
Next, import the CSS styles for the FirebaseUI project.
If you are using TailwindCSS, import the base CSS from the @firebase-ui/styles
package after your Tailwind import:
@import "tailwindcss";
@import "@firebase-ui/styles/src/base.css";
If you are not using Tailwind, import the distributable CSS in your project:
@import "@firebase-ui/styles/dist.css";
To learn more about theming, view the theming section.
FirebaseUI provides a number of opinionated components designed to drop into your application which handle common user flows, such as signing in or registration.
Allows users to sign in with an email and password:
React
import { SignInAuthScreen } from "@firebase-ui/react";
function App() {
return <SignInAuthScreen />;
}
Props: onForgotPasswordClick
/ onRegisterClick
Additionally, allow the user to sign in with an OAuth provider by providing children:
import { SignInAuthScreen, GoogleSignInButton } from "@firebase-ui/react";
function App() {
return (
<SignInAuthScreen>
<GoogleSignInButton />
</SignInAuthScreen>
);
}
Angular
import { SignUpAuthScreenComponent } from "@firebase-ui/angular";
@Component({
selector: "app-root",
imports: [SignUpAuthScreenComponent],
template: `<fui-sign-up-auth-screen></fui-sign-up-auth-screen>`,
})
export class AppComponent {}
The initializeUI function accepts an options object that allows you to customize FirebaseUI’s behavior.
type FirebaseUIConfigurationOptions = {
app: FirebaseApp;
locale?: Locale | undefined;
translations?: RegisteredTranslations[] | undefined;
behaviors?: Partial<Behavior<keyof BehaviorHandlers>>[] | undefined;
recaptchaMode?: 'normal' | 'invisible' | undefined;
};
App: The initialized Firebase app instance. This is required.
Locale: Optional locale string to override the default language (e.g., 'en', 'fr', 'es').
Translations: Add or override translation strings for labels, prompts, and errors.
Behaviors: Customize UI behavior such as automatic sign-in or error handling.
RecaptchaMode:Set the reCAPTCHA mode for phone auth (default is 'normal').
FirebaseUI provides a basic default theme out of the box, however the theme can be customized to match your application's design.
The package uses CSS Variables, which can be overridden in your application's CSS. Below is a list of all available variables:
:root {
/* The primary color is used for the button and link colors */
--fui-primary: var(--color-black);
/* The primary hover color is used for the button and link colors when hovered */
--fui-primary-hover: --alpha(var(--fui-primary) / 85%);
/* The primary surface color is used for the button text color */
--fui-primary-surface: var(--color-white);
/* The text color used for body text */
--fui-text: var(--color-black);
/* The muted text color used for body text, such as subtitles */
--fui-text-muted: var(--color-gray-800);
/* The background color of the cards */
--fui-background: var(--color-white);
/* The border color used for none input fields */
--fui-border: var(--color-gray-200);
/* The input color used for input fields */
--fui-input: var(--color-gray-300);
/* The error color used for error messages */
--fui-error: var(--color-red-500);
/* The radius used for the input fields */
--fui-radius: var(--radius-sm);
/* The radius used for the cards */
--fui-radius-card: var(--radius-xl);
}
The default values are based on the TailwindCSS theme variables. You can override these values with other TailwindCSS theme variables, or custom CSS values.
@firebase-ui/core
is a framework-agnostic layer that manages the complete lifecycle of Firebase Authentication flows. It exposes a reactive store via nanostores that can be wrapped and adapted into any JavaScript framework such as React, Angular, Vue, Svelte, or SolidJS to name a few.
-
Manages Firebase Authentication flows (sign-in, sign-out, linking, etc.)
-
Reactive UI state via nanostores
-
Form schemas using Zod
-
Pluggable behaviors (e.g. autoAnonymousLogin)
-
i18n and translations
-
Error parsing and localization
Call initializeUI() with your Firebase app and configuration options:
import { initializeUI } from '@firebase-ui/core';
const ui = initializeUI({
app: firebaseApp,
..
});
Configuration Type:
type FirebaseUIConfigurationOptions = {
app: FirebaseApp;
locale?: Locale | undefined;
translations?: RegisteredTranslations[] | undefined;
behaviors?: Partial<Behavior<keyof BehaviorHandlers>>[] | undefined;
recaptchaMode?: 'normal' | 'invisible' | undefined;
};
signInWithEmailAndPassword: Signs in the user based on an email/password credential.
- ui: FirebaseUIConfiguration
- email: string
- password: string
createUserWithEmailAndPassword: Creates a user account based on an email/password credential.
- ui: FirebaseUIConfiguration
- email: string
- password: string
signInWithPhoneNumber: Signs in the user based on a provided phone number, using ReCaptcha to verify the sign-in.
- ui: FirebaseUIConfiguration
- phoneNumber: string
- recaptchaVerifier: string
confirmPhoneNumber: Verifies the phonenumber credential and signs in the user.
- ui: FirebaseUIConfiguration
- confirmationResult: ConfirmationResult
- verificationCode: string
sendPasswordResetEmail: Sends password reset instructions to an email account.
- ui: FirebaseUIConfiguration
- email: string
sendSignInLinkToEmail: Send an sign-in links to an email account.
- ui: FirebaseUIConfiguration
- email: string
signInWithEmailLink: Signs in with the user with the email link. If autoUpgradeAnonymousCredential
then a pending credential will be handled.
- ui: FirebaseUIConfiguration
- email: string
- link: string
signInAnonymously: Signs in as an anonymous user.
- ui: FirebaseUIConfiguration
signInWithOAuth: Signs in with a provider such as Google via a redirect link. If autoUpgradeAnonymousCredential
then the account will upgraded.
- ui: FirebaseUIConfiguration
- provider: AuthProvider
completeEmailLinkSignIn: Completes the signing process based on a user signing in with an email link.
- ui: FirebaseUIConfiguration
- currentUrl: string
Using the returned FirebaseUIConfiguration
, it is reccomended to use local context/providers/dependency-injection to expose the FirebaseUIConfiguration to the application. Here is an example context wrapper which accepts the configuration as a ui
parameter:
/** Creates a framework-agnostic context for Firebase UI configuration **/
export function createFirebaseUIContext(initialConfig) {
let config = initialConfig;
const subscribers = new Set();
return {
/** Retrieve current config **/
getConfig() {
return config;
},
/** Update config and notify subscribers **/
setConfig(newConfig) {
config = newConfig;
subscribers.forEach((callback) => callback(config));
},
/** Subscribe to config changes (for use in any framework) **/
subscribe(callback) {
subscribers.add(callback);
/** Optionally call immediately with current config**/
callback(config);
return () => subscribers.delete(callback);
},
};
}
FirebaseUI Configuration Type:
export type FirebaseUIConfiguration = {
app: FirebaseApp,
getAuth: () => Auth,
setLocale: (locale: Locale) => void,
state: FirebaseUIState,
setState: (state: FirebaseUIState) => void,
locale: Locale,
translations: TranslationsConfig,
behaviors: Partial<Record<BehaviorKey, BehaviorHandlers[BehaviorKey]>>,
recaptchaMode: "normal" | "invisible",
};
Through this approach, you can now achieve global access to the FirebaseUI methods and state.
FirebaseUI Core provides built-in state management to track the current step in the authentication flow. This can be used to drive UI transitions, control rendering, or show progress indicators.
type FirebaseUIState =
| "loading"
| "idle"
| "signing-in"
| "signing-out"
| "linking"
| "creating-user"
| "sending-password-reset-email"
| "sending-sign-in-link-to-email";
These represent the current phase of the user experience — such as waiting for input, submitting credentials, or linking accounts.
The core module automatically updates state based on auth activity, but you can also override it manually if needed:
/** Set the UI state to "idle" **/
ui.setState("idle");
In a component, you can access the current state through the FirebaseUI configuration:
/** Sample: Framework-agnostic UI state management **/
/** Create a simple UI state store with an initial state **/
const uiStore = createUIStateStore({ state: "idle" });
uiStore.subscribe((ui) => {
/** Replace `showSpinner` and `showMainApp` with your actual rendering logic **/
if (ui.state === "signing-in") {
showSpinner();
} else {
showMainApp();
}
});
You can pass one or more translations to support localized strings.
import { english } from "@firebase-ui/translations";
initializeUI({
app,
locale: "en",
translations: [english],
});
To override or add your own strings:
const customFr = {
locale: "fr",
translations: {
errors: {
invalidEmail: "Adresse e-mail invalide",
},
},
};
To use a string at runtime (e.g., in an error message):
import { getTranslation } from "@firebase-ui/core";
const message = getTranslation(config, "errors", "unknownError");
When multiple translation sets are passed, FirebaseUI merges them in order — allowing you to layer overrides on top of built-in language packs.
FirebaseUI uses Zod to validate authentication forms. This ensures consistent, strongly typed, and localized error handling across form components.
Each schema can be used standalone or integrated into your custom forms. You can pass in a TranslationsConfig object to localize error messages.
createEmailFormSchema(translations?) Validates a sign-in or sign-up form using email and password.
-
email: Must be a valid email address.
-
password: Must be at least 8 characters.
import { createEmailFormSchema } from "@firebase-ui/core";
const schema = createEmailFormSchema(translations);
createForgotPasswordFormSchema(translations?) Validates the forgot password form.
- email: Must be a valid email address.
const schema = createForgotPasswordFormSchema(translations);
createEmailLinkFormSchema(translations?) Validates the email link authentication form.
- email: Must be a valid email address.
const schema = createEmailLinkFormSchema(translations);
createPhoneFormSchema(translations?) Validates the phone number authentication form using reCAPTCHA.
-
phoneNumber: Must be a valid phone number with at least 10 digits.
-
verificationCode: Optional, must be at least 6 digits if provided.
-
recaptchaVerifier: Must be an instance of RecaptchaVerifier.
const schema = createPhoneFormSchema(translations);
Handling errors can be managed using Zods parsing functions such as safeParse
The core library provides a function for handling errors.
export function handleFirebaseError(
ui: FirebaseUIConfiguration,
error: any,
opts?: {
enableHandleExistingCredential?: boolean;
}
)
This function will run through a series of checks to catch known Firebase errors:
-
auth/account-exists-with-different-credential
: Checking the error code to see if an account already exists for the user. IfenableHandleExistingCredential
is enabled the library will update the local storage automtaically before throwing the error. -
FirebaseUIError
: Alternatively, a FirebaseUIError will be thrown with the appropriate code.