Building a Next.js Dashboard with Dynamic Charts and SSR
Data visualizations and analytics provide you with a graphical representation of your organization's data and can help you make data-driven decisions for your business. Building an analytics application for your organization's data is easier than you think.
In this tutorial, you will learn how to build a robust data analytics application with a dashboard using Next.js, Cube and Bizcharts. We'll build a Next.js dashboard like this one...
...and then upgrade it to use server-side rendering (SSR):
Cube is an open-source, API-first semantic layer platform. Cube connects to dozens of different data sources (primarily databases) to make data accessible and consistent across every application.
You run your Cube API as a service. Cube manages connections to your databases and exposes an API for your front-end applications to consume and build data visualization and other analytics features.
Getting started with Cube
The easiest way to get started with Cube is with Cube Cloud. It provides a fully managed cube server ready to use. However, if you prefer self-hosting, then follow this tutorial.
We will create a new Cube deployment in Cube Cloud. You can select a cloud platform of your choice.
Next, select start from scratch to get started with a fresh instance.
Next, we will select a database. For this example application I am going to use PostgreSQL. Feel free to use any database of your choice.
Don’t have a database with sample data? We got you covered. We created a public database for you to connect your Cube instance and play around. Add the following credentials in your Cube database configuration to connect to our public database.
Hostname: demo-db-examples.cube.dev
Port: 5432
Database: ecom
Username: cube
Password: 12345
Cube can auto-generate a Data Schema from your SQL tables. A Cube.js Data Schema is used to model raw data into meaningful business definitions. The data schema is exposed through the querying API, allowing end-users to query a wide variety of analytical queries.
We will select the following tables for schema generation. More on Data Schema later in the article.
line_item
orders
products
product_categories
users
suppliers
It will take couple minutes to get up and running.
Visualizing data with the Developer Playground
Let’s head over to the Playground tab in Cube cloud. The Developer Playground is a tool to generate dashboards from various templates for different front-end frameworks and data visualization libraries.
We will create a new query. Let’s select Line Item Count as measures and Line Item Create at as time. We can select a framework and a data visualization library in the chart configuration. Then select Run to generate the data chart.
Once the chart is generated we can also select the edit button to view the code for the front end in code sandbox. This is extremely powerful because Cube scaffolds front-end code and gives us a template to build our front-end application.
Next, we will create a new Next.js application and create an analytics dashboard.
Building the Next.js App
Please run the following command to create a new Next.js app.
$ npx create-next-app myanalytics
$ cd myanalytics
Next, add the required npm packages to your project.
$ npm i @cubejs-client/react \
bizcharts \
antd \
react-flatpickr --save
Create a new .env.local file in the root directory of your project. Add the following environment variables.
You can find the Cube API endpoint from the Cube dashboard. Navigate to Settings from the Cube dashboard. There is a field called Cube.js API in the overview tab. Copy the url from there and add it to your .env.local.
We will also need to generate a Cube token to connect to Cube Cloud from our Next.js application. Please Select the Env vars tab in your Settings and copy the CUBEJS_API_SECRET value.
With this secret, we can generate a JWT token. You can run the following node script to generate a JWT token.
const jwt =require('jsonwebtoken');
constCUBE_API_SECRET='<Secret>';
const cubejsToken = jwt.sign(
{},CUBE_API_SECRET,{expiresIn:'30d'}
);
console.log(cubejsToken);
Learn more about JWT tokens and how they work on Auth0 website.
Copy the generated JWT token and add it to NEXT_PUBLIC_CUBEJS_TOKEN in .env.local file. We are now all set. Let’s go ahead and run our application with npm run dev command.
Creating our first chart
Let's create a chart to visualize our order counts for each day over a time period. Replace the contents of pages/index.js with the following code.
Let's review the code. First of all, we are initializing the Cube.js API client with the following lines of code.
const cubejsApi =cubejs(
process.env.NEXT_PUBLIC_CUBEJS_TOKEN,
{apiUrl: process.env.NEXT_PUBLIC_CUBEJS_API_URL}
);
Inside the useEffect() hook we run a function called loadData. Inside the loadData function we call the load function from cubejsApi. This function queries Cube Cloud and returns the desired data based on the defined Cube schema.
Notice that we pass in an object as a parameter in the load function. The shape of this object defines the type of data we are getting back.
We can generate this object from the Cube Playground. Let's head over to Cube Playground and execute a query. Select the JSON Query tab as shown in the following image.
Notice, we also import a component named LineChart from the components/LineChart file. We will pass the data as props to this component to create the chart.
Let's create a new file components/LineChart.js and add the following code.
Similarly, I will add a bar chart to visualize the order count by suppliers and a table for order count. The final version of pages/index.js should be as follows.
Fetching dashboard data with SSR (Server Side Rendering)
Next.js provides the ability to make an API call on the server-side. You do this with getServerSideProps function. You can learn more about it in the Next.js docs.
We can add the Cube API calls inside the getServerSideProps function and fetch all the data necessary for our dashboard on the server-side. When the page loads, the client (browser) doesn’t need to make additional API requests.
Let’s create a new page to pages/ssr-example.js and add the following code.
The key difference is that we put all the API calls inside the getServerSideProps function. Then we pass the data to our page component as props.
When is SSR useful?
Server-side rendered applications load faster on the client-side as they make all API calls on the server-side. This may not be noticeable in fast network but you can clearly notice the difference in a slow network.
Following is a screenshot of client side rendering in a 3G network. Notice it makes 2 API calls and roughly takes about 5 seconds to load the page.
Now, compare this to the SSR version. The SSR version will make one API call as it rendered all data in the server side. It makes one call and it takes about 2 seconds.
Next.js also caches data so the performance can be optimized more.
If you are expecting a lot of data for your dashboard and want to improve user experience regardless of the client’s network speed, then SSR is the way to go.
Where to go from here?
In this tutorial, we build a simple metrics dashboard using Cube and Next.js. Cube comes with tons of features for data analytics and visualization. One of the best places to learn about these features is Cube's official documentation page.
The complete source code for this tutorial is available in this GitHub repo.
Check out our tutorials and blog for more sample apps and blog posts like this one.
And join us on Slack! It is a great place to get help and stay up to date.