Building a Progressive Todo Web App with Vuetify, Vuex and GraphQL
Tags: vue, vuetify, graphql, javascript
Published: 2019-03-26 10:38:07

---
title: Building a Progressive Todo Web App with Vuetify, Vuex and GraphQL
published: true
description: Build a progressive todo app with Vuetify, Vuex, VueApollo and integrate GraphQL APIs using Hasura GraphQL Engine.
tags: vuejs, vuetify, graphql, javascript
canonical_url: https://blog.hasura.io/building-progressive-todo-web-app-with-vuetify-vuex-graphql/
---

## TL;DR
Build a progressive todo app with Vuetify, Vuex, VueApollo and integrate GraphQL APIs using Hasura GraphQL Engine.

Instant setup. App Source Code 👉 [vuetify-vuex-todo-graphql](https://github.com/hasura/graphql-engine/tree/master/community/sample-apps/vuetify-vuex-todo-graphql)

![vuetify+vuex+graphql](https://blog.hasura.io/content/images/2019/03/vuetify.png)

## Tech Stack
This progressive web app uses the following frameworks/servers

- Vue.js with Vuetify for Material Design UI, Vuex for state management, VueApollo for making GraphQL queries
- [Hasura GraphQL Engine](https://github.com/hasura/graphql-engine) to get instant GraphQL APIs over Postgres

## Vuetify Framework
[Vuetify](https://vuetifyjs.com/) is a semantic component framework for Vue. It is built according to Google's Material Design Spec and has intuitive properties without complex classes and markup.

In this app, we make use of Vuetify components like VGrid, VCard, VList, VTextField, VBtn among a bunch of available reusable components.

The progressive todo web app is a fork of [davidgaroro/vuetify-todo-pwa](https://github.com/davidgaroro/vuetify-todo-pwa) which uses

- Vuetify for the TodoMVC UI with material design
- Vuex for state management

Here's how the todo app looks like with Vuetify's material design components:

![Todo App](https://blog.hasura.io/content/images/2019/03/todo-app-landing-page.png)

We added **vue-apollo** to this app and configured **ApolloClient** to make GraphQL queries for storing and managing the todos in the database. We will use Hasura to get instant GraphQL APIs.

## Hasura + vue-apollo
[Hasura](https://hasura.io/) is an [open-source](https://github.com/hasura/graphql-engine) engine that gives you realtime GraphQL APIs on new or existing Postgres databases, with built-in support for stitching custom GraphQL APIs and triggering webhooks on database changes.

We will integrate Hasura GraphQL APIs with this todo app. Refer the [github](https://github.com/hasura/graphql-engine/tree/master/community/sample-apps/vuetify-vuex-todo-graphql) link to deploy Hasura and create the todos table.

Once we have Hasura deployed, we can configure the frontend to make GraphQL queries. We add all modules required to configure ApolloClient.

```js
npm install --save vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag
```

**Note**: You can also use **apollo-boost**, if you don't need fine grained control over configuration

We define **ApolloClient** in `src/apollo.js` file in the todo app,

```js
import Vue from 'vue'
import VueApollo from 'vue-apollo'
import { ApolloClient } from 'apollo-client'
import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'

const httpLink = new HttpLink({
  // You should use an absolute URL here
  uri: 'https://myapp.herokuapp.com/v1alpha1/graphql'
})

// Create the apollo client
export const apolloClient = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache(),
  connectToDevTools: true
})

const apolloProvider = new VueApollo({
  defaultClient: apolloClient
})

// Install the vue plugin
Vue.use(VueApollo)

export default apolloProvider
```

We need to just configure Hasura GraphQL Engine endpoint in the `httpLink` and import this apolloProvider in `main.js` and add it to the Vue instance like this:

```js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import apolloProvider from './apollo'
import './registerServiceWorker'
import './vuetify'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  apolloProvider,
  render: h => h(App)
}).$mount('#app')
```

Once this is configured, the apolloClient can be imported and used across the app.

We define the GraphQL queries/mutations and trigger them in **Vuex store**.

For example, to fetch all the todos, we define a simple query to fetch todos sorted by latest id.

```js
const todoQuery = gql`{
    todos(order_by: [{id: desc}]) {
      id
      text
      is_completed
    }
}`
```

and in our actions, we make this query using apolloClient and invoke the mutation handler using **commit** which will update the state.

```js
const actions = {
  async fetchTodos ({ commit }) {
    const { data } = await apolloClient.query({query: todoQuery})
    commit('fetchTodos', data.todos)
  },
}
```

Note that we are making use of **async, await** which makes the syntax cleaner.

Let's define a GraphQL mutation to insert a new todo.

```js
const todoMutation = gql`
  mutation insert_todos($text: String!) {
    insert_todos(objects: [{text: $text}]) {
      affected_rows
      returning {
        id
        text
        is_completed
      }
    }
}`
```

This mutation accepts a `$text` variable and inserts it into the todos table.

Similarly we define GraphQL mutations for adding/updating/deleting todos and we define actions to make the mutation and update the state in the Vuex store.

## Progressive Web App
This todo app is a PWA and comes with boilerplate setup for

- App manifest
- Service worker
- Workbox options - [Cache Google Fonts](https://developers.google.com/web/tools/workbox/guides/common-recipes#google_fonts)

which can be configured to get a Lighthouse score of 100.

## Todo App Source Code
I have put together the app with complete GraphQL integration so that you can get started quickly and extend it further!

Check it out on [github](https://github.com/hasura/graphql-engine/tree/master/community/sample-apps/vuetify-vuex-todo-graphql).

Note that this app doesn't have any user authentication yet and its currently a demo to integrate GraphQL queries/mutations with Vuetify + Vuex with Hasura.