Gridsome + Firebase: Starter for your next static yet dynamic site
https://github.com/u12206050/gridsome-firebase-starter
UPDATED: The Gridsome Firebase Starter now includes the
gridsome-source-firestore
to build static pages and content with data directly from Firestore.
What is Gridsome?
Gridsome is a Vue based framework for building lightning fast static websites. Using data from your CMS, Markdown or any available data API and populating a GraphQL database, Gridsome generates and builds your website based on pages and templates you create. READ MORE
The Benefit
In short we can build a highly reactive dynamic website that is statically generated. Using the reactivity of Vue and Firesync(more below) you can easily manage your Firestore subscriptions throughout your app for both public and private users, whilst having all the speed and features of a statically built site on what ever CMS/API you want.
Static & Dynamic Site?
So like myself, when I started this project, you might ask: What is the use case for using a realtime data service like Firebase’s Firestore with a static site generator like Gridsome?
In my case we have pages and content which makes sense generating static sites for, but we also have pages that are unique per user, account and order history pages. We also have parts of the static pages that have dynamic content for example comments and a list of recent articles.
So let’s build a static and dynamic site with support for Users using Firebase Authentication, Real time data using Firestore and any other functions you might need using Cloud Functions.
Getting started
I assume you already know what Firebase is and how to setup a new project.
Firebase
- Run
npm install -g firebase-tools
Firebase cli - Create your project folder
mkdir my-project
- Navigate to your project folder
cd my-project
- Run
firebase login
- Run
firebase init
Gridsome
If you don’t have Gridsome installed run npm install --global @gridsome/cli
Make sure you are inside your my-project
directory then:
- Create the Gridsome site with the
gridsome create website https://github.com/u12206050/gridsome-firebase-starter.git
- Navigate into the website folder
cd website
- Copy the
.env.example
file and rename to.env.development
- Update the
.env.development
with your firebase credentials - Run
gridsome develop
to start a local dev server athttp://localhost:8080
- Continue with the Gridsome docs to create pages and templates
Firesync store
Q: What is Firesync store?
A: Well, it consists of two files. store.js
and firesync.js
, what it is, is essentially a reactive store with a set of functions to keep your entire app or even just single components in sync with collections from Firebase’s Firestore. Let me explain:
store.js
creates a simple Vue store that you can use via this.$store
the file. Feel free to add other properties to it as you need. Properties on this simple store are reactive and can easily be updated as normal reactive properties on a local component, eg. this.$store.name = "John Doe"
However you may also define your own functions on the store
object which is what firesync.js
does and then use them as mutators or actions as you would in Vuex.
firesync.js
adds a set of functions to either the $store
object or the Vue.prototype
class, meaning to all Vue components. There is a set of three functions that are exported from firesync.js
and being used by fire.js
, which is the file that sets up the Firebase connection. These three functions are there to help you subscribe to collections based on three states within your app. Within each of these three functions you can add the subscriptions you want to add and remove. These three functions are:
onInit
Subscribe to collections as soon as a Firebase connection is established. For example, retrieve the latest headlines, messages or exchange rates.
onInit(db) {
/** Add public subscriptions here */
store.$bind(db.collection('rates'), 'rates', () => {
if (Array.isArray(store.rates)) {
store.loadedExchangeRates = true
}
})
}
onLogin
Subscribe to collections/document once a user is logged in. Useful for fetching the user’s profile and having that available on as this.$store.user
onLogin(db, uid) {
/** Add private, user only subscriptions here */
store.$bind(db.collection('users').doc(uid), 'user')
}
onLogout
Unsubscribe from the subscriptions you added in the onLogin function. You can also give a default value to update the property with.
onLogout() {
/* Unsubscribes from private subscriptions */
store.$unbind('user', null)
}
$Functions
We use the $
sign to prefix functions that are available on the `$store` and Vue scopes. On every Vue component/view you have access to the following:
this.$db
: Used for creating references and fetching data from Firestore.
const filteredDocsRef = this.$db.collection('documents').where('words', '>', 100)
this.$bind
: Bind the results of a Firestore reference to a property on the current component
this.$bind(filteredDocsRef, 'documents')
this.$unbind
: Unbinds the property on the component so it no longer gets updates. The second argument is optional, use it to update the property otherwise it stays unchanged with the last content that it had.
this.$unbind(‘documents’, [])
this.$store
A global simple store used for storing dynamic data fetched from Firestore. However you can use it to sync any data throughout your app.
this.$store.user
The same two functions are available on the global store
this.$store.$bind(ref, property, cb?)
this.$store.$unbind(property, value?)
Firebase Functions
this.$functions
: Most commonly used for creating requests to Firebase functions. Same as firebase.functions()
this.$functions.httpsCallable('getTime')().then(time => {
this.$store.currentTime = time
})
Firebase auth
this.$auth
: This is extended on the firebase.auth()
object which besides the logout()
function and currentUser
property it also has:
this.$auth.isLoggedIn
: If the user is logged in or not
this.$auth.userId
: The user id of the currently logged in user
this.$auth.roles
: An object of roles the user has been assigned
Firebase Firestore
this.$firestore
: Contains the useful field properties to use when writing to db. Some of these field properties:
new this.$firestore.GeoPoint(latitude, longitude)
Creates a new immutable GeoPoint object
new this.$firestore.Timestamp(seconds, nanoseconds)
Creates a new timestamp.
this.$firestore.FieldValue
Read more