Realtime Chat app with Vue and Hasura
Tags: vue, hasura, graphql
Published: 2019-03-27 17:26:48

---
title: Realtime Chat app with Vue and Hasura
published: true
description: Introducing realtime chat app with Vue and Hasura
tags: Vue, Hasura, GraphQL
---

So before VueConf I thought it will be a great idea to rewrite our React realtime chat app to VueJS, which features login, realtime chat inbox, typing indicator, online users

![](https://thepracticaldev.s3.amazonaws.com/i/cmilix7370rc3txufb48.png)

So here you go - the chat is up and running [here](https://realtime-chat-vue.hasura.app)

So in this blog post I want to describe what I actually  did for rewriting that. I won't go deeper in data modeling cause that is perfectly explained in this [blog post](https://blog.hasura.io/building-a-realtime-chat-app-with-graphql-subscriptions-d68cd33e73f/), but let me explain the steps I did for creating this in Vue.
For more in detail explanation how to use Vue with GraphQL you can check out my course here:

{% twitter 1110557406080188417 %}

If you are really new to GraphQL you can check a bootcamp I did on my [Youtube channel](https://www.youtube.com/channel/UCxiXx-gMssQnY0hTt5bStpw)

And check our [Hasura Youtube channel](https://www.youtube.com/channel/UCZo1ciR8pZvdD3Wxp9aSNhQ) for more Hasura content

So the steps I did after Data modeling: 

# 1. Add login functionality to Vue Router:

```javascript
router.beforeEach((to, from, next) => {
  const isPublic = to.matched.some(record => record.meta.public);
  const onlyWhenLoggedOut = 
    to.matched.some(record => record.meta.onlyWhenLoggedOut)
  const loggedIn = !!TokenService.getToken();
  if (!isPublic && !loggedIn) {
    return next({
      path: "/login",
      query: { redirect: to.fullPath }
    });
  }
  if (loggedIn && onlyWhenLoggedOut) {
    return next('/')
  }
  next();
});

```

# 2. Setup Apollo Client with subscriptions. 
You can learn more about that in the [course](https://dev.to/hasurahq/vue-and-graphql-with-hasura-video-course-3mpp)

```javascript
import VueApollo from "vue-apollo";
// Http endpoint
const httpLink = new HttpLink({
  uri: "https://realtime-chat.demo.hasura.app/v1alpha1/graphql"
})

const wsLink = new WebSocketLink({
  uri: "wss://realtime-chat.demo.hasura.app/v1alpha1/graphql",
  options: {
    reconnect: true
  }
});

const link = split(
  ({ query }) => {
    const { kind, operation } = getMainDefinition(query);
    return kind === "OperationDefinition" && operation === "subscription";
  },
  wsLink,
  httpLink
);


const apolloClient = new ApolloClient({
  link,
  cache: new InMemoryCache(),
  connectToDevTools: true
});

Vue.use(VueApollo);

// Call this in the Vue app file
export function createProvider() {
  return new VueApollo({
    defaultClient: apolloClient,
    defaultOptions: {
      $loadingKey: "loading"
    }
  });
}
```

# 3. Getting online users
For displaying online users we want to emit online event every time user is logged in so in our Home route we have to emit online event using apollo mutation

```javascript
created(){
    setInterval(
      async () => {
        await this.$apollo.mutate({
          mutation: require('../graphql/emitOnlineEvent.gql'),
          variables: {
            userId: this.userId
          }
        })
      },
      3000
    )
  }
```

# 4. Subscribing to messages
For getting the messages I created a query that will get all the messages and then subscribe to a new ones. I've explained how to deal with that in my Vue course too.

```javascript
 apollo: {
      messages: {
        query: require('../graphql/fetchMessages.gql'),
        loadingKey: "loading",
        variables(){
          return {
            last_received_id: -1,
            last_received_ts: "2018-08-21T19:58:46.987552+00:00"
          }
        },
        update(data){
          const receivedmessages = data.message
          return receivedmessages
        },
        fetchPolicy: 'cache-and-network',
        subscribeToMore: {
          document: require('../graphql/subscribeToNewMessages.gql'),
          updateQuery: (previousResult, { subscriptionData }) => {
            if (previousResult) {
              return {
                message: [
                  ...previousResult.message,
                  ...subscriptionData.data.message
                ]
              }
            }
          }
        },
        error(){
          alert("Error occured")
        }
      }
```

# 5. Typing Indicator
We also needed user typing notifications so I created emitTyping event mutation that emitted event every  few characters. That let us to keep track on typing users and show typing indicator whenever other user is typing

```javascript
 watch: {
      text: function(value){
        const textLength = value.length;
        if ((textLength !== 0 && textLength % 5 === 0) || textLength === 1) {
          this.emitTypingEvent();
        }
      }
    },
    methods: {
      emitTypingEvent(){
        if(this.userId) {
          this.$apollo.mutate({
          mutation: require('../graphql/emitTypingEvent.gql'),
          variables: {
              userId: this.userId
          }
          })
        }
      },
```

In a nutshell that's about it. I had an amazing experience creating this app with VueJS and for more info on how and what decisions I did when coding this app you can check it either on my [github](https://github.com/vnovick/vue-realtime-chat)
or in Hasura sample apps [repository](https://github.com/hasura/graphql-engine/tree/master/community/sample-apps)