Your desktop.
Your widgets.

A customizable widget-based desktop dashboard for Linux. Drop in plugins, arrange them freely, and make your desktop work for you.

Linux native (Qt 6) 12 built-in widgets Plugin SDK for custom widgets AppImage & Flatpak releases
Dashboard running with clock, calendar, weather, pomodoro, system status, htop, AI chat, links, todo, and logtail widgets
Dashboard canvas with multiple widgets arranged freely

Arrange widgets your way

Drag any widget card to reposition it, grab its edge to resize. The canvas remembers your layout and restores it exactly on next launch.

Add Widget dialog listing all available plugins including AI Chat, Calendar, Clock, Countdown, Links, Notes, Pomodoro, System Status, and more

Add widgets instantly

Click Add Widget to see every installed plugin. Drop a .so into the plugins/ folder and it shows up here immediately — no restart required.

Built for flexibility

🧩

Runtime plugin system

Drop a .so into the plugins/ directory and it appears instantly in the Add Widget dialog — no restart needed.

🖱️

Free-form canvas

Drag and resize widget cards anywhere on screen. Layout and widget state persist automatically across restarts.

🎨

Customizable appearance

Frameless window with a custom title bar. Set a solid background color with opacity or use your own wallpaper image.

📦

AppImage & Flatpak

AppImage: one portable file, no install needed. Flatpak: sandboxed and integrated with GNOME/KDE Software. Both bundle all 12 widgets and Qt.

12 widgets, ready to use

Every widget is a standalone plugin with its own repository. Mix and match, or build your own.

🕐

Clock

Current time (HH:MM:SS) updated every second.

📅

Calendar

Monthly calendar with dark styling and keyboard navigation.

Todo

Persistent checklist — add items with Enter, right-click to delete.

📝

Notes

Sticky note backed by a plain text editor. Content saved automatically.

🍅

Pomodoro

25 min / 5 min focus timer. Pause state survives restarts.

Countdown

Days remaining to a user-specified target date with a configurable label.

🔗

Links

Editable bookmark list. Click a link to open it in your default browser.

🌤️

Weather

Current conditions from Open-Meteo — no API key required. Search by city, toggle °C / °F.

No API key
📊

System Status

Live CPU%, memory%, disk%, and network rates read from /proc.

⚙️

Htop

Per-core CPU bars, memory bar, and a sorted process table.

🤖

AI Chat

Multi-turn chat via the OpenAI API. Configurable model, system prompt, and API key.

OpenAI API
📋

Log Tail

Tail any log file or the systemd journal with a configurable unit filter and line buffer.

Up and running in seconds

Choose the format that fits your workflow. Both are available on the releases page.

AppImage

Portable
1

Download

Grab Dashboard-*.AppImage from the releases page.

2

Make it executable

chmod +x Dashboard-*.AppImage
3

Run

Double-click, or from the terminal:

./Dashboard-*.AppImage

Flatpak

Sandboxed
1

Download

Grab Dashboard-*.flatpak from the releases page.

2

Install

flatpak install Dashboard-*.flatpak
3

Run

From your app launcher, or from the terminal:

flatpak run io.github.duh_dashboard.Dashboard

Build your own widget

Any shared library that implements IWidget is a valid plugin. The SDK handles the rest.

Quick start

Install the SDK and use the scaffolding script to generate a complete widget skeleton:

# Install widget-sdk
cmake -S widget-sdk -B build/sdk \
  -DCMAKE_INSTALL_PREFIX=~/.local
cmake --build build/sdk
cmake --install build/sdk

# Generate boilerplate
python3 widget-sdk/create-widget.py my-widget

This produces a fully self-contained CMake project ready to build and load into Dashboard.

The IWidget interface

Implement three methods and you have a working widget:

class MyWidget : public QWidget,
                 public IWidget {
  Q_OBJECT
  Q_PLUGIN_METADATA(IID IWidget_iid
                    FILE "my-widget.json")
  Q_INTERFACES(IWidget)
public:
  QString name() const override;
  QWidget* createWidget(
    WidgetContext*, QWidget* parent
  ) override;
  void saveState(QJsonObject&) override;
  void loadState(const QJsonObject&) override;
};

See the full guide in the widget-sdk repository.

All repositories