Deploy to Firebase App Hosting with a Next.js app

1. Before you begin

In this codelab, you'll learn how to deploy to Firebase App Hosting using a Next.js web app called Friendly Eats, which is a website for restaurant reviews.

Friendly Eats web app

The completed web app offers useful features that demonstrate how Firebase can help you build Next.js apps.

  • Automatic build and deploy: This codelab shows you how to use Firebase App Hosting to automatically build and deploy your Next.js code every time you push to a configured branch.
  • Sign-in and sign-out: The completed web app lets users sign in/out with Google. User login and persistence is managed entirely through Firebase Authentication.
  • Images: The completed web app lets signed-in users upload restaurant images. Image assets are stored in Cloud Storage for Firebase. The Firebase JavaScript SDK provides a public URL to uploaded images. This public URL is then stored in the relevant restaurant document in Cloud Firestore.
  • Filters: The completed web app lets signed-in users filter the list of restaurants based on category, location, and price. You can also customize the sorting method used. Data is accessed from Cloud Firestore, and Firestore queries are applied based on the filters used.
  • Reviews: The completed web app lets signed-in users post reviews of restaurants that consist of a star rating and a text-based message. Review information is stored in Cloud Firestore.
  • Review summaries: The completed web app automatically summarizes reviews using a Gemini model. AI-generated summaries are stored in Cloud Firestore.

Prerequisites

  • Knowledge of Next.js and JavaScript

What you'll learn

  • How to use Firebase with the Next.js App Router and server-side rendering
  • How to authorize calls to the Gemini API using server-side only Secrets

