• This repository has been archived on 16/Nov/2023
  • Stars
    star
    105
  • Rank 317,856 (Top 7 %)
  • Language
    TypeScript
  • Created over 4 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Next.js + ZEIT Now + Firebase [template]

DEV.TO: โ–ฒ๐Ÿ”ฅ Getting started with Next.js + Now + Firebase

This is a tutorial focused on setting up a minimal template project for Next.js, ZEIT Now, and Firebase.

  • The template project is an extension of the official Next.js with-firebase-authentication-serverless example, with a bit more functionality.
  • This tutorial provides some extra guidance on setting up environments & keys.
  • I've included lots of screenshots, so even if you aren't starting a new project, you'll get a feel for what working with these tools is like. I think this is a good snapshot of the state of the art in 2020 for quick-start developer products.

Recently, I started a new side project using:

I like this combination of tools a lot, so I decided to put together a detailed tutorial.

You can follow along using this template project:

{% github benzguo/nextjs-now-firebase no-readme %}

The template also includes Tailwind CSS (with ~zero styling). Here's what the sign up page looks like:

This template app includes:

  • Sign up, log in, log out
  • Update display name
  • Add object to a Firestore collection
  • List objects in a Firestore collection (using firestore-pagination-hook)
  • Fetch data with a simple Firebase function (server-side rendering using getInitialProps)

โ–ฒ Sign up for ZEIT

[ โคด๏ธ Sign up for ZEIT ]

I used the email signup flow, and thought it was pretty nice โœจ You can check out screenshots of the ZEIT onboarding flow [ โคต๏ธ here ].

ZEIT โ€“ empty dashboard

๐Ÿ”ฅ Set up Firebase

[ โคด๏ธ Sign up for Firebase ]

Sign into your Firebase account, and create two projects (one for your staging environment, and another for your production environment).

tl;dr: You'll need to do some clicking around to fully configure a new Firebase project. Check out the full Firebase project onboarding walkthrough [ โคต๏ธ here ].

Firebase โ€“ 2 projects

โ–ฒ Set up Now CLI

Install the Now CLI and run now login

now login

๐Ÿ”ฅ Set up Firebase CLI

Install the Firebase CLI and run firebase login

firebase login

If you haven't done this already:

  • generate a new project from the GitHub template repo
  • clone it to your machine
  • and navigate to the directory in your terminal.

{% github benzguo/nextjs-now-firebase no-readme %}

Run firebase use --add to add the two projects you created to the Firebase CLI. Use "staging" and "production" as your project aliases.

firebase use --add

โ–ฒ๐Ÿ”ฅ Now + Firebase

Staging environment

First, we'll configure our project's staging environment with keys from Firebase.

In the Firebase console, open your staging project, navigate to the "Service accounts" tab, and click "Generate new private key" to download your admin SDK keys.

Firebase โ€“ admin keys

Save the key file in the functions directory as serviceAccount-staging.json

๐Ÿ“ functions โ”œโ”€โ”€ serviceAccount-staging.json

โš ๏ธ Your private key (in your service account key file) gives access to your project's Firebase services. Keep it confidential and never store it in a public repository.

Note that serviceAccount* files are in the project's .gitignore, so they won't be checked into your repository. Make sure you follow best practices for keeping these keys safe! ๐Ÿ”’

Next, find your app keys (under Project settings).

Firebase โ€“ app keys

Enter these variables in the .env and .env.build files included in the template project.

Create two env files: $ touch .env $ touch .env.build

  • .env: runtime environment variables
  • .env.build: build step environment variables

Open your your editor, and the content below to the 2 .env files, filling in your Firebase keys.

.env

# .env
# == Firebase app keys (staging) ==
FIREBASE_API_KEY=โ– โ– โ– โ– โ– โ– โ– โ– -โ– โ– โ– โ– โ– โ– โ– โ– 
FIREBASE_AUTH_DOMAIN=โ– โ– โ– โ– โ– โ– โ– โ– .firebaseapp.com
FIREBASE_DATABASE_URL=https://โ– โ– โ– โ– โ– โ– โ– โ– .firebaseio.com
FIREBASE_PROJECT_ID=โ– โ– โ– โ– โ– โ– โ– โ– 
FIREBASE_STORAGE_BUCKET=โ– โ– โ– โ– โ– โ– โ– โ– .appspot.com
FIREBASE_MESSAGING_SENDER_ID=โ– โ– โ– โ– โ– โ– โ– โ– 
FIREBASE_APP_ID=1:โ– โ– โ– โ– โ– โ– โ– โ– :web:โ– โ– โ– โ– โ– โ– โ– โ– 
FIREBASE_MEASUREMENT_ID=G-โ– โ– โ– โ– โ– โ– โ– โ– 

.env.build

# .env.build
# == Firebase app keys (staging) ==
FIREBASE_API_KEY=โ– โ– โ– โ– โ– โ– โ– โ– -โ– โ– โ– โ– โ– โ– โ– โ– 
FIREBASE_AUTH_DOMAIN=โ– โ– โ– โ– โ– โ– โ– โ– .firebaseapp.com
FIREBASE_DATABASE_URL=https://โ– โ– โ– โ– โ– โ– โ– โ– .firebaseio.com
FIREBASE_PROJECT_ID=โ– โ– โ– โ– โ– โ– โ– โ– 
FIREBASE_STORAGE_BUCKET=โ– โ– โ– โ– โ– โ– โ– โ– .appspot.com
FIREBASE_MESSAGING_SENDER_ID=โ– โ– โ– โ– โ– โ– โ– โ– 
FIREBASE_APP_ID=1:โ– โ– โ– โ– โ– โ– โ– โ– :web:โ– โ– โ– โ– โ– โ– โ– โ– 
FIREBASE_MEASUREMENT_ID=G-โ– โ– โ– โ– โ– โ– โ– โ– 
# == Firebase admin keys (from serviceAccount-staging.json) ==
FIREBASE_CLIENT_EMAIL=firebase-adminsdk-โ– โ– โ– โ– @โ– โ– โ– โ– โ– โ– โ– โ– .iam.gserviceaccount.com
FIREBASE_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\nโ– โ– โ– โ– โ– โ– โ– โ– \n-----END PRIVATE KEY-----\n

