Create a real-time data analytics platform with Appwrite and Nuxtjs
Tags: javascript, appwrite, jamstack, webdev
Published: 2023-02-03 11:35:30

Creating a real-time data analytics platform can be challenging, but it can be made much easier with the right tools. One such tool is [Appwrite](https://appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog), a modern and powerful backend-as-a-service (BaaS) platform for easily building and deploying web and mobile applications. Another helpful tool is Nuxt.js, a progressive framework for building server-rendered Vue.js applications.

This article covers the steps to create a real-time data analytics platform using Appwrite and Nuxt.js by simulating a simple eCommerce dashboard.

## Repository

Here’a a link to the repo:

https://github.com/folucode/data-visualization-appwrite

## Prerequisites
- Basic understanding of CSS, JavaScript, and Nuxt.js
- Docker Desktop installed on your computer (run the `docker -v` command to verify the installation); if not, install it from [here](https://www.docker.com/products/docker-desktop/)
- An Appwrite instance running on your computer. Check out [this post](https://dev.to/hackmamba/create-a-local-appwrite-instance-in-3-steps-19n9?utm_source=hackmamba&utm_medium=hackmamba) to create a local Appwrite instance. It can also be installed using [digital ocean](https://docs.digitalocean.com/products/marketplace/catalog/appwrite/) or [gitpod](https://www.gitpod.io/guides/appwrite-and-gitpod)

## Setting up the project

Create a new Nuxt.js project using the following command:


    npx create-nuxt-app data-analytics-platform

This will guide you through several prompts to set up the project, including selecting a package manager, a UI framework, and additional features. Make sure to choose Axios as the HTTP client, as you'll use it to make API calls to Appwrite later.

Once you finish setting up the project, you can navigate to the project directory and start the development server using the following commands:


    cd data-analytics-platform
    npm run dev

## Setting up an Appwrite database

To set up an Appwrite storage bucket, log in to the Appwrite console and create a new project. Next, click on the `Databases` tab and then `Create database`. You can give it the name of `ecommerce`.

![image](https://paper-attachments.dropboxusercontent.com/s_AA60BADABC4BB9F8A2904A8B3056A20F654D2817563E0D779D009AFE0FEB6D3F_1671740806656_create+database.png)


Click on the ecommerce database and create a new collection in the database; call it `orders`. `Collections` serve as database tables in Appwrite.

Next, click on the collection, and then add new attributes. `Attributes` serve as database columns in Appwrite.

![image](https://paper-attachments.dropboxusercontent.com/s_EF134CC8966AA6545ABCCEA42FA99F2168DDAEED0CD28F222DFE26B40D4BF647_1671808767828_attributes+ecommerce.png)


The attributes you will add are:

- `customer` of type string
- `price` of type double

Click on the settings tab, scroll down to permissions, and add `Users` role with all permissions for the `orders` collection.

![image](https://paper-attachments.dropboxusercontent.com/s_EF134CC8966AA6545ABCCEA42FA99F2168DDAEED0CD28F222DFE26B40D4BF647_1671808909048_Screenshot+2022-12-23+at+16.20.32.png)

## Setting up the UI

In the components folder, create a file called `DataCard.vue` and paste the code below into it:

```javascript
    <template>
      <div class="chart">
        <div class="chart-inner stat-1">
          <div class="header">
            <div class="tagline">{{ tagline }}</div>
            <div class="count">{{ count }}</div>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      props: {
        tagline: String,
        count: Number,
      },
      name: "DataCard",
    };
    </script>
 ```  

This component is a simple card that will display the order details. There are two attributesL: tagline and count.

Next, in the `index.vue` file, paste the code below:

```javascript
    <template>
      <div>
        <div class="container-fluid">
          <DataCard tagline="Total Customers" :count="totalCustomers" />
          <DataCard tagline="Total Orders" :count="totalOrders" />
          <DataCard tagline="Total Revenue" :count="Math.round(totalRevenue)" />
        </div>
    
        <button class="button" @click.prevent="makeOrder()">Create Order</button>
    
        <h2>Orders</h2>
        <table>
          <tr>
            <th>Order ID</th>
            <th>Customer</th>
            <th>Price</th>
          </tr>
          <tr v-for="order in orders" :key="order.$id">
            <td>{{ order.$id }}</td>
            <td>{{ order.customer }}</td>
            <td>{{ order.price }}</td>
          </tr>
        </table>
      </div>
    </template>
    
    <script>
    export default {
      name: "IndexPage",
      data() {
        return {
          orders: [],
          totalCustomers: 0,
          totalOrders: 0,
          totalRevenue: 0,
        };
      },
      methods: {},
      mounted() {},
    };
    </script>
    
    <style>
    body {
      background-color: #252830;
      color: white;
    }
    .container-fluid {
      margin-left: 18%;
    }
    .chart {
      text-align: left;
      display: inline-block;
      width: 300px;
    }
    .chart-inner {
      background-color: rgba(233, 164, 164, 0.5);
    }
    .header {
      box-sizing: border-box;
      padding: 30px 15px;
      position: relative;
      text-shadow: 1px 1px 2px black;
    }
    .tagline {
      opacity: 0.75;
      text-transform: uppercase;
    }
    .count {
      display: inline-block;
      font-size: 32px;
      font-weight: 300;
      vertical-align: middle;
    }
    table {
      font-family: arial, sans-serif;
      border-collapse: collapse;
      width: 100%;
    }
    td,
    th {
      border: 1px solid #dddddd;
      text-align: left;
      padding: 8px;
    }
    .button {
      background-color: #4caf50; /* Green */
      border: none;
      color: white;
      padding: 15px 32px;
      text-align: center;
      text-decoration: none;
      display: inline-block;
      font-size: 16px;
    }
    </style>
```    

In this file, there is a DataCard to show Total Customers, Total Revenue, and Total Orders. You have a button to create an order, and this helps to save the time of building an order system since you're primarily interested in the real-time feature. The button has a click event with a function, `makeOrder()`, that you'll create later.

There's also a table to list all the orders in the Appwrite database.

## Building the App

Before you continue, install these two packages: the Appwrite official package and faker.js, a library to generate mock data. 


    npm i appwrite @faker-js/faker
### Connecting to Appwrite

In the `pages/i``ndex.vue` file, import the Appwrite package and the faker.js package, and then create an Appwrite connection like so:

```javascript
    ...
    <script>
    import { Client, Account, Databases } from "appwrite";
    import { faker } from "@faker-js/faker";
    
    const client = new Client();
    
    client
      .setEndpoint("http://localhost/v1") // The Appwrite Endpoint
      .setProject("[YOUR-PROJECT-ID]");
    
    const account = new Account(client);
    const database = new Databases(client);
    
    account.createAnonymousSession().then(
      (response) => {
        console.log(response);
      },
      (error) => {
        console.log(error);
      }
    );
    
    export default {
      name: "IndexPage",
      data() {
        return {
          orders: [],
          totalCustomers: 0,
          totalOrders: 0,
          totalRevenue: 0,
        };
      },
      methods: {},
      mounted() {},
    };
    </script>
    ...
```
In this file, you create an Appwrite instance along with an account and database, which you'll use later in the app. Also, set up an anonymous sessiont — this saves us the time of making a whole authentication system.

In the mounted method, check whether the anonymous account is active and subscribe to the documents channel. Subscribing to a channel updates your app in real time once a change is made in the database.

```javascript
    ...
     mounted() {
        if (account.get !== null) {
          try {
            client.subscribe("documents", (response) => {
            });
          } catch (error) {
            console.log(error, "error");
          }
        }
      }
    ...
```
### Making an order

Add a new method to the methods object called `makeOrder`. In this new method, you'll create a new order in the Appwrite database using faker.js, like so:

```javascript
    async makeOrder() {
      await database.createDocument(
        "[YOUR-DATABASE-ID]",
        "[YOUR-COLLECTION-ID]",
        "unique()",
        {
          customer: faker.name.fullName(),
          price: faker.finance.amount(),
        }
      );
    },
```
### Analyzing the data

To analyze the data, create a function called `visualizeData` and add the code below:

```javascript
    async visualizeData() {
      const orderDetails = await database.listDocuments(
        "[YOUR-DATABASE-ID]",
        "[YOUR-COLLECTION-ID]"
     );
    
      this.orders = orderDetails.documents;
      this.totalCustomers = orderDetails.total;
      this.totalOrders = orderDetails.total;
    
      this.totalRevenue = orderDetails.documents.reduce(
        (accumulator, currentValue) => accumulator + currentValue.price,
        0
      );
    },
```
In this code, you first fetch the orders from the database. The reduce function accumulates the prices to obtain the total revenue.

Every time the page reloads or changes occur in the database, you want to fetch all the podcasts in real time. To do so, call the visualizeData function in the mounted method like so:

```javascript
    ...
    mounted() {
      this.visualizeData();
    
      if (account.get !== null) {
        try {
          client.subscribe("documents", (response) => {
            this.visualizeData();
          });
        } catch (error) {
          console.log(error, "error");
        }
      }
    },
    ...
```
The app should look like so:

![image](https://paper-attachments.dropboxusercontent.com/s_EF134CC8966AA6545ABCCEA42FA99F2168DDAEED0CD28F222DFE26B40D4BF647_1671810948891_data+anlytics.gif)

## Conclusion

In conclusion, building a real-time data analytics platform with [Appwrite](https://appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog) and Nuxt.js can provide a powerful and flexible data analysis and visualization solution. By leveraging the real-time capabilities of Appwrite and the versatility of Nuxt.js, you can create dynamic and interactive dashboards that allow your users to quickly understand and explore their data in real time. 

Whether you are building a platform for business analytics, IoT data analysis, or any other real-time data application, Appwrite and Nuxt.js can provide the tools and framework you need to succeed.

## Resources
- [Appwrite Documentation](https://appwrite.io/docs?utm_source=hackmamba&utm_medium=blog&utm_campaign=hackmamba)
- [Nuxt.js Documentation](https://nuxtjs.org/docs/get-started/installation/)