What you'll need

  • A browser of your choice, such as Google Chrome
  • Access to IDX.dev (a web-based workspace)
  • A Google account for the creation and management of your Firebase project
  • A GitHub account (it doesn't need to be the same email account as the above)

2. Set up your development environment and GitHub repository

This codelab provides the app's starter codebase and relies on the Firebase CLI and IDX.dev.

Create a new GitHub repository and import it into IDX

Firebase App Hosting allows you to set up a GitHub repository so that it builds and deploys your Next.js code every time you push to a configured branch.

  1. Create a new GitHub repository for this codelab: https://github.com/new. Name it anything you'd like, for example MyFriendlyEatsCodelab.
  2. Copy your new repository URL. It will look like this:
    https://github.com/USER_NAME/REPOSITORY_NAME.git
  3. Go to https://idx.google.com and sign in.
  4. Click Import a repo and paste in your copied GitHub URL.
    IDX will prompt you to link to GitHub, then it will clone your (empty) repository.

View the codelab's source code repository

View the codelab source at https://github.com/firebase/friendlyeats-web. The friendlyeats-web repository contains sample projects for multiple platforms.

This codelab that you're working through focuses only on Firebase App Hosting and the Gemini API, and it's a shortened version of the full codelab "Integrate Firebase with a Next.js App". This shortened codelab requires that you only work with the source code in the #io-connect branch of the friendlyeats-web repository, specifically the nextjs-step10 directory.

Take note of the following additional directories of the friendlyeats-web repository. Even though you don't need these directories for this codelab, it's helpful to know what they are.

Copy the codelab source into your new repository

Here's how to copy the nextjs-step10 directory into your own repository:

  1. In IDX, open up the terminal using Menu > Terminal > New Terminal.
  2. Use the giget npm package to fetch only the nextjs-step10 directory from the io-connect branch:
    npx giget@latest gh:firebase/friendlyeats-web/nextjs-step10#io-connect . --force
    
  3. Track changes locally with git:
    git add -A
    git commit -m "codelab starting point"
    git branch -M main
    git push -u origin main
    

You should now see the starter code in your GitHub repository.

3. Review the starter codebase

In this section, you'll review a few areas of the app's starter codebase to which you'll add functionality in this codelab.

Folder and file structure

The following table contains an overview of the folder and file structure of the app:

Folders and files

Description

src/components

React components for filters, headers, restaurant details, and reviews

src/lib

Utility functions that aren't necessarily bound to React or Next.js

src/lib/firebase

Firebase-specific code and Firebase configuration

public

Static assets in the web app, like icons

src/app

Routing with the Next.js App Router

src/app/restaurant

An API route handler

package.json and package-lock.json

Project dependencies with npm

next.config.js

Next.js-specific configuration (server actions are enabled)

jsconfig.json

JavaScript language-service configuration

Server and client components

The app is a Next.js web app that uses the App Router. Server rendering is used throughout the app. For example, the src/app/page.js file is a server component responsible for the main page. The src/components/RestaurantListings.jsx file is a client component denoted by the "use client" directive at the beginning of the file.

Import statements

In some files, you might notice import statements like the following:

import RatingPicker from "@/src/components/RatingPicker.jsx";

The app uses the @ symbol to avoid clunky relative import paths and is made possible by path aliases.

Firebase-specific APIs

All Firebase API code is wrapped in the src/lib/firebase directory. Individual React components then import the wrapped functions from the src/lib/firebase directory, rather than importing Firebase functions directly.

Mock data

Mock restaurant and review data is contained in the src/lib/randomData.js file. Data from that file is assembled in the code in the src/lib/fakeRestaurants.js file.

4. Set up your Firebase project

In this section, you'll set up a Firebase project and associate a Firebase web app with it. You'll also set up the Firebase services used by the sample web app.

Create a Firebase project

  1. Sign into the Firebase console using the same Google Account you used in the previous step.
  2. Click the button to create a new project, and then enter a project name (for example, FriendlyEats Codelab).
  3. Click Continue.
  4. If prompted, review and accept the Firebase terms, and then click Continue.
  5. (Optional) Enable AI assistance in the Firebase console (called "Gemini in Firebase").
  6. For this codelab, you do not need Google Analytics, so toggle off the Google Analytics option.
  7. Click Create project, wait for your project to provision, and then click Continue.

Upgrade your Firebase pricing plan

To use Firebase App Hosting and Cloud Storage for Firebase, your Firebase project needs to be on the pay-as-you go (Blaze) pricing plan, which means it's linked to a Cloud Billing account.

  • A Cloud Billing account requires a payment method, like a credit card.
  • If you're new to Firebase and Google Cloud, check if you're eligible for a $300 credit and a Free Trial Cloud Billing account.
  • If you're doing this codelab as part of an event, ask your organizer if there are any Cloud credits available.

To upgrade your project to the Blaze plan, follow these steps:

  1. In the Firebase console, select to upgrade your plan.
  2. Select the Blaze plan. Follow the on-screen instructions to link a Cloud Billing account to your project.
    If you needed to create a Cloud Billing account as part of this upgrade, you might need to navigate back to the upgrade flow in the Firebase console to complete the upgrade.

5. Create an App Hosting backend

In this section, you'll set up an App Hosting backend to watch a branch on your git repository. You'll also configure all the services that the backend will be talking to.

By the end of this section, you'll have an App Hosting backend connected to your repository in GitHub that will automatically re-build and roll out a new version of your app whenever you push a new commit to your main branch.

Create a backend

  1. In the Firebase console, navigate to the App Hosting page:The zero state of the App Hosting console, with a 'Get Started' button
  2. Click Get started to start the backend creation flow.
  3. Follow the prompts to import and connect the GitHub repository you created earlier.
  4. Set deployment settings:
    • Keep the root directory as /
    • Set the live branch to main
    • Enable automatic rollouts
  5. Name your backend friendlyeats-codelab (or a backend name of your choice). This becomes part of the domain used to access the backend.
    This workflow also automatically creates a Firebase Web App in your Firebase project. Later in this codelab, you'll use the configuration values of this Web App to connect your codebase to your Firebase project.
  6. Click Finish and deploy. After a moment, you'll be taken to a new page where you can see the status of your new App Hosting backend!
  7. From the App Hosting dashboard, copy your new domain.
    It'll have a pattern like BACKEND_ID--PROJECT_ID.REGION.hosted.app. You'll need this domain to set up Firebase Authentication later.

It might take a few minutes for the domain to begin working due to DNS propagation and SSL cert creation. While your backend is being created, continue on to setting up the rest of the Firebase project and configuring your backend (next steps of this codelab).

Every time you push a new commit to the main branch of your GitHub repository, you'll see a new build and rollout begin in the Firebase console, and your site will automatically update once the rollout completes.

6. Set up other Firebase services

Even though this codelab focuses only on Firebase App Hosting and the Gemini API, the working web app requires other Firebase services to function. The code to make all these services work in your app are part of the codebase you copied into your own GitHub repo, but you still need to set up these services in your Firebase project.

Set up Authentication

  1. In the Firebase console, navigate to Authentication.
  2. Click Get started.
  3. In the Additional providers column, click Google > Enable.
    1. In the Public-facing name for project text box, enter a name, such as My FriendlyEatsCodelab app.
    2. From the Support email for project drop-down, select your email address.
    3. Click Save.
  4. Click the Settings tab in the Authentication page.
    1. Click Authorized Domains from the left-side menu in the screen.
    2. Click Add Domain, and then add your newly-created App Hosting domain (it ends with .hosted.app).
    3. Click Add to save.

Set up Cloud Firestore

  1. In the left-panel of the Firebase console, expand Build and then select Firestore database.
  2. Click Create database.
  3. Leave the Database ID set to (default).
  4. Select a location for your database, then click Next.
    For a real app, you want to choose a location that's close to your users.
  5. Click Start in test mode. Read the disclaimer about the security rules.
    Later in this codelab, you'll add Security Rules to secure your data. Do not distribute or expose an app publicly without adding Security Rules for your database.
  6. Click Create.

Set up Cloud Storage for Firebase

  1. In the left-panel of the Firebase console, expand Build and then select Storage.
  2. Click Get started.
  3. Select a location for your default Storage bucket.
    Buckets in US-WEST1, US-CENTRAL1, and US-EAST1 can take advantage of the "Always Free" tier for Google Cloud Storage. Buckets in all other locations follow Google Cloud Storage pricing and usage.
  4. Click Start in test mode. Read the disclaimer about the security rules.
    Later in this codelab, you'll add security rules to secure your data. Do not distribute or expose an app publicly without adding Security Rules for your Storage bucket.
  5. Click Create.

7. Configure your Web App

Now that you've created a Firebase project and enabled all the Firebase services used in your app, you're ready to start working in IDX to configure your web app to use those services.

Log into the Firebase CLI within IDX

IDX already has Node.js and the Firebase CLI installed, so you can skip their installation and just start setting up the CLI.

  1. In the terminal within IDX, run these commands to configure the CLI to use the Firebase project you created earlier:
    firebase login --no-localhost
    firebase use --add
    
    When prompted for an alias, enter codelab.
  2. Depending on whether you want Firebase to collect data, enter Y or N. Either option works for this codelab.
  3. In your browser, select your Google account, and then click Allow.

Deploy Security Rules and indexes

The code you copied into your GitHub repo already has sets of security rules for Firestore (in firestore.rules) and for Cloud Storage for Firebase (in storage.rules). After you deploy the Security Rules, the data in your database and your bucket are better protected from misuse.

You can also use the CLI to deploy a set of indexes for Firestore (in firestore.indexes.json) to enable advanced queries.

  1. In the terminal within IDX, run this command to deploy these Security Rules and indexes:
    firebase deploy --only firestore,storage
    
  2. If you're asked: "Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?", press Enter to select Yes.

Add your Firebase configuration to your web app code

  1. In the Firebase console, do the following:
    1. Navigate to your Project settings.
    2. Scroll down to the Your Apps section, and then select the app with the same name as your App Hosting backend.
    3. Under SDK setup and configuration, choose the Config option, then copy the firebaseConfig variable's properties and their values.
  2. In IDX, do the following:
    1. Open the apphosting.yaml file. This is where you'll setup your environment variables on App Hosting, as well as secrets and runtime configuration.
    2. Fill in the provided environment variable values with the configuration values you copied from the Firebase console.For example (replace with your own values):
      runConfig:
          minInstances: 0
          maxInstances: 2
      env:
          # Get these values from the Firebase console
          - variable: NEXT_PUBLIC_FIREBASE_API_KEY
              value: xxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxx
          - variable: NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
              value: project-id.firebaseapp.com
          - variable: NEXT_PUBLIC_FIREBASE_PROJECT_ID
              value: project-id
          - variable: NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET
              value: project-id.firebasestorage.app
          - variable: NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
              value: 111111111111
          - variable: NEXT_PUBLIC_FIREBASE_APP_ID
              value: 1:111111111111:web:aaaaaaaaaaaaaaaaaaaaaa
      
    3. Save the file. Then, in the terminal within IDX, run these commands to push the changes to GitHub:
      git commit -a -m "Setup Firebase Config"
      
      git push
      
  3. Go back to the Firebase console, and navigate back to the App Hosting page, and then do the following:
    1. Click View Dashboard for your backend.
    2. Observe that a new build has been triggered from your git push! This should take around 3 minutes to finish building and rolling out to Cloud Run. You can monitor its progress by clicking the build-ID chip.
    3. Refresh the console page to check if the rollout has finished. Once it completes, click the link for your domain (ending in .hosted.app) under domains to open it up and view the newly-deployed app!

Congrats, you've deployed the initial web app! Let's dig in a bit more.

8. Try out the web app in a browser

Verify you can login with Firebase Authentication

  1. In your browser, refresh the page displaying your web app.
  2. Click Sign in with Google.
  3. Sign out and sign in again. The page updates in real-time without a page refresh. You can repeat this step with different users.
  4. Optional: In your browser, refresh the web app. Right-click the web app, select View page source, and search for the display name. It appears in the raw HTML source returned from the server.

View restaurant information

The web app includes mock data for restaurants and reviews.

To insert mock restaurant data into your Cloud Firestore database, select 2cf67d488d8e6332.png > Add sample restaurants.

Verify that the restaurant listings load at server run time

Using the Next.js framework, it might not be obvious when data is loaded at server run time or client-side run time.

To verify that restaurant listings load at server run time, follow these steps:

  1. In the web app, open DevTools and disable JavaScript.Disable JavaScipt in DevTools
  2. Refresh the web app. The restaurant listings still load. Restaurant information is returned in the server response. When JavaScript is enabled, the restaurant information is hydrated through the client-side JavaScript code.
  3. In DevTools, re-enable JavaScript.
  4. In the web app, select 27ca5d1e8ed8adfe.png > Add sample restaurants. If your snapshot function is implemented correctly, the restaurants appear in real-time without a page refresh.

Add reviews for a restaurant

To add a review and verify that it's inserted into Cloud Firestore, follow these steps:

  1. Refresh the web app, and select a restaurant from the home page.
  2. On the restaurant's page, click 3e19beef78bb0d0e.png.
  3. Select a star rating.
  4. Write a review.
  5. Click Submit. Your review appears at the top of the list of reviews.

9. Summarize restaurant reviews with generative ai

In this section, you'll add a review summary feature so that a user can quickly understand what everyone thinks of a restaurant without having to read every review.

Store a Gemini API key in Cloud Secret Manager

App Hosting integrates with Cloud Secret Manager to allow you to store sensitive values like API keys securely.

  1. To use the Gemini API, you'll need an API key. Create a key in Google AI Studio.
    When prompted, select the same project that you've been using for this codelab (behind the scenes, a Firebase project is a Google Cloud project).
  2. In the terminal within IDX, run this command to create a new secret:
    firebase apphosting:secrets:set gemini-api-key
    
  3. When prompted for the secret value, copy and paste your Gemini API key from Google AI Studio.
  4. If you're asked: "To use this secret, your backend's service account must be granted access. Would you like to grant access now?", press Enter to select Yes.
  5. When asked if the new secret should be added to apphosting.yaml, enter Y to accept, then press Enter to select GEMINI_API_KEY as the environment variable name.

Your Gemini API key is now stored securely in Cloud Secret manager, and is accessible to your App Hosting backend. You can also view the value in the Secrets Manager Dashboard in the Google Cloud Console.

  1. Open the apphosting.yaml file and note that your secret's name, was recorded, but not the values.It should look like the following:
    runConfig:
        minInstances: 0
        maxInstances: 2
    env:
        # Get these values from the Firebase console
        - variable: NEXT_PUBLIC_FIREBASE_API_KEY
            value: xxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxx
        - variable: NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
            value: project-id.firebaseapp.com
        - variable: NEXT_PUBLIC_FIREBASE_PROJECT_ID
            value: project-id
        - variable: NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET
            value: project-id.firebasestorage.app
        - variable: NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
            value: 111111111111
        - variable: NEXT_PUBLIC_FIREBASE_APP_ID
            value: 1:111111111111:web:aaaaaaaaaaaaaaaaaaaaaa
        - variable: GEMINI_API_KEY
            secret: gemini-api-key
    

Implement the review summary component

  1. In IDX, open src/components/Reviews/ReviewSummary.jsx.
  2. Replace the GeminiSummary function with the following code:
    export async function GeminiSummary({ restaurantId }) {
        const { firebaseServerApp } = await getAuthenticatedAppForUser();
        const reviews = await getReviewsByRestaurantId(
            getFirestore(firebaseServerApp),
            restaurantId
        );
    
        const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
        const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash",
        safety_settings: [
            {
            category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
            threshold: HarmBlockThreshold.BLOCK_NONE,
            },
        ],
        });
        const reviewSeparator = "@";
        const prompt = `
            Based on the following restaurant reviews,
            where each review is separated by a '${reviewSeparator}' character,
            create a one-sentence summary of what people think of the restaurant.
    
            Here are the reviews: ${reviews.map(review => review.text).join(reviewSeparator)}
        `;
    
        try {
            const result = await model.generateContent(prompt);
            const response = await result.response;
            const text = response.text();
    
            return (
                <div className="restaurant__review_summary">
                    <p>{text}</p>
                    <p> Summarized with Gemini</p>
                </div>
            );
        } catch (e) {
            console.error(e);
            return <p>Error contacting Gemini</p>;
        }
    }
    
  3. In the terminal within IDX, run these commands to create a commit and push it to your GitHub repository.
    git commit -a -m "Use AI to summarize reviews"
    
    git push
    
  4. In the Firebase console, open the App Hosting page, and wait for your new rollout to complete.
  5. In your browser, click a restaurant card. At the top of the screen, you should see a one-sentence summary of all the reviews for the restaurant.
  6. Add a new review and refresh the page. You should see the summary change.

10. Conclusion

Congratulations! You learned how to use Firebase App Hosting to deploy a Next.js app and use the Gemini API to summarize text. Specifically, you used the following:

  • Firebase App Hosting to automatically build and deploy your Next.js code every time you push to a configured GitHub branch.
  • Cloud Secret Manager (integrated with App Hosting) to securely store your Gemini API key so that you can build generative AI features in your app.

Learn more

Dig into the full codelab "Integrate Firebase with a Next.js app" to learn how we added Firebase Authentication, Cloud Firestore, and Cloud Storage for Firebase to this app.

Also, check out more codelabs: