npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

sveltekit-firebase-helpers

v0.0.12

Published

Helpers for using Firebase with SvelteKit

Downloads

88

Readme

sveltekit-firebase-helpers

Helpers for using Firebase with SvelteKit. Because I always end up with the same code on every SvelteKit + Firebase project I have ...

Firebase Auth Gotchas

When using Firebase Auth, the protocol of the auth service needs to match that of your app. What are the implications of this?

Well, if you're using the live Firebase Auth service you need to use https even when running in local dev mode which can be achieved via the vite-plugin-mkcert package. You will also need to make sure that your app follows the Best practices for using signInWithRedirect on browsers that block third-party storage access which, spoiler, you should do via Option 3 of that article (and what this package helps with). You could use signInWithPopup but you really shouldn't as it comes with its own problems.

If you're using the Auth Emulator you have two options. It runs on http only so will work fine if you don't include the vite-plugin-mkcert package in your vite config (but silently fail if you do). If you do need https locally for other reasons you can use Caddy as a reverse proxy to provide the secure access to it. Personally, I prefer to toggle the vite config so I don't have to install and start another service which keeps the project neat and self-contained.

Finally, how do you sync the client-side auth state to your server? If you only use firebase-hosted services you don't need to, but if you have code on your server that needs to know the identity of the user, such as a shopping cart checkout, it will be important. How do you do this?

You could check for the ID Token changing on the client, and send a fetch request to your own server to mirror the state using a cookie, but there are subtle issues with this - the ID Token is automatically refreshed when calling firebase services but the one in the cookie may end up out-of-date if you're calling your own server. You also then have state in two different places, potentially out-of-sync, which is not ideal.

A better option is to implement Session management with service workers where the existing client-side auth state is used to automatically add an Authorization bearer token to each server request - it will even handle an initial page load if you need the auth state for SSR. Adding this auth token is something else this package can help with.

