Hosting a dynamic website on Firebase

Dynamic web site deployed on Firebase hosting

This page explains step by step how to configure, deploy and host a website with dynamic URLs on Firebase.

Before starting, I really struggled to write this page. The FireBase doc is not very clear. At the time I did my research, I didn't find any blog or video that clearly explained how to create dynamic URLs on FireBase. If this page helps you and saves you time, a little message or a donation, it will make me really happy !

The guide presented on this page has been tested with the following versions:

We assume that Node.js and npm are already installed. In my case, I used Volta with which you can select a Node engine when switching between projects.

If you are new to FireBase, I recommand to start by this page that explains to create a static website. Since this guide extends the previous, I strongly recommand to already understand the basics or FireBase.

Create a Firebase project

The first thing to do is to create a Firebase account and project.

As it is already explained here, I will pass quickly.

The project ID (fir-dynamic-c68ee in my case) is provided. We'll need it later, but don't worry, it is easy to retreive the ID in the Firebase console.

Firebase project home page

Create new folder on your local machine to store your project. Open a terminal an go to your new folder. Run the following command to install the Firebase package:

npm install firebase

If Firebase CLI tools are not installed yet, run the following command:

npm install -g firebase-tools

This command installs the Firebase tools globaly, so the content of your project folder should not change.

Login to your Firebase account:

$ firebase login

Hosting

The project is created in two steps:

  1. install static hosting
  2. install functions

To create and initiate the project, run the following command from your project's root directory for initiate the hosting:

firebase init hosting

The above command should display something like:

$ firebase init hosting

     ######## #### ########  ######## ########     ###     ######  ########
     ##        ##  ##     ## ##       ##     ##  ##   ##  ##       ##
     ######    ##  ########  ######   ########  #########  ######  ######
     ##        ##  ##    ##  ##       ##     ## ##     ##       ## ##
     ##       #### ##     ## ######## ########  ##     ##  ######  ########

You're about to initialize a Firebase project in this directory:

  /home/project/firebase-dynamic

=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add, 
but for now we'll just set up a default project.

? Please select an option: (Use arrow keys)
❯ Use an existing project 
  Create a new project 
  Add Firebase to an existing Google Cloud Platform project 
  Don't set up a default project 

Select Use an existing project and the Firebase project you created previously.

? Please select an option: Use an existing project
? Select a default Firebase project for this directory: fir-dynamic-c68ee (firebase-dynamic)
i  Using project fir-dynamic-c68ee (firebase-dynamic)

Few more questions are asked, here are my answers:

? What do you want to use as your public directory? public
? Configure as a single-page app (rewrite all urls to /index.html)? No
? Set up automatic builds and deploys with GitHub? No
✔  Wrote public/404.html
✔  Wrote public/index.html

A new public folder should be create with a default index.html file.

To be sure everything is properly installed, you can deploy your static part:

firebase deploy

The last line contains the public URL of your project.

Functions

The phylosophy of Firebase is that some URL will be redirected to functions. You now have to initialize Cloud Functions with the following command:

firebase init functions

Answer the questions, then the tool install the files we'll need:

? What language would you like to use to write Cloud Functions? JavaScript
? Do you want to use ESLint to catch probable bugs and enforce style? Yes
✔  Wrote functions/package.json
✔  Wrote functions/.eslintrc.js
✔  Wrote functions/index.js
✔  Wrote functions/.gitignore

Install dependencies with npm.

You should now have a new folder functions in your project directory.

Create your first function

Latter, dynamic URLs will be redirected to our function. Let's start by writing anapp function:

// Firebase functions
const functions = require("firebase-functions");

// Create an app with Express
const express = require("express");
const app = express();

// Any URL starting with /app/id will call this function
app.get("/", (req, res) => {
    res.send("This is a function");
});

// Export the app
exports.app = functions.https.onRequest(app);

To test your function, you can run firebase deploy in the command line, but we will first try it localy.

You probaly noticed that the Firebase CLI tool create a package.json file in the functions folder. Move to the functions folder, and run npm install.

To the root folder of your project, run the following command to serve your functions localy:

firebase serve

This command creates two local servers on your computer. The first one is your local hosting:

✔  hosting[fir-dynamic-c68ee]: Local server: http://localhost:5000

The link should display the default index.html in the public folder;

The second link is your functions folder:

✔  functions[us-central1-app]: http function initialized (http://localhost:5001/fir-dynamic-c68ee/us-central1/app).

This last link should display:

This is a function

Your function is working properly. Note that the /app at the end of the URL specify which function is called. Here, we just have a single function app.

From here, we have two problems:

Dynamic URLs

This is the tricky part!

To serve dynamic URL, we will edit the firebase.json file in the project root. The file should look like:

{
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  }
}

Add the following lines to specify that any URL starting with /app/ will be redirected to our app function`

{    
  "functions": [
  {
      "source": "functions",
      "codebase": "default",
      "ignore": [
          "node_modules",
          ".git",
          "firebase-debug.log",
          "firebase-debug.*.log"
      ]
    }
  ],

  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
          "source": "/app/**",
          "dynamicLinks": true,
          "function": "app"                
      }
    ]
  }
}

The first part configures the functions, the last part specifies that any URL starting with /app will be redirected to our function. Note that the first part may be add by the previous command firebase init functions.

Edit the index.js in the functions folder, and change the app.get() first parameter:

// Firebase functions
const functions = require("firebase-functions");

// Create an app with Express
const express = require("express");
const app = express();

// Any URL starting with /app/id will call this function
app.get("/app/:id", (req, res) => {
    res.send("ID = " + req.params.id);
});

// Export the app
exports.app = functions.https.onRequest(app);

In your browser, go to the root URL of your static hosting. If you didn't change the file index.html, you should have a page titled Firebase Hosting Setup Complete.

At the end of the URL, add /app/12, in my case: http://localhost:5000/app/12:

Dynamic URL redirected to Firebase functions

Note that the last parameter of the URL (12) is sent to the Express get() function.

You can now deploy your app to check it is still working once deployed.

Deploy

Functions are not working with the free plan. Check that your project is with the blaze plan. If not, you'll have to upgrade your project in the Firebase console.

Run the following command to deploy on Firebase hosting:

firebase deploy

It may take some time, especialy when creating the Node.js 18 functions. Be patient!

i  functions: creating Node.js 18 function app(us-central1)...

Note that you Node.js version may prevent the command to work properly. If necessary, change the version in the package.json file:

"engines": {
  "node": "18"
},

Once the command is over, the last line should display your public URL:

Hosting URL: https://fir-dynamic-c68ee.web.app

Go to this URL, you should have one more time your home page index.html.

As previously, add /app/7 at the end of the URL: https://fir-dynamic-c68ee.web.app/app/7

Et voila:

Dynamic web site deployed on Firebase hosting

Download

You can download the final project on Github:

Project on GitHub.

See also


Last update : 04/26/2023