PWA - Nuxt.js

Nuxt 2 is an open-source meta-framework built on Vue that makes developing Progressive Web Apps easier. To get started using Nacelle with Nuxt, follow the quick start guide below or spin up a Nuxt accelorator project.

Nacelle’s Nuxt accelerator

While we encourage merchant developers to use create-nuxt-app to scaffold new Nacelle x Nuxt projects, Nacelle's Nuxt starter is a viable option for those who prefer a more featureful starting point than a fresh create-nuxt-app project.

To create a new Nacelle Nuxt starter project:

npx degit <https://github.com/getnacelle/nacelle-js/starters/nuxt>

Scaffold a new Nuxt project

Using create-nuxt-app and [Nuxt’s Quick Start](Nuxt’s Quick Start docs) docs

npx create-nuxt-app <project-name>

Add Nacelle's SDK

npm i @nacelle/storefront-sdk

Environment variables

These can be found in the dashboard, and the documentation is here

# .env

NACELLE_STOREFRONT_ENDPOINT="\<YOUR_NACELLE_STOREFRONT_ENDPOINT>"  
NACELLE_STOREFRONT_TOKEN="\<YOUR_NACELLE_STOREFRONT_TOKEN>"  
NACELLE_STOREFRONT_LOCALE="\<YOUR_NACELLE_STOREFRONT_LOCALE>"

MYSHOPIFY_DOMAIN="\<YOUR_MYSHOPIFY_DOMAIN>"  
SHOPIFY_STOREFRONT_CHECKOUT_TOKEN="\<YOUR_STOREFRONT_CHECKOUT_TOKEN>"  
SHOPIFY_STOREFRONT_API_VERSION="\<YOUR_STOREFRONT_API_VERSION>"

Runtime configs

// nuxt.config.js

export default {
  // ...other config,
  publicRuntimeConfig: {
    nacelle: {
      storefrontEndpoint: process.env.NACELLE_STOREFRONT_ENDPOINT,
      token: process.env.NACELLE_STOREFRONT_TOKEN,
      locale: process.env.NACELLE_STOREFRONT_LOCALE
    }
  }
}

Nacelle SDK init

Nuxt plugin docs

// plugins/nacelle-sdk.js

import { Storefront } from '@nacelle/storefront-sdk';

export default (context, inject) => {
  const client = new Storefront(context.$config.nacelle);
  inject('nacelle', client);
};
// nuxt.config.js

export default {
  // ...other config,
  plugins: ['~/plugins/nacelle-sdk.js']
}

Using asyncData

Nuxt’s asyncData docs

The asyncData hook is a perfect place to fetch data for pages. Below is an example of fetching data for a product page.

// pages/products/_handle.vue

export default {
  async asyncData({ app, params }) {
    const data = await app.$nacelle.query({ 
      query: QUERY, 
      variables: {
        handles: [params.handle]
      } 
    })
    return {
      data
    }
  }
}

const QUERY = `
  query Page($handles: [String!]){
    products(filter: { handles: [$handle] }){
      // fields to return
    }
    content(filter: { handles: [$handle]}) {
      // fields to return
    }
  }
`

Using fetch

The fetch hook is a perfect place to fetch data in components that are not pages. Below is an example of fetching data for a layout.

// layouts/default/_handle.vue

export default {
  async fetch() {
    this.data = await this.$nacelle.query({ 
      query: QUERY, 
      variables: {
        handles: ['header', 'footer']
      } 
    })
  }
}

const QUERY = `
  query Content($handles: [String!]){
    content(filter: { handles: [$handle] }){
      // fields to return
    }
  }
`

Static Generation

Nuxt’s static generation docs

Using the generate hook

Nuxt’s generate docs

To statically generate your site, Nuxt needs to be aware of all dynamic routes. Below is an example of setting up your dynamic product and collection routes for static generation.

// utils/buildRoutes.js

import { Storefront } from '@nacelle/storefront-sdk';

export const buildRoutes = async () => {
  const client = new Storefront({
    storefrontEndpoint: process.env.NACELLE_STOREFRONT_ENDPOINT,
    token: process.env.NACELLE_STOREFRONT_TOKEN,
    locale: process.env.NACELLE_STOREFRONT_LOCALE
  });
  const QUERY = `
    {
      products {
        content {
          handle
        }
      }
      productCollections {
        content {
          handle
        }
      }
    }
  `;

  const response = await client.query({ query: QUERY });
  
  return [
    ...response?.products.map(
      (product) => `/products/${product.content.handle}`
    ),
    ...response?.productCollections.map(
      (productCollection) => `/collections/${productCollection.content.handle}`
    )
  ];
};
// nuxt.config.js

import { buildRoutes } from '~/utils/buildRoutes'

export default {
  // ...other config,
  generate: {
    routes: () => buildRoutes()
  }
}