All Collections
Flamelink Documentation
Using Flamelink with Nuxt.js
Using Flamelink with Nuxt.js

How do I get Flamelink to work universally between client and server?

Engineering avatar
Written by Engineering
Updated over a week ago

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.

Did this answer your question?