Yes. You can deploy Nuxt on Firebase App Hosting (2024)
Tags: tutorial, nuxt, firebase, webdev
Published: 2024-06-07 00:12:46

Firebase team just announced, at [Google I/O 2024](https://youtu.be/qyhdKb8liEA), a new product to deploy fullstack web app: [Firebase App Hosting](https://firebase.google.com/docs/app-hosting?authuser=1).

Previously we had [Firebase Hosting](https://firebase.google.com/docs/hosting) which was only suitable for frontend apps:

* Types : Static Site, SPA Single Page App
* Frameworks : Vue.js, React.js, Svelte, Flutter web.

But we couldn't deploy fullstack apps (using SSR, ISR) with Firebase Hosting. It was possible to workaround this limitation using Firebase Functions. I tried it and it was not easy nor pleasant:

* There was a latency due to warm-up functions
* You have to configure the functions to serve the content (which is an additional step specific to Firebase Hosting)

Today, with Firebase App Hosting, this became a lot more easier.
Since Firebase team didn't explicitly tell if it was possible to deploy applications other than Angular and Next.js, I took the journey to deploy a Nuxt app using SSR.

<br />
**TL;DR: It's working!**
<br />

I'll assume that you have the necessary toolings to develop a Nuxt app. You need:

- [Node.js](https://nodejs.org/) installed - v18.0.0 or newer
- [A terminal](https://warp.dev/): in order to run Nuxt & Firebase commands
- A Text editor: like [VSCode](https://code.visualstudio.com/)
- [Git](https://git-scm.com/) and a [GitHub](https://github.com/) account 
(create an account if you don't already have one)

I'm using macOS with Node.js v20.13.1 (lts/iron), VSCode with the [official Vue extension](https://marketplace.visualstudio.com/items?itemName=Vue.volar), [bun](https://bun.sh/) v1.1.8.

I'll name the project nuxt-firebase. Feel free to replace that name with your your own.

<br />
<br />
## Create a Nuxt app

Let's create a Nuxt app with minimal code and SSR configuration. Than we will deploy it on the cloud.

<br />
<br />
### Initialize the repository

[(You can follow the official Nuxt documentation there).](https://nuxt.com/docs/getting-started/installation)

{% embed https://www.loom.com/share/ebfe93c5dcf04aa1897ddd3c80998153?sid=43a2aa94-1106-40aa-b9cd-4fe45bd6e9da %}

<br />
First, initialize a repository with Nuxt:

```bash
# initialize your nuxt app
npx nuxi@latest init nuxt-firebase
```
We then navigate into the created directory:

```bash
# move into your project directory
cd nuxt-firebase
```

Run the app to check that everything is okay:

```bash
# in your nuxt project directory
npm run dev -- -o
```

<br />
### Add pages and routes

We're going to edit the app.vue file and add two pages inside the /pages/ directory which does not exist yet.

{% embed https://www.loom.com/share/22d2476442ec4834a58ac5d0b316b5fb?sid=f2fdc398-54f1-4e6d-84fc-02c156da36f2 %}

Replace the content of app.vue with this one:

```vue
// app.vue
<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>

  <footer>
    <div class="link-bar">
      <NuxtLink to="/">Home</NuxtLink>
      <NuxtLink to="/about">About</NuxtLink>
    </div>
  </footer>
</template>

<style>
footer {
  position: fixed;
  bottom: 24px;
  display: flex;
  justify-content: center;
  align-items: center;

  left: 0;
  right: 0;
  padding: 10px;
  text-align: center;
}

.link-bar {
  display: flex;
  justify-content: center;
  gap: 1rem;

  padding: 0.5rem;
  border-radius: 0.5rem;
  
  border: 1px solid #FFE6E6;
  box-shadow: 0 0 10px #FFE6E6;
  position: relative
}

</style>
```

Create the `/pages/` folder at the root of your project's directory. Inside, add these two files:

**index.vue:**

```vue
// pages/index.vue
<template>
<h1>Index</h1>
</template>
```

**about.vue:**

```vue
// pages/about.vue
<template>
<h1>About</h1>
</template>
```

You should see something like this in your browser:


![Nuxt basic project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0nvuw9ji3jxc3us7h61c.png)

It's very basic. You can customize your pages but for our demo it's good enough.

<br />
### Configure Rendering Modes

By default, Nuxt uses SSR in development mode, but switches to client-side rendering in production (for example, static rendering).

We need to configure our app routes to explicitly tell Nuxt to use SSR for our pages in `nuxt.config.ts`:

```ts
// nuxt.config.ts
// --------------
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  devtools: { enabled: true },
  routeRules: {
    '/': { ssr: true },
    '/about': { ssr: true },
  },
})

```

Now when we'll deploy our app on Firebase App Hosting, the routes `/` and `/about` will be serve through server side rendering (SSR).

For our own knowledge, here is an example of a config rendering rules with their purpose:

```ts
// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // Homepage pre-rendered at build time
    '/': { prerender: true },
    // Products page generated on demand, revalidates in background, cached until API response changes
    '/products': { swr: true },
    // Product page generated on demand, revalidates in background, cached for 1 hour (3600 seconds)
    '/products/**': { swr: 3600 },
    // Blog posts page generated on demand, revalidates in background, cached on CDN for 1 hour (3600 seconds)
    '/blog': { isr: 3600 },
    // Blog post page generated on demand once until next deployment, cached on CDN
    '/blog/**': { isr: true },
    // Admin dashboard renders only on client-side
    '/admin/**': { ssr: false },
    // Add cors headers on API routes
    '/api/**': { cors: true },
    // Redirects legacy urls
    '/old-page': { redirect: '/new-page' }
  }
})
```

An overview of routes rendering rules:


![Nuxt routes rendering rules overview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kc8yem7qmnny68xdr8ek.png)

Source: https://nuxt.com/docs/guide/concepts/rendering#route-rules

See the official documentation for more information: https://nuxt.com/docs/guide/concepts/rendering

<br />
## Push into GitHub

The final part in the code editor is to push the new code to [GitHub](https://github.com/). Thus Firebase will be able to fetch and build our app with its CI/CD.

{% embed https://www.loom.com/share/701d8dac81444ac7b203bf0a24d9f08e?sid=99495d57-4973-44e1-9a24-e13b57a610fa %}

You can see the source code here: [nuxt-firebase](https://github.com/rootasjey/nuxt-firebase)

<br />
## Deploy on Firebase App Hosting

First we need to [create a Firebase account](https://firebase.google.com/) if we don't have one. After your Firebase account has been created, you should see the welcome screen. Click on the "Create a project" button:

{% embed https://www.loom.com/share/3e6540357efa4e97ae0fb02ce2fa7c7c?sid=73011a55-422d-4021-bf25-e371a5872bc7 %}

Once created, we go on le left side bar and select "App Hosting".

You can follow the video tutorial or/and the screen by screen images with text explanations:

{% embed https://www.loom.com/share/c5a2f777651a44c786ff0b9f23e2a22b?sid=cd269e94-e8f3-4c23-8adb-ea843a41ec12 %}

App Hosting button is in the Build accordion:


![Firebase Console - Home](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gj8uzxcwhpsjbfl6dpet.png)

We arrive on the App Hosting welcome page:


![Firebase Console - App Hosting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4h1wuovl53dj0xp481di.png)

We need to upgrade our project from Spark Plan to Blaze Plan.
Our Nuxt app uses features in the Blaze Plan so we have to add a payment method. For this demo we'll pay little to nothing since our app won't consume much resources, if it has minimal traffic. Firebase products pricing - including App Hosting - is based on usage cost. Meaning that if your app get approximately 10k visits, you'll pay ~$0.15 according to the [Firebase documentation](https://firebase.google.com/docs/app-hosting/costs).


![Firebase cost usage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3xp1bv2ern710k2uf8m1.png)

NOTE: This is an example and other factors should be taken into account like: Effective Concurrency, CPU/Mem Time.

Plus there are no-cost limits which allow us to use these resources for free before being charged:


![Firebase no-cost limits](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0t8avl2klw0n37norloe.png)

After clicking on the "Upgrade project" button, a popup opens:


![Firebase Console - App Hosting - Upgrade project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ef2b0134kmujdf1ozzl4.png)

Click on "Continue".


![Firebase Console - App Hosting - Payment](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v3s2pbpvj2tj50ygpdfb.png)

We confirm our country, and enter a payment method.

Your account is now setup on the Blaze plan, now we can go to our dashboard and create a new **App Hosting** project (which will be inside our Firebase project: nuxt-firebase).

Click on "Get started" button.


![Firebase Console - App Hosting - Set up](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zfkvyl32f645uq8ucixe.png)

The configuration wizard will ask us to create access from our GitHub account to Google Developer Connect, which will be then linked to Firebase.


![Firebase Console - App Hosting - Connect GitHub](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xqmsxgta608s4c730f4a.png)

When this is done, we will be able to select our GitHub account and Nuxt app (hosted on GitHub).

Wait some minutes for the app to build. At this time, the build time is much longer than Vercel. It takes ~45 seconds on Vercel and ~3 minutes on Firebase App Hosting.

And voilà! If the build and deployment succeeded, a new link is generated with a SSL certificate. It may took some time (in minutes or hours) for the link to be functional.


![Firebase Console - App Hosting - Success](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dxdv9306lhong3g59xan.png)

You can visit the deployed [Nuxt app this new url](https://nuxt-firebase--nuxt-firebase-1f646.us-central1.hosted.app/).

The source code is on [GitHub](https://github.com/rootasjey/nuxt-firebase).

## Sources
* [Nuxt documentation](https://nuxt.com/docs/getting-started/installation)
* [Google I/O - Introducing Firebase App Hosting](https://youtu.be/qyhdKb8liEA?si=Fm0BohXjKZA7O93w)
* [Firebase App Hosting documentation](https://firebase.google.com/docs/app-hosting)