# Rich data visualization

**URL:** <https://discourse.nodered.org/t/rich-data-visualization/97436>\
**Category:** Dashboard\
**Tags:** uibuilder\
**Created:** [5 June 2025 19:04 UTC](https://discourse.nodered.org/t/rich-data-visualization/97436 "2025-06-05T19:04:20Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![pedro\_uno](https://avatars.discourse-cdn.com/v4/letter/p/bcef8e/32.png) [@pedro\_uno](https://discourse.nodered.org/u/pedro_uno)\
**Post date:** [5 June 2025 19:04 UTC](https://discourse.nodered.org/t/rich-data-visualization/97436/1 "2025-06-05T19:04:20Z")

</div>

Hello  
I am a neophyte Node-Red user but I have already built a flow to act as an instrument interface. The flow runs on an embedded system with Arm A53 micro-controller and FPGA logic. I have been able to get sensor data from the FPGA and into a Dashboard Chart node. The web interface has a switch to enable auto-trigger which updates the data in the Chart at a rapid rate. I use the Chart node in one-shot mode where I send it a complete vector of data all at once and it replaces the previous plot with the new one. It looks like a digital oscilloscope when it is running. Thanks for all the help.

This experiment succeeded as a proof of concept but our production instruments need richer data visualization like scatter plots, colorized heat maps and digital phosphor style rendering.

My question is whether Node-Red can be readily extended to use more sophisticated commercial javascript data visualization libraries?

My day job is FPGA programmer but I like the way Node-Red lets me hack together a quick interface for demonstration and testing. A professional web developer would responsible for the production interface.

---

<div class="post-metadata">

**Author:** ![jbudd](https://avatars.discourse-cdn.com/v4/letter/j/5f8ce5/32.png) [@jbudd](https://discourse.nodered.org/u/jbudd)\
**Post date:** [5 June 2025 19:51 UTC](https://discourse.nodered.org/t/rich-data-visualization/97436/2 "2025-06-05T19:51:33Z")

</div>

You may find uibuilder a better match for your requirements than the Node-red dashboard since as I understand it, you are free to use whatever libraries you like.

Hopefully you will be able to share whatever you create with the community

---

<div class="post-metadata">

**Author:** ![bakman2](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bakman2/32/6207_2.png) [@bakman2](https://discourse.nodered.org/u/bakman2)\
**Post date:** [5 June 2025 20:27 UTC](https://discourse.nodered.org/t/rich-data-visualization/97436/3 "2025-06-05T20:27:01Z")

</div>

Simple example using http-in/out + websocket nodes

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/d/ad2486a31dc402727f1d78d6fd434f51d537d5cc.png)

open the webpage at `<nodered ip:port>/chart` and press the inject button.  
The data generator generates a datapoint every millisecond for 5 seconds (a lot of data), it streams the chart (apache echarts) -

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/4/640fe4ee44dd0b14af0dc1cebc3a1354ef4224e2.png)

Example flow:

```auto
[{"id":"6353e1f90e6bf036","type":"http in","z":"fae101de87421f64","name":"","url":"/chart","method":"get","upload":false,"swaggerDoc":"","x":200,"y":120,"wires":[["516249feec1b3670"]]},{"id":"0befe11c2d87ac22","type":"http response","z":"fae101de87421f64","name":"","statusCode":"","headers":{},"x":510,"y":120,"wires":[]},{"id":"516249feec1b3670","type":"template","z":"fae101de87421f64","name":"","field":"payload","fieldType":"msg","format":"html","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n<head>\n <title>Real-Time ECharts Chart</title>\n <script src=\"https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js\"></script>\n <style>\n #chart {\n width: 100%;\n height: 600px;\n }\n </style>\n</head>\n<body>\n <div id=\"chart\"></div>\n <script>\n // Initialize ECharts\n const chartDom = document.getElementById('chart');\n const myChart = echarts.init(chartDom);\n let dataPoints = [];\n const MAX_POINTS = 1000;\n\n // Initial chart configuration\n let option = {\n title: {\n text: 'Real-Time Data Stream'\n },\n tooltip: {\n trigger: 'axis'\n },\n dataZoom: [\n {\n type: 'inside'\n },\n {\n type: 'slider'\n }\n],\n xAxis: {\n type: 'time',\n splitLine: {\n show: false\n }\n },\n yAxis: {\n type: 'value'\n },\n series: [{\n name: 'Value',\n type: 'line',\n showSymbol: false,\n data: dataPoints\n }]\n };\n myChart.setOption(option);\n\n const socket = new WebSocket(location.origin.replace(/^http/, 'ws') + '/ws/chart_data');\n\n socket.onmessage = (event) => {\n const newData = JSON.parse(event.data);\n const timestamp = new Date().getTime();\n \n dataPoints.push({\n name: timestamp,\n value: [timestamp, newData.value]\n });\n\n if (dataPoints.length > MAX_POINTS) {\n dataPoints.shift();\n }\n\n myChart.setOption({\n series: [{\n data: dataPoints\n }]\n });\n };\n\n window.addEventListener('resize', () => {\n myChart.resize();\n });\n </script>\n</body>\n\n</html>","output":"str","x":360,"y":120,"wires":[["0befe11c2d87ac22"]]},{"id":"6bef3acd4f7f9f0d","type":"websocket out","z":"fae101de87421f64","name":"","server":"0333b76e0face47c","client":"","x":570,"y":180,"wires":[]},{"id":"37f36e4b77ce0b46","type":"inject","z":"fae101de87421f64","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":200,"y":180,"wires":[["5f5b4928cf73a7b7"]]},{"id":"5f5b4928cf73a7b7","type":"function","z":"fae101de87421f64","name":"data generator","func":"\nfunction generate(){\n return {payload:{ value: Math.random() * 100}\n }\n}\n\nconst timer = setInterval(() => {\n node.send(generate())\n}, 1);\n\n\nsetTimeout(()=>{\n clearInterval(timer)\n},5000)\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":180,"wires":[["6bef3acd4f7f9f0d"]]},{"id":"0333b76e0face47c","type":"websocket-listener","path":"/ws/chart_data","wholemsg":"false"}]

```

---

<div class="post-metadata">

**Author:** ![omrid](https://avatars.discourse-cdn.com/v4/letter/o/77aa72/32.png) [@omrid](https://discourse.nodered.org/u/omrid)\
**Post date:** [6 June 2025 10:44 UTC](https://discourse.nodered.org/t/rich-data-visualization/97436/4 "2025-06-06T10:44:50Z")

</div>

you can import a richer charting package, such as `chart.js`, into a dashboard `template` node

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [6 June 2025 20:18 UTC](https://discourse.nodered.org/t/rich-data-visualization/97436/5 "2025-06-06T20:18:12Z")

</div>

> [@pedro\_uno](#):
>
> A professional web developer would responsible for the production interface.

This is perfect for UIBUILDER. It is specifically designed to allow developers to be able to use existing web development tooling and workflows while providing a lightweight data interface to/from Node-RED using a simple client library.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [6 July 2025 20:19 UTC](https://discourse.nodered.org/t/rich-data-visualization/97436/6 "2025-07-06T20:19:01Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
