
Nuxt.js (v1), Firestore & SSR 🔥
This article will help you integrate Firebase Firestore into a Nuxt.js project while keeping the server-side rendering capabilities that come with the amazing Universal SSR mode of Nuxt.js.
And all of this without the need for any additional libraries other than Google’s own Firebase SDK.
❗️️ NEWER ARTICLE! This article is based on Nuxt.js Version 1.x. If you are working with the newer Nuxt 2.0, check out this article:
https://medium.com/@pascalluther/nuxt-js-v2-firestore-ssr-938d8fb7d2b0
1) Install Nuxt.js
⏭ skip to section 2 if you already have a Nuxt.js project running ⏭
First, install the vue-cli if you haven’t already:
npm install -g @vue/cli @vue/cli-initThen, for the sake of simplicity, install the Nuxt.js starter template with the following command:
vue init nuxt-community/starter-template <project-name>❗️️ Make sure to replace “<project-name>” with your project-name!
After following the installation instruction you should be able to run your project and see the following:

2) Install the Firebase SDK
⏭ skip to section 3 if you already have the Firebase SDK installed ⏭
Now let’s install the Firebase SDK. Do this with the following command:
npm install firebase --saveThis is all the dependencies you will need. In your packages.json file you should see the below:
"dependencies": {
"firebase": "^5.4.2",
"nuxt": "^1.0.0"
},The starter template comes with Nuxt v.1.0.0. Change that to ^1.4.2 or higher and then run npm install to update to a more recent version, just for the sake of not using a rather old version.
❗️️️️ but don’t update to Nuxt 2+since this article doesn’t cover that
This article was written with the following two versions:
"dependencies": {
"firebase": "^5.4.2",
"nuxt": "^1.4.2"
},3) Initiate the Firebase SDK
Now let’s finally write some code. 🎉
We want to make sure that the Firebase SDK is initiated on the server, so the server can get data from Firestore and render it before it gets sent to the client.
In your /plugins folder, create a file called firebase.js and add the following code:
import firebase from 'firebase/app'
import 'firebase/firestore'
if (!firebase.apps.length) {
const config = {
apiKey: '<replace this>',
authDomain: '<replace this>',
databaseURL: '<replace this>',
projectId: '<replace this>',
storageBucket: '<replace this>',
messagingSenderId: '<replace this>'
}
firebase.initializeApp(config)
firebase.firestore().settings({timestampsInSnapshots: true})
}
const fireDb = firebase.firestore()
export {fireDb}❗️️ Make sure to replace “<replace this>” with your Firebase credentials. I will refrain from explaining how to setup a Firebase project and getting the credentials, since this is well documented in the Firebase docs here.
Now we add the plugin to our nuxt.config.js like so:
plugins: [
'~/plugins/firebase.js'
],4) Write to Firestore
Now we can already write something to Firestore! 🤩
Delete all content in your pages/index.vue file and replace it with the following:
<template>
<section class="container"> <div>
<h2>
Write to Firestore.
</h2>
<div>
<button @click="writeToFirestore" :disabled="writeSuccessful">
<span v-if="!writeSuccessful">Write now</span>
<span v-else>Successful!</span>
</button>
</div>
</div> </section>
</template>
<script>
import {fireDb} from '~/plugins/firebase.js'
export default {
data() {
return {
writeSuccessful: false
}
},
methods: {
async writeToFirestore() {
const ref = fireDb.collection("test").doc("test")
const document = {
text: "This is a test message."
}
try {
await ref.set(document)
} catch (e) {
// TODO: error handling
console.error(e)
}
this.writeSuccessful = true
}
}
}
</script>
<style>
.container {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
</style>
Your app should now look like this:

When clicking on “Write now”, the button should change to “Successful!” and there should be a collection “test” with a document named “test” in your Firestore database:

❗️️ If this did not work, make sure your project and Firestore is set up properly. You might have to setup an instance of Firestore first. Also, make sure that your security rules are defined as public (but change that later on!).
5) Read from Firestore
Now let’s read what we wrote to the Firestore!
Add a second <div> below the “Write to Firestore”-Div like so:
<div>
<h2>
Read from Firestore.
</h2>
<div>
<button @click="readFromFirestore" :disabled="readSuccessful">
<span v-if="!readSuccessful">Read now</span>
<span v-else>Successful!</span>
</button>
<p>{{text}}</p>
</div>
</div>Add the attributes readSuccessful and text to your data, so it looks like this:
data() {
return {
writeSuccessful: false,
readSuccessful: false,
text: ""
}
},And finally add a method to read the data from Firestore like below:
async readFromFirestore() {
const ref = fireDb.collection("test").doc("test")
let snap
try {
snap = await ref.get()
} catch (e) {
// TODO: error handling
console.error(e)
}
this.text = snap.data().text
this.readSuccessful = true
}Now try it out!
After clicking both buttons, your app should look like this:

That’s it. You can now already read and write to Firebase Firestore with Nuxt.js!
But wait… that is a client side request to Firestore. 😱 That has nothing to do with SSR.
Well, read on.
6) Server-side Rendering (SSR)
If you want your page to render the data from Firestore already on server-side, simply do it as you are used to with Nuxt.js —by adding an asyncData function (more Infos here):
async asyncData({app, params, error}) {
const ref = fireDb.collection("test").doc("test")
let snap
try {
snap = await ref.get()
} catch (e) {
// TODO: error handling
console.error(e)
}
return {
text: snap.data().text
}
},That’s already it! We successfully implemented Nuxt.js with Firebase Firestore! 🎉🎉
Additional Content
Entire index.vue:
<template>
<section class="container">
<div>
<h2>
Write to Firestore.
</h2>
<div>
<button @click="writeToFirestore" :disabled="writeSuccessful">
<span v-if="!writeSuccessful">Write now</span>
<span v-else>Successful!</span>
</button>
</div>
</div>
<div>
<h2>
Read from Firestore.
</h2>
<div>
<button @click="readFromFirestore" :disabled="readSuccessful">
<span v-if="!readSuccessful">Read now</span>
<span v-else>Successful!</span>
</button>
<p>{{text}}</p>
</div>
</div>
</section>
</template>
<script>
import {fireDb} from '~/plugins/firebase.js'
export default {
data() {
return {
writeSuccessful: false,
readSuccessful: false,
text: ""
}
},
async asyncData({app, params, error}) {
const ref = fireDb.collection("test").doc("test")
let snap
try {
snap = await ref.get()
} catch (e) {
// TODO: error handling
console.error(e)
}
return {
text: snap.data().text
}
},
methods: {
async writeToFirestore() {
const ref = fireDb.collection("test").doc("test")
const document = {
text: "This is a test message."
}
try {
await ref.set(document)
} catch (e) {
// TODO: error handling
console.error(e)
}
this.writeSuccessful = true
},
async readFromFirestore() {
const ref = fireDb.collection("test").doc("test")
let snap
try {
snap = await ref.get()
} catch (e) {
// TODO: error handling
console.error(e)
}
this.text = snap.data().text
this.readSuccessful = true
}
}
}
</script>
<style>
.container {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
</style>Links:
- See entire code on GitHub:
https://github.com/lupas/nuxt1-firestore
Thanks & Credits to:
- The amazing Nuxt.js framework
- Google Firestore
- Nuxt-Community on GitHub for the Starter Template
- Not sure anymore, but might have gotten a hint by Adriano Resende’s answer on StackOverflow, so thanks to him just in case ;-)
