Skip to content

Convert neohtop to Extension

neohtop is a beautiful desktop version of the htop command.

A modern, cross-platform system monitor built on top of Svelte, Rust, and Tauri.

In this blog, I will talk about how I converted neohtop to an extension.

It maybe simpler than you think.

TC;SC

Here is a screenshot of the extension, exactly the same as the desktop version.

Intro

neohtop is a Tauri app. It’s frontend is built with Svelte, and backend is built with Rust.

One of the reasons I created kunkun is to make it easy to write cross-platform apps and distribute them on different platforms.

And neohtop is a perfect example for this.

It’s a nice GUI wrapper over the sysinfo crate. See its Cargo.toml.

Luckily, Kunkun’s extension API also provides a sysInfo API, see docs. It is based on tauri-plugin-system-info, which is also a wrapper over the sysinfo crate. See Cargo.toml.

Since the data source are the same, then it should be straightforward to convert it to an extension.

I set a 30 minutes goal for myself, but it took me 90 minutes to complete the conversion. This is because neohtop did its data aggregation and preprocessing in rust, and I need to convert the logic to TypeScript. Kind of like how TypeScript is converted to Golang, I just needed to convert the rust code to TypeScript, not hard at all, just time-consuming.

Code

In this PR, I demonstrated all the changes I made for the conversion.

First of all, neohtop is written in frontend framework svelte, so obviously this is a custom UI extension.

Manifest

package.json

package.json
"kunkun": {
"name": "neohtop",
"shortDescription": "A modern, cross-platform system monitor",
"longDescription": "A modern, cross-platform system monitor",
"identifier": "neohtop",
"demoImages": [
"https://imgur.com/D8VHDEz.png"
],
"permissions": [
"system-info:all",
"shell:kill-any"
],
"icon": {
"type": "remote-url",
"value": "https://github.com/Abdenasser/neohtop/raw/main/app-icon.png"
},
"customUiCmds": [
{
"name": "neohtop",
"main": "/",
"dist": "build",
"devMain": "http://localhost:1420",
"cmds": [],
"window": {
"title": "Neohtop",
"hiddenTitle": true,
"titleBarStyle": "overlay",
"width": 1400,
"height": 1000
}
}
]
},
  • build folder is the default output folder of svelte projects, thus dist is set to build.
  • devMain is the local server that serves the svelte project, it is used when developing the extension with HMR.
  • system-info:all permission is required to access the system info data.
  • shell:kill-any permission is required to kill any process by a pid.

Frontend

neohtop has no default window title bar, but users can drag the window by clicking on the top of the app. This is achieved by simply including data-tauri-drag-region in a div element.

<div class="title-bar" data-tauri-drag-region></div>

In a KK extension, we use data-kunkun-drag-region instead, just remember to call ui.registerDragRegion in app initialization.

TitleBar.svelte
<div class="title-bar" data-tauri-drag-region>
<div class="title-bar" data-kunkun-drag-region>
+page.svelte
import { ui } from "@kksh/api/ui/custom";
onMount(() => {
ui.registerDragRegion("kunkun");
});

Data Preprocessing/Aggregation

This is the most time-consuming part.

The source system info data is preprocessed before rendering. The preprocessing logic is written in Rust, thus I need to convert them to TypeScript.

neohtop (Rust)kunkun-ext-neohtop (TypeScript)
process_monitor.rsprocessMonitor.ts
system_monitor.rssystemMonitor.ts

Acknowledgements