v0.2.0 · Auth available · Firestore next

Typed React hooks for Firebase, one hook per flow

Each hook runs a whole flow end to end and holds its own loading, error and success state. Zero dependencies — firebase and react stay peers.

Get startedBrowse the hooks
$ pnpm add @timonwa/firebase-hooks firebase

The same sign-in, twice

Email and password, with a server session minted from the ID token and errors surfaced to the UI.

Firebase directly21 lines
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

async function login(email: string, password: string) {
  setLoading(true);
  setError(null);
  try {
    const cred = await signInWithEmailAndPassword(
      auth,
      email,
      password,
    );
    const idToken = await cred.user.getIdToken();
    await createSession(idToken);
    return cred;
  } catch (e) {
    setError(toMessage(e));
  } finally {
    setLoading(false);
  }
}
With useLogin6 lines
const { login, loading, error } = useLogin(auth, {
  onIdToken: (idToken) => createSession(idToken),
});

const result = await login(email, password);
if (result.success) router.push("/dashboard");

And it does more: if createSession throws, the sign-in aborts rather than leaving a signed-in user with no server session.

What you get

Six decisions that shape every hook in the package.

Whole flows, not single calls

usePhoneSignIn builds and tears down the reCAPTCHA verifier. useOAuthSignIn finishes a redirect when the page returns. useEmailLinkSignIn asks for the address instead of calling window.prompt.

Failures are values

Actions never throw. A failure carries Firebase’s own code and the untouched original error, so you branch on a result instead of wrapping every call in try/catch.

Server sessions built in

onIdToken hands you a fresh ID token as part of the sign-in, not after it. Throw inside it and the sign-in aborts, so a user can’t land on a protected page without a server session.

Nothing withheld

Sign-ins hand back Firebase’s raw UserCredential. Error messages stay exactly as Firebase wrote them unless you opt into formatting.

Configure once, override anywhere

Session callbacks, action-code settings and error wording live on the provider. Any hook can override them, or opt out entirely with null.

Reauthentication handled

Pass currentPassword to a sensitive operation and the recent-sign-in check happens first. Omit it, and auth/requires-recent-login reaches you to handle your own way.

Twenty hooks, one contract

Every Firebase Auth client flow, each following the same shape — so learning one is learning the rest.

One import per service

An app only carries the services it uses. The most-used ship first.

  • Core@timonwa/firebase-hooksAvailable
  • Auth@timonwa/firebase-hooks/authAvailable
  • Firestore@timonwa/firebase-hooks/firestoreComing soon
  • Storage@timonwa/firebase-hooks/storageComing soon
  • Cloud Functions@timonwa/firebase-hooks/functionsComing soon

Sign a user in, in about five lines