Using Firebase Admin SDK with Next.js 13
I recently had to use Firestore Database and Firebase Storage for the backend of a NextJs application. This is a guide on how you can set this up. We will look at how to pull in a list of collections and their data, get a specific document by its ID, and lastly get an image from storage using the public download url.
I also show you how you can hide this public download url behind an API route for another level of obfuscation for your front-end.
Getting Started
Section titled Getting StartedThe first thing you are going to need is a Firebase Project. To set this up start here. I go through this in the video above, if you do not already have one set up.
Once you have created the project, create a new web app within that project.
Once that is created, go ahead to the project settings. Here we need to download a service account private key. Go to the service accounts tab and click Generate new private key
. This should download a JSON file we will use later
1. Add your environment variables
Section titled 1. Add your environment variablesWe will need to add four values to our environment variables. If you dont already have a .env
file create one now. If you have one add these values in to the file:
Fill these values in with the respective values from the JSON you downloaded earlier. Storage bucket by default will be the project ID plus .appspot.com
at the end. You can also find this in your project settings, under the web app configuration.
2. Install npm packages
Section titled 2. Install npm packagesWe will need the firebase-admin
package, so go ahead and install that.
I also reccommend installing server-only
, I will explain this in section 3.
3. Initialise Firebase Admin
Section titled 3. Initialise Firebase AdminNow that we have our configuration values, we need to create a function to utilise these. Create a file called firebaseAdmin.ts
. This is the file we will use to store the configuration for firebase admin.
Populate the file with the code below, I’ll explain the key points:
At the top of the file we import server-only
. This adds a build time check to our project, that ensures any function run in this file is run in a server environment. This helps catch leaks into client components. Read more here.
The function initAdmin()
will need to be called wherever we want to access firestore/storage. This ensures an application has been initialised. If its called and one is already initialised, it will return that instance and not create a new one.
4. Fetch data from firestore
Section titled 4. Fetch data from firestoreTo fetch some data from firestore, I am again going to create a new file to house our functions, with the server-only header as well. Mine will be called firebase.ts
I am going to add some example functions in here to fetch some data I have stored in the database, as well as a public download URL for a file I have stored in storage.
In the function getLogoFromStorage
its worth noting the logo.png
is the path to the file in firebases storage. So if you had it nested in a folder it would look something like this images/logo.png
.
Further, the getLogoFromStorage
function uses the firebase public download url. In Firebase, a public download URL is a unique link generated for a file stored in Firebase Cloud Storage, which allows the file to be accessed, provided they have the correct access token. The access token is a random UUIDv4 string that makes the URL hard to guess, thereby providing a level of security against unauthorized access. In a section below I explain how you can further hide this url from your users.
Lastly, these functions will not work unless we call the initAdmin
function we defined earlier. Before you call these, make sure you do await initAdmin()
.
5. Using in Server Components
Section titled 5. Using in Server ComponentsTo use these in a server component, make sure the default export is an async function.
After that we need to make sure we call await initAdmin()
to initalise the application set-up if it has not been already.
Then it is as simple as calling the functions to get the data we need.
6. Hiding Firebase Public Download URLs
Section titled 6. Hiding Firebase Public Download URLsTo hide the public download URL, we are going to utilise a NextJS API route. This route will be used as the new url for the file. You could pass it additional parameters in the body to handle a range of files. For this example we are simply going to hide the URL of an image. You could also do this in any server environment that you can make requests in, such as Cloud Functions.
First create the API route, this will be a folder structure like this app/api/image/route.ts
,
Next, add the following:
Again, we are calling the initAdmin
function to ensure the application is initialised.
Next we are simply using the same method to get the URL, but this time it will only occur on the server.
Lastly, we fetch the URL from within the function, and we return its response as a new one.
Now when you go to /api/image
it will load in the image, but with a clean URL, and the public download URL with the access token has only been exposed to the server.