Building Analytic Dashboards in Svelte

📅 2 years ago 🕒 10 min read 🙎‍♂️ by Madza

Building analytic dashboards in Svelte

Data has always been easier to perceive in a visual way. Visualization of the data allows us to see the tendencies over periods of time, allows us to compare different data as well makes it easier to see the totals, highlights, lows, and so on.

One of the most common ways to visualize data in software is analytics panels. We see them in most backend systems to display the visitor engagement data, user activity metrics, server stats, and other metrics.

In this article, we will build an analytics dashboard in Svelte. We will focus on how to create the components, separate the data from the code and implement the logic.

For reference here is the source code for the final project.

Creating a Wireframe

We will create a server statistics dashboard, that will display statistics via three different types of charts. There will be one line chart, two bar charts, and three doughnut charts.

The line chart will display the visitor stats across the six-month period. The bar charts will display the most visited pages as well as top referrers that bring traffic to the site. Finally, the doughnut charts will display user OS, browser, and device usages.

The layout of the analytics dashboard is shown in the wireframe below:

Wireframe image

Setting up the Project

To scaffold a new Svelte project we will use degit, a tool that is used to set up the fully functional Svelte app using the minimal template. Open up your terminal and run the following command: npx degit sveltejs/template svelte-analytics.

After that change your working directory to the newly created folder by running cd svelte-analytics. Then install all the necessary dependencies for the Svelte project to work by running the command npm install.

Then run npm run dev in your terminal and navigate to https://localhost:8080 in your browser. You should be presented with a Svelte project preview that looks like this:

Svelte project image

We will also install an external npm library chart.js that will help us to to create modern-looking and interactive charts. Run npm install chart.js and wait while the terminal finishes installing the package.

Simulating the Data

Normally the data would be fetched from the database. Since we will be focusing on how to create the analytics components themselves, we will create a sample data in a separate file and then import it where necessary.

Navigate to the src folder and create a new file called data.js inside it. Next, make sure to include the following code in it:

const colors = ["tomato", "gold", "limegreen"];

export const visits = {
  title: "Unique visitors",
  type: "line",
  backgroundColor: colors[0],
  labels: ["January", "February", "March", "April", "May", "June"],
  data: [275, 254, 261, 279, 262, 268]
};

export const pages = {
  title: "Top pages",
  type: "bar",
  backgroundColor: colors[0],
  labels: ["/gallery", "/blog", "/about", "/pricing", "/contact"],
  data: [220, 176, 132, 88, 44]
};

export const referrers = {
  title: "Top referrers",
  type: "bar",
  backgroundColor: colors[0],
  labels: ["google", "twitter", "facebook", "linkedin", "dev.to"],
  data: [23, 14, 6, 5, 2]
};

export const os = {
  title: "OS usage",
  type: "doughnut",
  backgroundColor: colors,
  labels: ["Win", "MacOS", "Linux"],
  data: [400, 100, 200]
};

export const browsers = {
  title: "Browser usage",
  type: "doughnut",
  backgroundColor: colors,
  labels: ["Chrome", "Firefox", "Safari"],
  data: [240, 100, 60]
};

export const devices = {
  title: "Device usage",
  type: "doughnut",
  backgroundColor: colors,
  labels: ["Phone", "Desktop"],
  data: [220, 260]
};

We first created a colors array, that will define the background color for the charts. We used predefined HTML color names "tomato", "gold" and "limegreen", but you can adjust them to any custom color palettes you want to fit your specific project.

Then we created a separate object for each chart consisting of the title, type, background color, labels, and data of the chart. We used export statements for each variable so we can later import them into the main file App.svelte and pass them in as props.

Creating the Chart Component

To create a chart component that will visualize our data, create a new folder components in the project root and make a new file Chart.svelte inside it. Now add the following code in the newly created file:

<script>
	import Chart from "chart.js/auto";
	import { onMount } from "svelte";

	let ctx;
	let chartCanvas;

	export let type;
	export let labels;
	export let data;
	export let title;
	export let backgroundColor;
	export let showLegends = false;

	onMount(async () => {
	  ctx = chartCanvas.getContext("2d");
	  const chart = new Chart(ctx, {
	    type,
	    data: {
	      labels,
	      datasets: [
	        {
	          backgroundColor,
	          data
	        }
	      ]
	    },
	    options: {
	      plugins: {
	        title: {
	          display: true,
	          text: title
	        },
	        legend: {
	          display: showLegends,
	          position: "bottom"
	        }
	      }
	    }
	  });
	});
</script>

