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, 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 - An Appwrite instance running on your computer. Check out this post to create a local Appwrite instance. It can also be installed using digital ocean or 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
.
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.
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.
Setting up the UI
In the components folder, create a file called DataCard.vue
and paste the code below into it:
<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:
<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:
...
<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.
...
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:
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:
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:
...
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:
Conclusion
In conclusion, building a real-time data analytics platform with Appwrite 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.