- Published on
Deploy Next Js App with Server-side Rendering (SSR) to Firebase at ~0$ cost
- Authors
- Name
- Haythem Chibani
- @haythem_chibani
Using Next.Js
comes with plenty of usefull features one of which is Server-side Rendering
that offers us extremely fast loading speed , improves user experience
and ofcourse it helps search engines
to easily index & crawl content . But to be able to do that our Next.Js App needs a server to handle server rendering. So in this Article , I will demonstrate how to deploy a Next.Js app with SSR to firebase
using cloud function
& firebase hosting
.
Bootstrapping our Application
npx create-next-app firebase_example
Now lets update our pages/index.js with the following code :
export default function Home(props) {
return (
<div
style={{
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
{props.ssrWorking ? <h1>SSR Working 🔥!</h1> : <h1>SSR NOT WORKING !</h1>}
</div>
);
}
export async function getServerSideProps() {
return {
props: { ssrWorking: true },
};
}
What we did here is calling getServerSideProps
function and passing ssrWorking
prop to our Page , now we should be able to tell if SSR is going to be working when deployed to production .
Prepare our firebase Project :
We go straight to firebase Console Select Add project
and name it firebase-example

Select continue for step 2 and step 3 and click on create Project
. The following page appears confirming the project is successfully setup ♨.
Next we need to upgrade it to Blaze
(Pay as you go) Plan in order to use cloud Function Functionality. This is the only configuration we need on the firebase console.
Firebase setup for our Next js App
Now we go back to our Next.js Project. We start by installing the firebase tools to be able to run firebase CLI commands.
npm install -g firebase-tools
Then we connect our Next.js project with the firebase project we just created by the following command.
firebase login
Now we have access to all the firebase projects associated with the login account. We now initialize firebase on our project using
firebase init

- Select Hosting configuration for now , we will add functions manually in the next step 1
- Select existing projects as we have already created project through firebase console.
- Select the project we just created on the console.
- Select public and No for subsequent questions.
Firebase functions Configuration
Now we edit our firebase.json
file to our requirements as follows :
{
"hosting": {
"public": "public",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"rewrites": [
{
"source": "**",
"function": "nextServer"
}
]
},
"functions": {
"source": ".",
"runtime": "nodejs16"
}
}
public
defines the files in our project directory that should be deployed and ignore
defines the files that should be ignored during deployment.
We include the rewrite rule in the case if the request to files or directories through URL doesn’t exist on the public folder. In such a case we execute nextServer cloud function
to determine the response.
source
indicates the location of our nextServer function.
runtime
indicates the Node.js runtime version
to run our nextServer function.
Cloud function Setup
We will be creating our custom Server in function.js
in the Root of project .
const { https } = require("firebase-functions");
const { default: next } = require("next");
const isDev = process.env.NODE_ENV !== "production";
const server = next({
dev: isDev,
//location of .next generated after running -> npm run build !
conf: { distDir: ".next" },
});
const nextjsHandle = server.getRequestHandler();
exports.nextServer = https.onRequest((req, res) => {
return server.prepare().then(() => nextjsHandle(req, res));
});
Here we are checking if we are running the application in a development
or production
environment to later provide the information to the next function and then we connect our custom Server
to our Next.js Application by providing the location of .next
folder generated after running npm run build command in our root Next.js application to the conf
option of the next function.
server.getRequestHandler
returns a request handler which we can use to parse all HTTP requests
.
server.prepare
makes our Next.js build code(.next) ready to run on our custom server for handling SSR
.
Preparing for deployment
First of all let’s delete the public/index.html
file generated when we ran firebase init
Right after that let’s install our dependencies running :
npm i firebase-admin firebase-functions cross-env
Now we’ll be configuring our package.json
:
{
"name": "firebase_example",
"version": "0.1.0",
"private": true,
"main": "function.js",
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"deploy": "next build && cross-env NODE_ENV=production firebase deploy --only functions,hosting"
},
"dependencies": {
"cross-env": "^7.0.3",
"firebase-admin": "^11.3.0",
"firebase-functions": "^4.1.0",
"next": "13.0.4",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"eslint": "8.28.0",
"eslint-config-next": "13.0.4"
}
}
Here we added our function file function.js
on the main
key and added our deployment script to Build and Deploy ✌.
Deployment
Now everything is setup and we are ready to deploy our Application
npm run deploy

Everything works great 😍 we can simply now access our hosted App with the link provided in the console 🔥
CI/CD configuration
For the next part we’re going to be setting up our github actions for continuous integration & deployment .

In the firebase console we navigate to Project settings and then we go to Service accounts so we can generate our private key
, now we have downloaded a json file containing our access config .
Lets copy the content of the json file and add it as a github secret
named FIREBASE_SERVICE_ACCOUNT
.
Now we are good to go straight and create our github actions
Let’s create a folder named .github
and add 2 files inside
name: Deploy to Firebase Hosting on PR
'on': pull_request
jobs:
build_and_deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm ci && npm run build
- uses: www-norma-dev/firebase-hosting-functions-deploy@main
with:
repoToken: ${{ secrets.GITHUB_TOKEN }}
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }}
projectID: fir-example-11ebb
name: Deploy to Firebase Hosting on main merge
'on':
push:
branches:
- main
jobs:
build_and_deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm ci && npm run build
- uses: www-norma-dev/firebase-hosting-functions-deploy@main
with:
repoToken: ${{ secrets.GITHUB_TOKEN }}
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT }}
projectID: fir-example-11ebb
channelId: live
The first github action deploys our PR
to a preview channel
that expires in 7days and comments the URL on the PR .
The second github actions deploys our App on Live channel
when we merge a PR to the main
branch .
Don’t forget to update the project ID
with yours ( available in firebase console Project settings under general settings . )
We now have our project setup for manual deployment running npm run deploy
command as well as a CI/CD Pipeline
to handle our PRs and production on main branch merge .
Thats it for today 😀, we now have a Next.Js App deployed to firebase hosting with cloud function to handle Server-side Rendering , with this approach you can use Next.Js to its full potential including Incremental-static-regenration
as well as API-routes
, Goodluck on your journey and happy coding 👊