โš ๏ธ These keys give access to your project's Firebase services. Keep them confidential and never store them in a public repository.

Note that .env* files are in the project's .gitignore, so they won't be checked into your repository. Make sure you follow best practices for keeping these keys safe! ๐Ÿ”’

Now, you're ready to try running the app locally.

$ npm install $ npm run dev

When you open http://localhost:3000 in your browser, you should see this page:

Try creating an account โœ…

Production environment

Now, we'll configure the project's production environment with keys from Firebase.

Open your production project in the Firebase console, and follow the same steps as above:

  1. Download your admin keys to /functions/serviceAccount-production.json
  2. Find your app keys in the Firebase console's Project settings page.

Run the following commands to add your production Firebase keys to Now:

$ now secrets add firebase-api-key โ– โ– โ– โ– โ– โ– โ– โ– -โ– โ– โ– โ– โ– โ– โ– โ– 

$ now secrets add firebase-auth-domain โ– โ– โ– โ– โ– โ– โ– โ– .firebaseapp.com

$ now secrets add firebase-database-url https://โ– โ– โ– โ– โ– โ– โ– โ– .firebaseio.com

$ now secrets add firebase-project-id โ– โ– โ– โ– โ– โ– โ– โ– 

$ now secrets add firebase-storage-bucket โ– โ– โ– โ– โ– โ– โ– โ– .appspot.com

$ now secrets add firebase-messaging-sender-id โ– โ– โ– โ– โ– โ– โ– โ– 

$ now secrets add firebase-app-id 1:โ– โ– โ– โ– โ– โ– โ– โ– :web:โ– โ– โ– โ– โ– โ– โ– โ– 

$ now secrets add firebase-measurement-id G-โ– โ– โ– โ– โ– โ– โ– โ– 

$ now secrets add firebase-client-email firebase-adminsdk-โ– โ– โ– โ– @โ– โ– โ– โ– โ– โ– โ– โ– .iam.gserviceaccount.com

$ now secrets add -- firebase-private-key "-----BEGIN PRIVATE KEY-----\nโ– โ– โ– โ– โ– โ– โ– โ– \n-----END PRIVATE KEY-----\n"

๐Ÿ”ฅ Firestore โ€“ creating a custom index

Here, we'll walk through creating an index in Firestore. You'll need to do this pretty frequently as you iterate on your app's data model.

Navigate to http://localhost:3000/spaces, and open your browser's console.

You should see an error in the console, with a link to create an index.

Firestore - create index error

Following the link takes you to the Firestore dashboard, with a modal to create a new index:

This workflow is great for prototyping. As you solidify your data model, you can switch to deploying indexes from the CLI.

๐Ÿ”ฅ Firebase functions โ€“ setup

Here, we'll configure Firebase functions to support deploying to staging & production, and then deploy functions.

Now, navigate to http://localhost:3000/account

You should see an error. This page makes a request to a Firebase function, and we haven't deployed functions yet.

To set up functions, we'll configure our staging & production projects with an environment config variable. Functions use this config variable to decide which keys to use at runtime.

$ firebase use staging
Now using alias staging (my-project-staging)

$ firebase functions:config:set app.environment="staging"
โœ”  Functions config updated.

$ firebase use production
Now using alias production (my-project-production)

$ firebase functions:config:set app.environment="production"
โœ”  Functions config updated.

Now, we can deploy functions to staging and production.

First, install dependencies: $ cd functions && npm install && cd ..

Deploy to staging: $ firebase deploy -P staging --only functions

Deploy to production: $ firebase deploy -P production --only functions

{% asciinema 299401 %}

Navigate to http://localhost:3000/account. You should be able to load the page without errors โœ…

โ–ฒ Deploy app to production

Finally, we'll run now to set up a ZEIT Now project and deploy to production.

$ now

{% asciinema 299403 %}

final

In the future, you can deploy your app to production using now --prod. To run the app locally, use now dev.

๐Ÿ“Œ Reference

Run app locally (using staging environment)

$ now dev

Deploy functions to staging

$ firebase deploy -P staging --only functions

Deploy functions to production

$ firebase deploy -P production --only functions

Run functions locally

$ cd functions && npm run shell

Deploy to production

$ now --prod

Running functions locally

To run Firebase functions locally, navigate to the functions directory and run npm run shell

$ cd functions && npm run shell
...
โœ”  functions: Emulator started at http://localhost:5000
i  functions: Loaded functions: getEnvironment
firebase > getEnvironment({})
Sent request to function.
firebase > 
RESPONSE RECEIVED FROM FUNCTION: 200, {
  "result": {
    "environment": "staging"
  }
}

This project is configured to use the staging environment when running functions locally.

Running functions locally can be convenient for development, but handling authenticated functions can be tricky. Firebase has some local emulators, but it's unclear what the story is for emulating authentication.

Often, I'll just deploy functions directly to staging, and open http://localhost:3000 to verify changes.