Integrate Contentful in Vue 3


Integrate Contentful CMS in Vue 3, can be done using Graphql as well as the contentful library. We go with npm package.

Install the dependency by running the command yarn add contentful in terminal.

The client

We can a create client module in order to make contentful queries.

//contentdul/index.js

import {createClient} from 'contentful'

const client=createClient({
    space:'w591jyzdi2py',
    accessToken:'DXG7DohnxRncpcxSPtLGr5fR4_fzjyzRzVZAiP9Ussk'
});

export {client}  

Replace the space and accessToken with your Contentful configurations which can be accessible in settings (contentful.com).

A list of posts

Using the getEntries async methos we can fetch the entries object. Since it is a an async call, we have to use a async component.

So lets create a list of posts

<template>
  <div>
    <h3> Contentful entries are ...</h3>
    <ol v-for="post in posts.items">
      <router-link :to="{path:`/post/${post.sys.id}`}">
        <ul>{{ post.fields.title }}</ul>
      </router-link>
    </ol>
  </div>
</template>

<script setup lang="ts">
import {client} from '@/contentful'
const posts = await client.getEntries();
</script>

<style scoped>

</style> 

The above setup component is an async component since it has a top level await.

Render the list

In a View component , we can render the async component with optional fall back template.

<script setup lang="ts">
import PostList from '@/components/PostList.vue'
</script>
<template>
  <div>
    <h1>Posts</h1>
    <suspense>
      <post-list/>
      <template #fallback>
        loading ..
      </template>
    </suspense>
  </div>
</template>
 

The same logic can be applied to a dynamic route. Please using dynamic route guide for Vue 3.

[display-post id=8704]

Async call in Vue 3 setup

Async calls in Vue3 setup script


To cope with Async call , Vue provide <Suspense>.

<script setup>
const res = await fetch(...)
</script> 

By default a setup with await will turn the component into async.

So how do we render the async component then ?

In order to render async component we have to wrap it with Suspense as follows

<template>
....
<Suspense>
  <!-- component with nested async dependencies -->
  <Dashboard />

  <!-- loading state via #fallback slot -->
  <template #fallback>
    Loading...
  </template>
</Suspense> 
</template>

The fallback template can be used to render the loading action logic.

Dynamic route and params in Vue 3

How to create dynamic route in Vue 3


We can define a dynamic route in vue router configuration file as follows

   {
      path: '/post/:id',
      name: 'posts',
    component:PostView
    }, 

this route allow us to use the id as param, for example /post/2, /post/231.

To access the param in a component template

<template>
{{$route.params.id}}
</template>

In the script we can use the useRoute() hook provide by Vue, to access the params.

const route = useRoute();
const id = route.params.id; 

Create a contentful plugin nuxt 3

How to create and use a contentful plugin in Nuxt 3


Contentful is headless CMS which can be used as powerful backbone for commercial and content rich app.

Using contentful with Nuxt 3 is so easy. I found that there is no nuxt-module available for Nuxt 3.

Using contentful in Nuxt 3 is only possible with a plugin, so let’s start building …

headless – plugin

Contentful-plugin

In Nuxt 3 need not register plugin in the nuxt.config. Just add a plugin at /plugins/ and go on.

We nee to install the contentful dependency first.

yarn add contentful 

Create a contentful client using the credentials (obtain it from contentful CMS – settings) and provide in the return statement , so that we can use it with useNuxtApp() hook.

// plugins/contentful-plugin.ts

import {createClient} from 'contentful'

const config = {
    space: 'w591jyzdi2py',
    accessToken: 'DXG7DohnxRncpcxSPtLGr5fR4_fzjyzRzVZAiP9Ussk'
};

export default defineNuxtPlugin(() => {
    return {
        provide: {
            client :createClient({
                space: 'w591jyzdi2py',
                accessToken: 'DXG7DohnxRncpcxSPtLGr5fR4_fzjyzRzVZAiP9Ussk'
            })
            }
        }

})
  

Using the plugin

In any component we can use the plugin. Here is dynamic route use case in which fetch a entry / post by id.

const route = useRoute()
const id = route.params.id;
const {$client}=useNuxtApp()
const {data} =await useAsyncData(id,()=> $client.getEntry(id)); 

In the above lines, extracted the $client using useNuxtApp() hook and invoke the client.

How to build a blog using Nuxt 3 and Graphql

How to build a blog app using TailwindCSS + Nuxt 3 + Graphql API


Vue is so popular among UI developers and also among React users. It is easy to learn and develop apps required with minimal effort.

Vue 3 is the latest version and Nuxt 3 is another framework on top Vue 3 with lots build tools.

Nuxt 3 come with all required tool for full stack developer and API route, middleware, plugins etc.

Here is our full live Nuxt 3 blog project

Continue reading “How to build a blog using Nuxt 3 and Graphql”

Setup Graphql client in Nuxt3

How to setup Graphql client in Nuxt3


Graphql API allow us consume on demand data from the API. In Nuxt 3 we can use the Nuxt module to setup a client and query graphql.

GQL Client configuration

Install the nuxt/graphql-client dependency and add the nuxt. Configurations as follows .

yarn add nuxt-graphql-client 
import { defineNuxtConfig } from 'nuxt'

// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({

    runtimeConfig: {
        public: {
            GQL_HOST: 'https://mockend.com/manoj-ap/mockbackend/graphql'
        }
    },
    modules: ['nuxt-graphql-client']
}) 

Queries

Create folder queries with posts.gql, add following simple query. In our example it is a set of posts.

//queries/posts.gql
query posts {
  posts(limit: 5) {
    id
    title
  }
}
 

The filename should match the query name.

Querying data

