Nuxt.js is a special type of beast because it is a universal framework - having part of your code run server-side and the same (or a different) piece of code run in the browser.
The concept explained for Nuxt.js below roughly translates to other universal frameworks, like Next.js as well.
How does this relate to the Flamelink SDK?
• The Flamelink SDK uses Firebase under the hood to query your project's database(s), storage, etc.
• Firebase provides 2 SDK's for working with your content: one for server-side (firebase-admin) and one for client-side (firebase)
Even though it is possible to use the firebase
client SDK on the server, it is limited in what it can do because it is not intended to run in a trusted environment like a server. One of these limitations is that you cannot access anything from your storage buckets. The firebase-admin
SDK solves this problem - it lets you access a Storage Bucket server-side.
The flamelink
SDK will try its best to work with either of the 2 Firebase SDK's.
Implementation
For your Nuxt.js implementation, this means you need to provide the Flamelink SDK with an instance of a firebase-admin
app when the code runs on your server and an instance of a firebase
client app when it runs in a browser.
Luckily, Nuxt.js provides a flag, process.server
, which we can use to check when the code is running server-side. To further complicate it a bit, especially when running in dev
mode, your Nuxt.js code can run numerous times, and the Firebase SDK will not allow you to initialize the same Firebase app multiple times. The duplicate app instance problem is luckily easy to fix by first checking if an app instance exists before creating a new one.
To initialize a firebase-admin
instance, you typically use a service account. To initialize a firebase
client instance, you use the application configuration options found in the Firebase console. Since the firebase-admin
app uses a service account, it bypasses any security rules set on either of your databases or storage bucket and instead uses roles assigned to your particular service account. On the other hand, when using the firebase
client app in a browser, it is subject to these security rules. If your security rules specify that a user needs to be authenticated to read/write from a specific collection, you will need to ensure the user logs in first using Firebase Auth. If you don't want your users to have to auth before reading specific data, update your security rules to allow for that.
Code Example
import * as flamelink from 'flamelink/app'
import 'flamelink/content'
import 'flamelink/storage'
import 'flamelink/settings'
import 'flamelink/users'
import 'flamelink/navigation'
export default ({ app }) => {
let firebaseApp
if (process.server) {
const admin = require('firebase-admin')
if (!admin.apps.length) {
const serviceAccount = require(process.env
.FLAMELINK_PATH_TO_SERVICE_ACCOUNT)
firebaseApp = admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: process.env.FLAMELINK_DB_URL,
storageBucket: process.env.FLAMELINK_STORAGE_BUCKET
})
} else {
firebaseApp = admin.app()
}
} else {
const firebase = require('firebase/app')
require('firebase/auth')
require('firebase/database') // either `database` or `firestore`
require('firebase/firestore')
require('firebase/storage')
if (!firebase.apps.length) {
firebaseApp = firebase.initializeApp({
apiKey: process.env.FLAMELINK_API_KEY,
authDomain: process.env.FLAMELINK_AUTH_DOMAIN,
databaseURL: process.env.FLAMELINK_DB_URL,
projectId: process.env.FLAMELINK_PROJECT_ID,
storageBucket: process.env.FLAMELINK_STORAGE_BUCKET,
messagingSenderId: process.env.FLAMELINK_MESSAGING_SENDER_ID
})
} else {
firebaseApp = firebase.app()
}
}
app.flamelink = flamelink({ firebaseApp, dbType: 'cf' })
}
In summary
Make sure you initialize a firebase-admin
app when your code runs server-side and a firebase
client app when it runs in the browser. Pass these app instances into the Flamelink SDK as firebaseApp
and set your dbType
to either "rtdb"
or "cf"
if you use the Real-time DB or Cloud Firestore respectively. Then you can use the flamelink
app instance to query your content, navigation, storage, etc.