<canvas bind:this={chartCanvas}></canvas>

We first imported the Chart component from the chart.js library. Then we imported the built-in onMount function from Svelte, which runs after the component is first rendered to the DOM.

Then we created context and canvas variables (ctx and chartCanvas) for the chart itself and created variables for the values that we will need to pass in when we import the Chart component in the main App.svelte file.

Finally, inside the onMount functions we created type, data, and options parameters, that we will be used to construct all of the charts. In order to render the Chart component to the screen, we bound chartCanvas to the canvas element.

Creating the App Logic

Now let's put the data and chart component together. Navigate to the src folder and open the file App.js. Add the following code inside it:

<script>
import  Chart  from  "../components/Chart.svelte";
import  {  visits,  pages,  referrers,  os,  browsers,  devices  }  from  "./data.js";
</script>

<main>
  <h3>Monthly Visitors</h3>
  <section>
  <Chart {...visits}/>
  </section>
  <h3>Top pages and Referrers</h3>
  <div id="pages">
  <section>
    <Chart {...pages}/>
  </section>
  <section>
    <Chart {...referrers}/>
  </section>
  </div>
  <h3>OS, Browsers and Devices</h3>
  <div id="devices">
  <section>
    <Chart {...os} showLegends={true}/>
  </section>
  <section>
    <Chart {...browsers} showLegends={true}/>
  </section>
  <section>
    <Chart {...devices} showLegends={true}/>
  </section>
  </div>
</main>

We first imported the Chart component and all the data objects we created earlier. Since we used export statements for each object variable, it was easy to import everything in a single line.

Next, we used a main wrapper around the whole app, created the h3 titles for the dashboard sections, and used grid layout wrappers for pages and devices sections, which will include 2 and 3 charts, respectively.

We then included all the planned Chart components. Notice we wrapped each Chart component inside a section tag. This is because Chart.js needs a parent element to define the width and adjust for responsiveness when viewed on different screen widths.

Finally, we used a JavaScript spread syntax to pass in the required props for the Chart components. For the last three charts, we will also display the legends, so an additional prop was added that enabled that option.

Styling the App

Now let's add some stylesheet rules to our app so the elements are being displayed as expected. While still on the App.svelte file, add the following code under the previously written Script tags and HTML:

<style>
  @import url("https://fonts.googleapis.com/css2?family=Montserrat&display=swap");

  :global(*) {
    margin: 0;
    padding: 0;
  }

  :global(body) {
    background-color: rgb(255, 137, 116);
    font-family: "Montserrat", sans-serif;
  }

  main {
    max-width: 800px;
    min-height: 100vh;
    margin: 0 auto;
    padding: 0 20px;
    background-color: rgb(245, 245, 245);
  }

  h3 {
    padding: 20px 0;
  }

  section {
    min-width: 100%;
    background-color: white;
    border-radius: 10px;
  }

  #pages {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 20px;
  }

  #devices {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
    padding-bottom: 20px;
  }

  @media only screen and (max-width: 560px) {
    #pages,
    #devices {
      grid-template-columns: 1fr;
    }
  }
</style>

First, we imported Montserrat font and set it to be used throughout the whole app. We also used reset rules for the padding and margin, so the dashboard looks the same on the different browsers. We set the background color of the page to be orange.

For the dashboard itself, we set the width to never exceed 800px and centered it in the viewport. We also used some padding and set the background color to be light grey. We set some top and bottom padding for the section titles, as well as defined the width, background color as well border-radius for the sections themselves.

For the wrappers that will include multiple charts, we set the layout to be grid and use the grid-template-columns, that divide the available width of the main wrapper into 2 or 3 columns with equal width, with a 20px gap between them.

Finally, we created a CSS media rule for both grid wrappers. If the screen width is 560px or smaller, the grid layout for pages and devices switches to 1 column, meaning all the included charts are shown directly below each other.

The last thing left to do after styling would be to test the app. Check if the development server is still running. If it is not, run npm run dev in your terminal again and visit the https://loclahost:8080 in your browser. You should be presented with the final dashboard, that looks like this:

Image of the final project

Conclusion

In this tutorial, we learned how to create reusable chart components. During the process of making the analytics dashboard, we got to know how to separate the data from the code and how to import, export, and pass in the type, data, and options for the charts.

Feel free to adapt and use this template in your own projects. Also, if you want, you can move the data to the database and implement the backend so the data gets updated when the project is being used.

Hopefully, you gained some knowledge and from now on you will feel more comfortable implementing dashboards while working with Svelte.