{"id":46786,"date":"2024-01-10T00:00:00","date_gmt":"2024-01-10T08:00:00","guid":{"rendered":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/"},"modified":"2025-11-13T12:56:50","modified_gmt":"2025-11-13T20:56:50","slug":"building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb","status":"publish","type":"post","link":"https:\/\/griddb.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/","title":{"rendered":"Building a Desktop WiFi Network Monitor with Tauri, React, Node.js, and GridDB"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>In this article, we will delve into the process of constructing a Desktop WiFi Network Monitor, intricately weaving together technologies like <strong>Node.js<\/strong>, <strong>Tauri<\/strong>, and <strong>React<\/strong>. Central to our architectural decisions is the emphasis on using <strong>GridDB<\/strong> for our storage needs.<\/p>\n<p>But why GridDB? As we navigate through the intricacies of WiFi network monitoring, the choice of a reliable and efficient storage mechanism becomes paramount. GridDB, with its unique features and optimized performance characteristics, emerges as an ideal candidate. Paired with the versatility of Node.js, the rich user interface capabilities of React, and the cross-platform advantages of Tauri, we aim to present a holistic approach to effective network monitoring.<\/p>\n<h2>Source Code<\/h2>\n<p>There are a few steps to set up the project:<\/p>\n<h3>Preparation<\/h3>\n<p>This source code was tested on Windows 11 and with Ubuntu 20.04 on WSL2 and heavily depends on the native packet capture, which is <strong>Npcap<\/strong> on Windows.<\/p>\n<blockquote>\n<p>Before installing, ensure that your Windows system has a WiFi device. Please note that this project has only been tested with one WiFi device.<\/p>\n<\/blockquote>\n<h4>Install Npcap<\/h4>\n<p><a href=\"https:\/\/npcap.com\/\">Npcap<\/a> is a packet capture and sending library for Microsoft Windows. We need to install this software first so that later we can use it with the node.js npm package, such as <a href=\"https:\/\/github.com\/mscdex\/cap\"><code>cap<\/code><\/a>, to perform packet capturing.<\/p>\n<p>To download Npcap, please visit <a href=\"https:\/\/npcap.com\/#download\">their site<\/a> and choose the appropriate installer type for a hassle-free installation. Upon installation, leave every option at its default.<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/npcap-windows.png\"><img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/npcap-windows.png\" alt=\"\" width=\"499\" height=\"388\" class=\"aligncenter size-full wp-image-29893\" srcset=\"\/wp-content\/uploads\/2024\/01\/npcap-windows.png 499w, \/wp-content\/uploads\/2024\/01\/npcap-windows-300x233.png 300w\" sizes=\"(max-width: 499px) 100vw, 499px\" \/><\/a><\/p>\n<h3>Clone the Source Code on Windows<\/h3>\n<p>Clone the source code from this <a href=\"https:\/\/github.com\/junwatu\/bearsakura-netwatch\">GitHub repository<\/a>.<\/p>\n<p>There will be two servers running on different operating systems. The first one is the <strong>Node.js<\/strong> server that acts like a forwarder that will run on Windows, we callled <strong>Node.js Forwarder<\/strong>, and the second one is the <strong>Node.js<\/strong> server that connects to <strong>GridDB<\/strong> that will run on Linux.<\/p>\n<p>The <strong>Node.js Forwarder<\/strong> will capture the WiFi network traffic and send it to the <strong>Node.js<\/strong> server on Linux. The <strong>Node.js<\/strong> server on Linux will store the captured packets and save them in the database and also will serve the data to the <strong>Tauri<\/strong> desktop application.<\/p>\n<h4>Node.js Forwarder<\/h4>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">git clone git@github.com:junwatu\/bearsakura-netwatch.git<\/code><\/pre>\n<\/div>\n<p>Go to the <code>server<\/code> directory and install all the dependencies.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">cd server\nnpm install<\/code><\/pre>\n<\/div>\n<p>To capture packets in this project, we use the <code>cap<\/code> npm package that requires <code>node-gyp<\/code> to build the native module. This native module is the bridge between Node.js and Npcap. When we run <code>npm install<\/code>, it automatically creates the native module. To make sure it works, you can install it globally.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">npm install -g node-gyp<\/code><\/pre>\n<\/div>\n<p>However, the <code>node-gyp<\/code> itself has dependencies, like Python and a C++ compiler, which must be installed on the system to work correctly. Please read the <a href=\"https:\/\/www.npmjs.com\/package\/node-gyp#on-windows\">node-gyp Windows documentation guide<\/a>.<\/p>\n<h4>Configure <code>env<\/code><\/h4>\n<p>Configure the <code>.env<\/code> file, and change the port if you have to. These are the default values:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">PACKET_PORT=5000\nDATABASE_SERVER_PORT=4000<\/code><\/pre>\n<\/div>\n<ul>\n<li><code>PACKET_PORT<\/code> is where the port of Node.js forwarder on Windows listens to. Change this if necessary.<\/li>\n<li><code>DATABASE_SERVER_PORT=4000<\/code> is where the port of the Node.js server on Linux listens to.<\/li>\n<\/ul>\n<h4>Run the forwarder<\/h4>\n<p>This command will run the Node.js forwarder on Windows:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">npm run dev<\/code><\/pre>\n<\/div>\n<h3>Clone the Source Code on Linux<\/h3>\n<p>Clone the source code from this <a href=\"https:\/\/github.com\/junwatu\/bearsakura-netwatch\">GitHub repository<\/a>. Go to the <code>server-db<\/code> directory and install all the dependencies.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">cd server-db\nnpm install<\/code><\/pre>\n<\/div>\n<h4>Configure <code>env<\/code> for the server on Linux<\/h4>\n<p>Configure the <code>.env<\/code> file and change the port if necessary. This is the default value:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">DATABASE_SERVER_PORT=4000<\/code><\/pre>\n<\/div>\n<p>Make sure this port matches with the <code>.env<\/code> configuration on the <strong>Node.js Forwarder<\/strong>. For example, if the <code>.env<\/code> configuration is <code>DATABASE_SERVER_PORT=3000<\/code>, this port should be <code>3000<\/code> too.<\/p>\n<h4>Run the server on Linux<\/h4>\n<p>This command will run the server on Linux:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">npm run dev<\/code><\/pre>\n<\/div>\n<h3>Run the desktop monitor<\/h3>\n<p>Download the desktop binary file from <a href=\"https:\/\/github.com\/junwatu\/bearsakura-netwatch\/releases\/download\/v0.1.0\/BearWatch_0.1.0_x64-setup.exe\">here<\/a>. Run the installer and go to the installation directory.<\/p>\n<p>Open the <code>config.json<\/code> file:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">\n{\n    \"api\": {\n        \"base_url\": \"http:\/\/localhost:4000\"\n    }\n}<\/code><\/pre>\n<\/div>\n<p>Make sure the <code>base_url<\/code> port is match with the <code>.env<\/code> configuration <code>DATABASE_SERVER_PORT=4000<\/code>.<\/p>\n<p>For example, if the <code>.env<\/code> configuration have <code>DATABASE_SERVER_PORT=3000<\/code> then the <code>base_url<\/code> should be <code>http:\/\/localhost:3000<\/code>.<\/p>\n<p>Run the desktop application, double click <code>BearWacth.exe<\/code>:<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/desktop.png\"><img decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/desktop.png\" alt=\"\" width=\"852\" height=\"632\" class=\"aligncenter size-full wp-image-29891\" srcset=\"\/wp-content\/uploads\/2024\/01\/desktop.png 852w, \/wp-content\/uploads\/2024\/01\/desktop-300x223.png 300w, \/wp-content\/uploads\/2024\/01\/desktop-768x570.png 768w, \/wp-content\/uploads\/2024\/01\/desktop-600x445.png 600w\" sizes=\"(max-width: 852px) 100vw, 852px\" \/><\/a><\/p>\n<h2>System Architecture<\/h2>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/system-arch.png\"><img decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/01\/system-arch.png\" alt=\"\" width=\"1357\" height=\"802\" class=\"aligncenter size-full wp-image-29890\" srcset=\"\/wp-content\/uploads\/2024\/01\/system-arch.png 1357w, \/wp-content\/uploads\/2024\/01\/system-arch-300x177.png 300w, \/wp-content\/uploads\/2024\/01\/system-arch-1024x605.png 1024w, \/wp-content\/uploads\/2024\/01\/system-arch-768x454.png 768w, \/wp-content\/uploads\/2024\/01\/system-arch-600x355.png 600w\" sizes=\"(max-width: 1357px) 100vw, 1357px\" \/><\/a><\/p>\n<p>Within the architecture of the Desktop WiFi Network Monitor, <strong>Npcap<\/strong> stands out as a powerful packet capture module optimized for Windows OS. This utility continuously fetches WiFi network packets, subsequently channeling them to our dedicated <strong>Node.js Forwarder<\/strong>. This forwarder will then send the packets to the <strong>Node.js Server<\/strong> that will store the data in the <strong>GridDB<\/strong> database. The <strong>Node.js Server<\/strong> will also serve the data to the <strong>Desktop Database Monitor<\/strong> that will display the data on a desktop dashboard.<\/p>\n<h2>Capture Network Traffic<\/h2>\n<p>Capturing network traffic using Node.js typically involves native modules that interface with system-level libraries like <strong>libpcap<\/strong> (on Unix-like systems) or <strong>WinPcap\/Npcap<\/strong> (on Windows). For this post, we will use <strong>Windows OS<\/strong> and <strong>Npcap<\/strong>.<\/p>\n<h2>Backend Development with Node.js and GridDB<\/h2>\n<h3>Node.js<\/h3>\n<p>Node.js\u00c2\u00ae is an open-source, cross-platform JavaScript runtime environment. Download the Windows installer from <a href=\"https:\/\/nodejs.org\/en\/download\">here<\/a>. We will use the Node.js LTS v18.18.0 version. There are many ways to install Node.js in Windows, and please look into their <a href=\"https:\/\/nodejs.dev\/en\/\">documentation<\/a>. We can use 3rd party Windows package installer such as <a href=\"https:\/\/chocolatey.org\/\">chocolatey<\/a> or use the manual installation.<\/p>\n<p>You can check the Node.js installation in the terminal by running this command:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">node --version<\/code><\/pre>\n<\/div>\n<h3>GridDB<\/h3>\n<p>GridDB is a highly scalable NoSQL database specifically tailored for time-series data. Rooted in its unique architecture, it offers both in-memory and disk-based storage, ensuring optimized performance and data durability. Its architecture is designed to handle massive volumes of data, making it a preferred choice for IoT, telemetry, and any application where time-based data is crucial. Beyond its core features, GridDB boasts advanced functions like automatic partitioning and robust failover mechanisms, ensuring data consistency and high availability.<\/p>\n<p>Go to the <a href=\"https:\/\/docs.griddb.net\">Official GridDB website<\/a> for installation information.<\/p>\n<h3>Packet Capture with Node.js<\/h3>\n<p>The code for packet capture is pretty easy. The <code>startCapturing(ipAddress)<\/code> function will start the packet-capturing process. It will detect the WiFi interface and start capturing the packets. The <code>getPackets()<\/code> function will return the captured packets.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">import pkg from 'cap';\nconst { Cap, decoders } = pkg;\n\nconst PROTOCOL = decoders.PROTOCOL;\n\nlet packets = [];\n\nfunction startCapturing(ipAddress) {\n    const c = new Cap();\n    const device = Cap.findDevice(ipAddress);\n    const filter = 'ip';\n    const bufSize = 10 * 1024 * 1024;\n    const buffer = Buffer.alloc(65535);\n\n    const devices = Cap.deviceList();\n    const wifiDevice = devices.find(device => {\n        const description = device.description.toLowerCase();\n        return description.includes('wireless') || description.includes('wi-fi');\n    });\n\n    if (!wifiDevice) {\n        console.error('No Wi-Fi device found!');\n        process.exit(1);\n    }\n\n    const wifiInterfaceName = wifiDevice.name;\n    const linkType = c.open(wifiInterfaceName, filter, bufSize, buffer);\n\n    c.on('packet', function(nbytes, trunc) {\n        const ret = decoders.Ethernet(buffer);\n\n        if (ret.info.type === 2048) {\n            const decodedIP = decoders.IPV4(buffer, ret.offset);\n            const srcaddr = decodedIP.info.srcaddr;\n            const dstaddr = decodedIP.info.dstaddr;\n\n            let packetInfo = {\n                length: nbytes,\n                srcaddr: srcaddr,\n                dstaddr: dstaddr\n            };\n\n            if (decodedIP.info.protocol === PROTOCOL.IP.TCP) {\n                const decodedTCP = decoders.TCP(buffer, decodedIP.offset);\n                packetInfo.protocol = 'TCP';\n                packetInfo.srcport = decodedTCP.info.srcport;\n                packetInfo.dstport = decodedTCP.info.dstport;\n            } else if (decodedIP.info.protocol === PROTOCOL.IP.UDP) {\n                const decodedUDP = decoders.UDP(buffer, decodedIP.offset);\n                packetInfo.protocol = 'UDP';\n                packetInfo.srcport = decodedUDP.info.srcport;\n                packetInfo.dstport = decodedUDP.info.dstport;\n            }\n\n            packets.push(packetInfo);\n\n            \/\/ Limit the storage to the last 100 entries (or any other number)\n            if (packets.length > 100) packets.shift();\n        }\n    });\n}\n\nfunction getPackets() {\n    return packets;\n}\n\nexport { startCapturing, getPackets };<\/code><\/pre>\n<\/div>\n<p>This packet is hosted on <code>http:\/\/localhost:5000\/packets<\/code> (the port and host depend on the <code>.env<\/code> configuration settings). This Node.js server will act like a forwarder. It runs on Express.js and uses the <code>startCapturing<\/code> module to get the captured packets.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">\nimport 'dotenv\/config';\nimport express from 'express';\nimport bodyParser from 'body-parser';\nimport axios from 'axios';\nimport * as packetCapturer from '.\/packetCapturer.js';\n\nconst app = express();\napp.use(bodyParser.json());\n\nconst PORT = process.env.PACKET_PORT || 3000;\nconst HOST = process.env.PACKET_IP_ADDRESS || 'localhost';\nconst SERVER_DB_HOST = process.env.DATABASE_SERVER || 'localhost';\nconst SERVER_DB_PORT = process.env.DATABASE_SERVER_PORT || 4000;\n\npacketCapturer.startCapturing(process.env.PACKET_IP_ADDRESS);\n\nsetInterval(async () => {\n    const packets = packetCapturer.getPackets();\n    try {\n        await axios.post(`http:\/\/${SERVER_DB_HOST}:${SERVER_DB_PORT}\/save-packets`, packets);\n        console.log('Packets sent successfully');\n    } catch (error) {\n        console.error('Error sending packets:', error);\n    }\n}, 5000);  \/\/ Adjust the interval to your needs\n\n\napp.get('\/packets', (req, res) => {\n    res.json(packetCapturer.getPackets());\n});\n\napp.listen(PORT, HOST, () => {\n    console.log(`Server started on http:\/\/${HOST}:${PORT}`);\n});<\/code><\/pre>\n<\/div>\n<p>You can check the packets before sending to the Node.js server on Linux by opening <code>http:\/\/localhost:5000\/packets<\/code> in the browser. This forwarder will send packets to the Node.js server on Linux for every 5 seconds.<\/p>\n<h3>Node.js Server<\/h3>\n<p>The Node.js server is a simple Node.js server that runs on Linux and will receive the captured packets and store them in the GridDB database. The database server will run on <code>http:\/\/localhost:4000<\/code> (the port depends on the <code>.env<\/code> configuration settings).<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">import 'dotenv\/config';\nimport cors from 'cors';\nimport express from 'express';\nimport bodyParser from 'body-parser';\nimport* as griddb from '.\/griddbservice.js'\n\nconst app = express();\napp.use(cors());\napp.use(bodyParser.json());\n\nconst PORT = process.env.DATABASE_SERVER_PORT || 4000;\nconst HOST = process.env.DATABASE_SERVER || 'localhost';\n\napp.get(\n    '\/info', (req, res) = > { res.json({message : 'database server'}); });\n\napp.post(\n    '\/save-packets', async(req, res) = > {\n      const packets = req.body;\n\n      for (let packet of packets) {\n        const {length, srcaddr, dstaddr, protocol, srcport, dstport} = packet;\n        await griddb.saveData(\n            {length, srcaddr, dstaddr, protocol, srcport, dstport});\n      }\n\n      res.json({message : 'saved'});\n    });\n\napp.get('\/get-all-packets', async (req, res) => {\n  const packets = await griddb.getAllData();\n  res.json({packets});\n})\n\napp.listen(PORT, HOST, () => {\n    console.log(`Server started on http:\/\/${HOST}:${PORT}`);\n});<\/code><\/pre>\n<\/div>\n<p>The packets data will received via <code>POST<\/code> method on <code>\/save-packets<\/code> endpoint. The <code>saveData<\/code> function will save the data to the GridDB database.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">await griddb.saveData({length, srcaddr, dstaddr, protocol, srcport, dstport});<\/code><\/pre>\n<\/div>\n<p>The <code>getAllData<\/code> function will get all the data from the GridDB database. This data that will be send to the desktop application.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">app.get('\/get-all-packets', async (req, res) => {\n  const packets = await griddb.getAllData();\n  res.json({packets});\n})<\/code><\/pre>\n<\/div>\n<p>You can check the packets data by opening <code>http:\/\/localhost:4000\/get-all-packets<\/code> in the browser, to make sure the packets data is saved in the database.<\/p>\n<h2>Front-end Development with Tauri and React<\/h2>\n<h3>Tauri<\/h3>\n<p><a href=\"https:\/\/tauri.app\/\">Tauri<\/a> is a toolkit for building small, secure, and fast applications with web technologies. It&#8217;s a competitor to <a href=\"https:\/\/www.electronjs.org\/\">Electron<\/a>, aiming to provide a leaner and more performant solution for creating desktop applications with web front-ends. The core idea is to enable developers to use familiar web technologies while reducing the bloat and potential security issues associated with bundling a complete Chromium instance, which is what Electron does.<\/p>\n<p>Tauri is built in <a href=\"https:\/\/www.rust-lang.org\/\">Rust<\/a>, a memory-safe language and its core is a very lightweight webview rendering engine. This allows for significantly smaller binary sizes and lower resource usage compared to Electron. It also provides a strong security model by minimizing the necessary permissions and isolating the web content from the system.<\/p>\n<p>The motivation behind Tauri&#8217;s creation was to address the common criticisms of Electron regarding size, speed, and security while preserving the ease of development and cross-platform capabilities that web technologies provide.<\/p>\n<h3>React<\/h3>\n<p><a href=\"https:\/\/react.dev\/\">React<\/a> is a JavaScript library for building user interfaces, maintained by Facebook and a community of individual developers and companies. It was created to facilitate the development of complex, interactive UIs in an efficient and flexible manner. React&#8217;s <a href=\"https:\/\/reactjs.org\/docs\/faq-internals.html\">virtual DOM<\/a> further optimizes rendering and improves app performance. The declarative nature of React simplifies the code, making it easier to debug and manage. The component-based architecture allows developers to build encapsulated components that manage their own state, which can then be composed to make complex UIs. React also empowers developers with the ability to create web applications that can update and render efficiently in response to data changes.<\/p>\n<h3>Tauri and React<\/h3>\n<p>The code for the Tauri and React live in the <code>desktop<\/code> folder. To build it you need to install Rust and node.js. Please follow the <a href=\"https:\/\/tauri.app\/v1\/guides\/getting-started\/prerequisites\">Tauri installation guide<\/a> for more information.<\/p>\n<p>The main UI for desktop WiFi monitor is:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">import React, { useState, useEffect } from 'react'\nimport PacketVisualization from '.\/packet-visualization'\nimport { invoke } from \"@tauri-apps\/api\/tauri\";\n\nimport \".\/App.css\";\n\nfunction App() {\n  const [packetData, setPacketData] = useState(null)\n  const [apiBaseUrl, setApiBaseUrl] = useState(null)\n\n  useEffect(() => {\n    async function fetchPacketData() {\n      const config = await invoke('read_config');\n      const apiBaseUrlConfig = await invoke('get_api_base_url', { config: config });\n      const response = await fetch(`${apiBaseUrlConfig}\/get-all-packets`)\n      const data = await response.json()\n\n      setPacketData(data)\n      setApiBaseUrl(apiBaseUrlConfig)\n    }\n  \n    fetchPacketData()\n    \n    \/\/ fetch every 5 seconds\n    const intervalId = setInterval(fetchPacketData, 5000)  \n    \/\/ cleanup interval on component unmount\n    return () => clearInterval(intervalId)  \n  }, [])\n  \n\n  return (\n    &lt;div className=\"container\">\n      {packetData && &lt;packetvisualization data={packetData}>&lt;\/packetvisualization>}\n      &lt;p className='packet-server'>\n        Packet Server: {apiBaseUrl}\n      &lt;\/p>\n    &lt;\/div>\n  );\n}\n\nexport default App;<\/code><\/pre>\n<\/div>\n<p>This code invoke rust code that read our <code>config.json<\/code> configuration.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-javascript\">const config = await invoke('read_config');\nconst apiBaseUrlConfig = await invoke('get_api_base_url', { config: config });\nconst response = await fetch(`${apiBaseUrlConfig}\/get-all-packets`)<\/code><\/pre>\n<\/div>\n<p>The JavaScript code will call the rust code that reads the <code>config.json<\/code> file and get the <code>apiBaseUrl<\/code> configuration. The <code>apiBaseUrl<\/code> configuration is the <code>base_url<\/code> configuration in the <code>config.json<\/code> file.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-sh\">\n{\n    \"api\": {\n        \"base_url\": \"http:\/\/localhost:4000\"\n    }\n}<\/code><\/pre>\n<\/div>\n<p>This is the rust code that reads the <code>config.json<\/code> file:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-rust\">\n\/\/ Prevents additional console window on Windows in release, DO NOT REMOVE!!\n#![cfg_attr(not(debug_assertions), windows_subsystem = \"windows\")]\n\nuse std::fs;\nuse serde_json::Value;\n\n\/\/ Learn more about Tauri commands at https:\/\/tauri.app\/v1\/guides\/features\/command\n#[tauri::command]\nfn greet(name: &str) -> String {\n    format!(\"Hello, {}! You've been greeted from Rust!\", name)\n}\n\n#[tauri::command]\nfn read_config() -> Result&lt;String, String> {\n  let path = \"config.json\";\n  let config = fs::read_to_string(path).map_err(|e| e.to_string())?;\n  Ok(config)\n}\n\n#[tauri::command]\nfn get_api_base_url(config: String) -> Result&lt;String, String> {\n  let parsed_config: Value = serde_json::from_str(&config).map_err(|e| e.to_string())?;\n  let base_url = parsed_config\n    .get(\"api\")\n    .and_then(|api| api.get(\"base_url\"))\n    .and_then(|base_url| base_url.as_str())\n    .ok_or(\"Missing 'api.base_url' setting\")?;\n  Ok(base_url.to_string())\n}\n\nfn main() {\n    tauri::Builder::default()\n        .invoke_handler(tauri::generate_handler![greet, read_config, get_api_base_url])\n        .run(tauri::generate_context!())\n        .expect(\"error while running tauri application\");\n}<\/code><\/pre>\n<\/div>\n<p>Every custom method that we want to call from JavaScript must be registered in the <code>tauri::Builder::default().invoke_handler<\/code> method. For example, we want to call the <code>read_config<\/code> method from JavaScript, so we need to register it in the <code>tauri::Builder::default().invoke_handler<\/code> method.<\/p>\n<h2>Future Enhancements<\/h2>\n<p>The desktop WiFi monitor is a proof of concept, and there are many things that can be improved. Here are some of the future enhancements:<\/p>\n<ul>\n<li>Working on different machines<\/li>\n<li>Better packet visualization<\/li>\n<li>Better setup process and deployment<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Introduction In this article, we will delve into the process of constructing a Desktop WiFi Network Monitor, intricately weaving together technologies like Node.js, Tauri, and React. Central to our architectural decisions is the emphasis on using GridDB for our storage needs. But why GridDB? As we navigate through the intricacies of WiFi network monitoring, the [&hellip;]<\/p>\n","protected":false},"author":41,"featured_media":29754,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[121],"tags":[],"class_list":["post-46786","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Building a Desktop WiFi Network Monitor with Tauri, React, Node.js, and GridDB | GridDB: Open Source Time Series Database for IoT<\/title>\n<meta name=\"description\" content=\"Introduction In this article, we will delve into the process of constructing a Desktop WiFi Network Monitor, intricately weaving together technologies\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Building a Desktop WiFi Network Monitor with Tauri, React, Node.js, and GridDB | GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"og:description\" content=\"Introduction In this article, we will delve into the process of constructing a Desktop WiFi Network Monitor, intricately weaving together technologies\" \/>\n<meta property=\"og:url\" content=\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/\" \/>\n<meta property=\"og:site_name\" content=\"GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/griddbcommunity\/\" \/>\n<meta property=\"article:published_time\" content=\"2024-01-10T08:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-13T20:56:50+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/griddb.net\/wp-content\/uploads\/2023\/06\/system-arch.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1583\" \/>\n\t<meta property=\"og:image:height\" content=\"960\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"griddb-admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:site\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"griddb-admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/\"},\"author\":{\"name\":\"griddb-admin\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\"},\"headline\":\"Building a Desktop WiFi Network Monitor with Tauri, React, Node.js, and GridDB\",\"datePublished\":\"2024-01-10T08:00:00+00:00\",\"dateModified\":\"2025-11-13T20:56:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/\"},\"wordCount\":1566,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2023\/06\/system-arch.png\",\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/\",\"url\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/\",\"name\":\"Building a Desktop WiFi Network Monitor with Tauri, React, Node.js, and GridDB | GridDB: Open Source Time Series Database for IoT\",\"isPartOf\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2023\/06\/system-arch.png\",\"datePublished\":\"2024-01-10T08:00:00+00:00\",\"dateModified\":\"2025-11-13T20:56:50+00:00\",\"description\":\"Introduction In this article, we will delve into the process of constructing a Desktop WiFi Network Monitor, intricately weaving together technologies\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/#primaryimage\",\"url\":\"\/wp-content\/uploads\/2023\/06\/system-arch.png\",\"contentUrl\":\"\/wp-content\/uploads\/2023\/06\/system-arch.png\",\"width\":1583,\"height\":960},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website\",\"url\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/\",\"name\":\"GridDB: Open Source Time Series Database for IoT\",\"description\":\"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL\",\"publisher\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization\",\"name\":\"Fixstars\",\"url\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"contentUrl\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"width\":200,\"height\":83,\"caption\":\"Fixstars\"},\"image\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/griddbcommunity\/\",\"https:\/\/x.com\/GridDBCommunity\",\"https:\/\/www.linkedin.com\/company\/griddb-by-toshiba\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\",\"name\":\"griddb-admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g\",\"caption\":\"griddb-admin\"},\"url\":\"https:\/\/griddb.net\/en\/author\/griddb-admin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Building a Desktop WiFi Network Monitor with Tauri, React, Node.js, and GridDB | GridDB: Open Source Time Series Database for IoT","description":"Introduction In this article, we will delve into the process of constructing a Desktop WiFi Network Monitor, intricately weaving together technologies","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/","og_locale":"en_US","og_type":"article","og_title":"Building a Desktop WiFi Network Monitor with Tauri, React, Node.js, and GridDB | GridDB: Open Source Time Series Database for IoT","og_description":"Introduction In this article, we will delve into the process of constructing a Desktop WiFi Network Monitor, intricately weaving together technologies","og_url":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/","og_site_name":"GridDB: Open Source Time Series Database for IoT","article_publisher":"https:\/\/www.facebook.com\/griddbcommunity\/","article_published_time":"2024-01-10T08:00:00+00:00","article_modified_time":"2025-11-13T20:56:50+00:00","og_image":[{"width":1583,"height":960,"url":"https:\/\/griddb.net\/wp-content\/uploads\/2023\/06\/system-arch.png","type":"image\/png"}],"author":"griddb-admin","twitter_card":"summary_large_image","twitter_creator":"@GridDBCommunity","twitter_site":"@GridDBCommunity","twitter_misc":{"Written by":"griddb-admin","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/#article","isPartOf":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/"},"author":{"name":"griddb-admin","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233"},"headline":"Building a Desktop WiFi Network Monitor with Tauri, React, Node.js, and GridDB","datePublished":"2024-01-10T08:00:00+00:00","dateModified":"2025-11-13T20:56:50+00:00","mainEntityOfPage":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/"},"wordCount":1566,"commentCount":0,"publisher":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization"},"image":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2023\/06\/system-arch.png","articleSection":["Blog"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/","url":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/","name":"Building a Desktop WiFi Network Monitor with Tauri, React, Node.js, and GridDB | GridDB: Open Source Time Series Database for IoT","isPartOf":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/#primaryimage"},"image":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2023\/06\/system-arch.png","datePublished":"2024-01-10T08:00:00+00:00","dateModified":"2025-11-13T20:56:50+00:00","description":"Introduction In this article, we will delve into the process of constructing a Desktop WiFi Network Monitor, intricately weaving together technologies","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/blog\/building-a-desktop-wifi-network-monitor-with-tauri-react-node-js-and-griddb\/#primaryimage","url":"\/wp-content\/uploads\/2023\/06\/system-arch.png","contentUrl":"\/wp-content\/uploads\/2023\/06\/system-arch.png","width":1583,"height":960},{"@type":"WebSite","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website","url":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/","name":"GridDB: Open Source Time Series Database for IoT","description":"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL","publisher":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization","name":"Fixstars","url":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/","url":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","contentUrl":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","width":200,"height":83,"caption":"Fixstars"},"image":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/griddbcommunity\/","https:\/\/x.com\/GridDBCommunity","https:\/\/www.linkedin.com\/company\/griddb-by-toshiba"]},{"@type":"Person","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233","name":"griddb-admin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g","caption":"griddb-admin"},"url":"https:\/\/griddb.net\/en\/author\/griddb-admin\/"}]}},"_links":{"self":[{"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/posts\/46786","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/comments?post=46786"}],"version-history":[{"count":1,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/posts\/46786\/revisions"}],"predecessor-version":[{"id":51449,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/posts\/46786\/revisions\/51449"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/media\/29754"}],"wp:attachment":[{"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/media?parent=46786"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/categories?post=46786"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/griddb.net\/en\/wp-json\/wp\/v2\/tags?post=46786"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}