?? Building a Cross-Platform Memory Monitor App with Go, Wails, and TailwindCSS: My Journey in Crafting a Real-Time UI
As developers, we're always looking for efficient ways to monitor system performance and create seamless user experiences across different platforms. Recently, I decided to build a cross-platform memory monitor app using Go and Wails, leveraging TailwindCSS for the UI. The goal? A lightweight, real-time memory usage monitor that works on macOS, Windows, and Linux (Ubuntu) and boost my software development skills.
Here's a deep dive into my experience and how you can build a similar app. Let's go! ??
So why I want to use wails ? I am a full stack web developer and I use React a lot. So this is a good point to use some of my knowledge in project.
First of all I need to install Wails. Checkout the document and install wails-cli:
go install github.com/wailsapp/wails/v2/cmd/wails@latest
Now init the application with wails-cli:
wails init -n gitlab.com/naHDop/sys-monitor -t react-ts
??? Step 1: Collecting Memory Usage Data with Go
The first step was grabbing system memory data in real-time. I used the gopsutil library in Go to fetch metrics like total memory, used memory, and free memory. I include code into generated (by wails-cli) file `app.go -> func startup` Here's a quick look at how I collected the data:
// startup is called at application startup
func (a *App) startup(ctx context.Context) {
// Perform your setup here
a.ctx = ctx
// Use a ticker to send memory updates to the frontend
go func() {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
v, _ := mem.VirtualMemory()
// Send memory data to frontend
runtime.EventsEmit(ctx, "memoryUpdate", v.Total/1024/1024, v.Used/1024/1024, v.Free/1024/1024, v.UsedPercent)
}
}
}()
}
?? Step 2: Switching to Wails for Modern UI Flexibility
Once the backend logic was up and running, I turned to Wails for building the front-end. Wails lets you build native desktop apps using modern web technologies like React and TailwindCSS while using Go for the backend.
This was a game-changer! With Wails, I could leverage React for the dynamic UI and have real-time updates for the memory data.
?? Real-Time Data Visualization with React and TailwindCSS
Using Recharts in React, I built a real-time line chart to visualize memory usage. So you need to install in in frontend foler
cd frontend
npm i recharts
Here’s how the core UI component looks (frontend/src/App.tsx):
领英推荐
import './App.css'
import { useEffect, useState } from "react";
import { EventsOn } from "../wailsjs/runtime";
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from "recharts";
function App() {
const [memoryData, setMemoryData] = useState([{
timestamp: new Date().toLocaleTimeString(),
usedPercent: 0,
}]);
const [stats, setStats] = useState({
total: 0,
used: 0,
free: 0,
usedPercent: 0,
});
useEffect(() => {
// Subscribe to the memoryUpdate event from Go backend
EventsOn("memoryUpdate", (total, used, free, usedPercent) => {
const timestamp = new Date().toLocaleTimeString();
setStats({ total, used, free, usedPercent })
// Append new memory usage data to the chart
setMemoryData((prevState) => {
// Ensure the previous data is being accumulated and sliced correctly
const newData = [...prevState, { timestamp, usedPercent }];
return newData.slice(-60); // Keep the last 60 points (for example, 60 seconds of data)
})
});
}, []);
return (
<div className="min-h-screen bg-gray-100 p-6">
{/* Header */}
<header className="mb-8">
<h1 className="text-3xl font-semibold text-gray-800 text-center">
Memory Monitor Dashboard
</h1>
</header>
{/* Memory Stats */}
<div className="grid grid-cols-1 sm:grid-cols-3 lg:grid-cols-3 gap-6 mb-8">
<div className="p-4 bg-white shadow-lg rounded-lg">
<h2 className="text-m font-medium text-gray-600">Total Memory</h2>
<p className="text-xl font-semibold text-gray-900">{stats.total} MB</p>
</div>
<div className="p-4 bg-white shadow-lg rounded-lg">
<h2 className="text-m font-medium text-gray-600">Used Memory</h2>
<p className="text-xl font-semibold text-gray-900">{stats.used} MB</p>
</div>
<div className="p-4 bg-white shadow-lg rounded-lg">
<h2 className="text-m font-medium text-gray-600">Memory Usage</h2>
<p className="text-xl font-semibold text-gray-900">{`${stats.usedPercent.toFixed(2)}%`}</p>
</div>
</div>
{/* Line Chart */}
<div className="p-4 bg-white shadow-lg rounded-lg">
<h2 className="text-s font-medium text-gray-600 mb-4">Memory Usage (%)</h2>
<ResponsiveContainer width="100%" height={200}>
<LineChart data={memoryData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="timestamp" />
<YAxis domain={[0, 100]} />
<Tooltip />
<Line type="monotone" dataKey="usedPercent" stroke={stats.usedPercent > 75 ? "#d88884" : "#8884d8"} strokeWidth={2} dot={false} />
</LineChart>
</ResponsiveContainer>
</div>
</div>
)
}
export default App
This component dynamically updates every second, displaying memory usage as it changes. TailwindCSS made styling this super smooth and easy! ?
? Challenges Faced and Solutions
Of course, no development journey is complete without its challenges. Here are some issues I faced and how I overcame them:
?? Key Learnings from this Experience
This project was an incredible learning experience for me, and here are my key takeaways:
?? Conclusion
In the end, building this cross-platform memory monitor app was a rewarding experience. I pushed the boundaries of what Go can do in the desktop space, integrated modern web technologies, and created a real-time, visually appealing tool.
Whether you're building cross-platform apps or just exploring Go with modern UIs, I highly recommend Wails for a smooth, developer-friendly experience.
If you're interested in trying this out or have questions, feel free to connect! I'd love to discuss more about Go, Wails, or building cross-platform applications.