It also handles some edge cases you may otherwise struggle with. Picture this - in response to a form POST action you want to update the custom claims for a user, maybe to indicate which service plan they are now on or that they have some new permission. You might expect to do the form post, have the invalidateAll() method called (which Svelte's use:enhance form action does for you by default) and see your freshly loaded data based on the claim you set during the server action. Except it won't. The Firebase client-side lib syncs the auth state of the main thread with the service-worker but it does it via polling so there can be a half-second or so where it doesn't have the latest auth token, or any auth token at all if you have just loaded a page from a sign-in redirect. Again, this is something this package can help with by providing it's own temporary auth-token-syncing for those situations just to ensure the state seen by the service-worker is completely up-to-date.

Oh, and one other issue - SvelteKit is often very opinionated but sometimes those opinions are a little blinkered. You can't, for instance, use dynamic .env variables in your service-worker code, only static ones which just doesn't cut-it for serious work - you should be able to deploy the same compiled code / docker image to different environments and have it work, having to compile a specific version for each one is tedious and error prone. Anyway, we built something in to handle this as well to save you the work of figuring it out.

Usage

How to use the features of the package. Of course, you need to install it using the package manager of your choice (which should be pnpm):

pnpm i sveltekit-firebase-helpers

Server Hooks

The server-side helpers are added as handlers in your app server hooks. You can add them separately (using sequence if you have multiple handlers) or use a single call to add them all. Let's go through each one individually first:

Auth Handle

To decode any http Authorization header added by the service-worker use createAuthHandle passing in the firebase-admin/auth instance it needs to decode the firebase ID token:

import { createAuthHandle } from "sveltekit-firebase-helpers";
import { auth } from './firebase.server'

export const handle = createAuthHandle(auth)

Any requests with an Authorication Bearer [token] header will now be decoded and added as a locals.user property.

Options Handle

The service-worker needs access to the firebase config, but SveleKit conspires to make that difficult to import. To get around this we provide our own server-endpoint that the service-worker can request it from.

import { createOptionsHandle } from "sveltekit-firebase-helpers";
import { options } from './firebase'

export const handle = createOptionsHandle(options)

Optionally pass an additional number of seconds to the createOptionsHandle call to publicly cache the response (default = 300, set 0 to disable).

Example options.ts:

import { dev } from '$app/environment'
import {
  PUBLIC_FIREBASE_API_KEY,
  PUBLIC_FIREBASE_AUTH_DOMAIN,
  PUBLIC_FIREBASE_DATABASE_URL,
  PUBLIC_FIREBASE_PROJECT_ID,
  PUBLIC_FIREBASE_STORAGE_BUCKET,
  PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
  PUBLIC_FIREBASE_APP_ID,
  PUBLIC_FIREBASE_MEASUREMENT_ID
} from '$env/static/public'

export const options = {
  apiKey: PUBLIC_FIREBASE_API_KEY,
  authDomain: dev ? 'localhost:5173' : PUBLIC_FIREBASE_AUTH_DOMAIN,
  databaseURL: PUBLIC_FIREBASE_DATABASE_URL,
  projectId: PUBLIC_FIREBASE_PROJECT_ID,
  storageBucket: PUBLIC_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
  appId: PUBLIC_FIREBASE_APP_ID,
  measurementId: PUBLIC_FIREBASE_MEASUREMENT_ID
}

You can test the handle is working correctly by requesting the /__/firebase/init.json endpoint in your app. You should see the client-side Firebase Options config returned (which is perfectly safe and normal to send to the client for the client-side Firebase libraries to work).

Proxy Handle

To proxy auth requests so you can use signInWithRedirect on browsers that block 3rd party cookies (now all of them) use createAuthHandle passing in the application-id.firebaseapp.com domain name from you Firebase app config, e.g. captaincodeman-experiment.firebaseapp.com.

import { createProxyHandle } from "sveltekit-firebase-helpers";
import { env } from '$env/dynamic/public'

const auth_domain = env.PUBLIC_FIREBASE_AUTH_DOMAIN

export const handle = createProxyHandle(auth_domain)

Any requests to /__/auth/... will be proxied to the auth_domain configured, effectively making your app serve the firebase auth endpoints itself to get around the 3rd party cookie restrictions.

If you need to set any additional http headers you can pass an optional HeadersInit as a separate object, e.g.:

export const handle = createProxyHandle(
	auth_domain,
	{ 'Cross-Origin-Embedder-Policy': 'require-corp' }
)

Service Worker

To automatically add the Authentication Bearer [idToken] http header to each server request, use the addFirebaseAuth method in your service worker. If running against the Firebase Auth Emulator pass that as a separate auth_emulator parameter. The service-worker code will automatically request and use the /__/firebase/init.json endpoint provided by the Options Handle above so it needs to be added to the Server Hooks.

/// <reference types="@sveltejs/kit" />
/// <reference no-default-lib="true"/>
/// <reference lib="esnext" />
/// <reference lib="webworker" />

import { addFirebaseAuth } from 'sveltekit-firebase-helpers'

addFirebaseAuth({
  auth_emulator: 'http://localhost:9099'  // if using the Firebase Auth Emulator
})

NOTE: when using a service-worker for firebase state, you must implement custom auth initialization specifically using indexedDBLocalPersistence for persistence. This is handled in the addFirebaseAuth implementation but for your own firebase client you can initialize it using:

import {
  browserPopupRedirectResolver,
  getAuth,
  indexedDBLocalPersistence,
  initializeAuth,
 } from 'firebase/auth'
import { app } from './app'
import { browser } from '$app/environment'

// SSR friendly auth initialization
export const auth = browser
  ? initializeAuth(app, {
      persistence: [indexedDBLocalPersistence],
      popupRedirectResolver: browserPopupRedirectResolver,
    })
  : getAuth(app)

The browser check is to avoid an error if using SSR.

One additional advantage of this is that your client-side auth dependencies are reduced so your app should start faster (you can also avoid loading the popupRedirectResolver for initialization and pass it to methods like signInWithRedirect when called for even greater savings).

When using signInWithRedirect your page loads and will automatically handle the redirect token or you may call getRedirectResult to get the result yourself. At this point, your SvelteKit load functions will have already run with an unauthenticated user so to update your app data you may need to call invalidateAll to re-run the load functions. But because of the polling delay, the service-worker may not have the auth token yet so we've provided a syncAuthToken method that will send it to the client - call it before the invalidateAll.

The same situation happens if you update the auth claims on the server inside any endpoint or form action. You can use syncAuthToken to ensure that any invalidateAll call will include the latest token when data is refreshed from the server.

Project configuration

TODO: detail project configutation for local development with and without Firebase Auth Emulator, and what .env settings should be used.