In any page we can use the async fetch using the client as follows.

<script setup>
const { data, error } = await useAsyncData("posts", () => GqlPosts());
</script>

How to enable custom layout for routes in Nuxt3

How to enable custom Layout for a pages in Nuxt3


Layouts in Nuxt 3 and Nuxt 2 have some minor changes. In Nuxt 2 we have used <Nuxt/> component to render pages / routes (if you using ~pages ) .

Nuxt 3 replaced the Nuxt component with <Slot/>.

How to create a Layout ?

To create and apply custom layout, we need to create Layouts folder and create our layouts.

//custom.vue
<template>
<div data-theme="winter" class="">   
    <header>
     <Header/>
    </header>
    <main class="h-screen w-full grid  overflow-auto ">
      <slot/>
    </main>
    <footer>
    <Footer/>
    </footer>
  </div>
</template>

 

Applying Layout

We can apply layout to pages using the the defineMeta section in the page component.

//pages/index.vue
<template>
  <div class="flex justify-center">
    <div class="p-1 h-full w-3/4 ">
      <Hero />  
    
    </div>     
  </div>
</template>

<script setup>
  definePageMeta({
   layout: "custom",
 });
</script> 

It also require to wrap the root component with <NuxtLayout> as follows

//app.vue
<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>

Applying layout in a template

We can apply templates using the NuxtLayout component directly into the HTML. Wrap the components with the NuxtLayout and pass the layout name.

<template> 
  <NuxtLayout name='custom'>
   <h1>Hello world</h1>
  </NuxtLayout>
</template>

Default layout

To create a default layout , create a component file with Layouts/default.vue and will be used for all pages with no Layout specified.

Disabling Layout

Suppose you want disable default layout for particular page, pass layout as false.

 definePageMeta({
   layout:false,
 }); 

How to integrate Strapi in Nuxt3

How to configure strapi CMS in Nuxt 3


Strapi a opensource headless CMS for developing content rich applications using Javascript.

Nuxt 3 is a framework on top of the Vue 3 progressive JavaScript framework. Along with Vuejs 3 it offers fast development, with minimal bundle size and performance upgrade.

Integrating Strapi in Nuxt 3

Strapi exposes AP for each collection types and have corresponding API end points. So we can either use fetch methods or axios for data fetching. Nuxt 3 has its own module to handle strapi operations.

Configure @nuxt/strapi

Install the strapi dependency

yarn add --dev @nuxtjs/strapi

also need to configure the nuxt config.

export default {
  buildModules: ['@nuxtjs/strapi'],
  strapi: {
  url: process.env.STRAPI_URL || 'http://localhost:1337',
  prefix: '/api',
  }
}

How to access collections ?

We can access the strapi collections using find, findOne methods, that the module provides.

<script>
 
export default {
  data() {
    return {
       
      products: [],
      categories:[]
       
    };
  },
 
  async mounted() {
    const { find } = useStrapi4()
    this.products=await find("products")
     this.categories=await find("categories")
  },

  components: {},
};
</script>

The useStrapi4() hook will return the async functions to retrieve data we needed.

Nuxt 3 Pinia store example

Nuxt 3 Pinia Store example


This is the Nuxt 3 Pinia snippet example, place the code in store.ts under store folder.

import { defineStore,acceptHMRUpdate } from 'pinia'

export const useStore = defineStore('storeId', {
  // arrow function recommended for full type inference
  state: () => {
    return {
      // all these properties will have their type inferred automatically
      count: 0,
    }
  },
})

if (import.meta.hot) {
  import.meta.hot.accept(acceptHMRUpdate(useStore, import.meta.hot))
}

Other snippets

How to create Vue 3 el check box filter

How to implement a post filter using pinia store, el-checkbox


Vue 3 is a progressive framework for web development, this opensource project is a power tool in web developer kit. It’s fast, lightweight and easy to learn. Version 3 has many performance upgrade from Vue 2.

Check Box filter

This is a el-plus tutorial, if you are familiar with Vue 3 and el-plus library , good to go. Suppose we had a set of posts or list of objects and wanna apply some simple category tag filter. How do we implement this logic.

What we need ?

  • A store
  • Check box component
  • Watch [Vue]

Store

Store can be used to global store , Vuex is good for Vue but in this project I used Pinia store.

el-checkbox group

This is an element plus UI, which help use to use a group checkbox together.

<template>
  <div>
  <div class="type-container">Filter Ads</div>
    <el-checkbox-group v-model="checkList">
      <div v-for="cat in store.categories" :key="cat.id">
      <el-badge class="item" :value="cat.posts.length"> 
      <el-checkbox :label="cat.name" /> 
      <!-- <span class="job-number " >1</span> -->
        </el-badge> 
      </div>
    </el-checkbox-group>
   
  </div>
  {{ checkList }}
</template>

<script lang="ts">
import {defineComponent, ref, watch, watchEffect} from "vue";
import { useCategory } from "@/store/categories";
import {useAd} from "~/store/ads";

export default defineComponent({
  setup: function () {
    const store = useCategory();
    const storeAds = useAd();
    store.getCategories();

    const checkList = ref([]);
    watchEffect(()=>{
      if(checkList.value.length<=0){
        storeAds.filteredAds= storeAds.ads;
      }
      else {
        storeAds.filterAdsByCategory(checkList.value);
      }
    });
    return {
      checkList,
      store,
    };
  },
});
</script>
<style scoped>
.item {
  margin-top: 0px;
  margin-right:7px;
}
</style>

WatchEffect

In the script setup , we created a reactive property and watch the changes in the checkList and filter the Ad posts which is List of Ads.

You can implement your own login in watchEffect as required.