jazzy_desktop
Build lightning-fast, cross-platform desktop applications using Nim and modern web technologies.
Summary
| Latest Version | 0.1.1 |
|---|---|
| License | MIT |
| CI Status | Failing |
| Downloads | 0 |
| Last Indexed | 2026-07-21 05:27 |
Tags
Authors
- Caner
Installation
nimble install jazzy_desktop
choosenim install jazzy_desktop
git clone https://github.com/canermastan/jazzy-desktop
OS Compatibility
| Platform | Linux | macOS | Windows | FreeBSD | OpenBSD | NetBSD | Android | iOS | WASM | Embedded |
|---|---|---|---|---|---|---|---|---|---|---|
| jazzy_desktop | ✓ | ✓ | ✓ | - | - | - | - | - | - | - |
Dependencies
| Package | Version | Optional |
|---|---|---|
| nim >= | 2.0.0 | No |
| jazzy >= | 0.4.4 | No |
Source
| Repository | https://github.com/canermastan/jazzy-desktop |
|---|---|
| Homepage | https://github.com/canermastan/jazzy-desktop |
| Registry Source | nimble_official |
README
Jazzy Desktop
Build modern desktop applications with Nim and your favourite web stack.
The desktop application framework for the Nim ecosystem — powered by Jazzy Framework under the hood.
Why Jazzy? • Features • Quick Start • Core Concepts • Native OS APIs • Web Mode • Roadmap
Why Jazzy Desktop?
The Nim ecosystem has GUI libraries — but they all make you think in widgets, layouts, and signals. It's 2026. Your users expect the web. Jazzy Desktop lets you build with the tools you already know: React, Vue, Svelte, plain HTML — anything that runs in a browser — while your backend is pure, compiled, blazing-fast Nim.
| NiGui | libui-ng (nim-libui) | fidget | Jazzy Desktop | |
|---|---|---|---|---|
| UI Model | Native widgets | Native widgets | OpenGL canvas | Web (HTML/CSS/JS) |
| Frontend | Nim only | Nim only | Nim only | React / Vue / Svelte / anything |
| Styling | OS-native | OS-native | Custom | Full CSS, animations, glassmorphism |
| IPC | — | — | — | Zero-config RPC + WebSockets |
| Web Deploy | ✗ | ✗ | ✗ | ✓ — same binary, zero changes |
| Hot-Reload | ✗ | ✗ | ✗ | ✓ |
Native GUI toolkits are powerful, but they come with constraints. Jazzy Desktop removes those constraints: your UI is a first-class web application backed by a native Nim process, communicating over a local Jazzy HTTP server. You get the rendering power of the browser, the raw speed of Nim, and a zero-config bridge between them.
Features
✨ Zero-Config RPC
Write a Nim function, annotate it with {.expose.}, and call it from JavaScript like a local function. The macro takes care of routing, type validation, and serialization automatically.
⚡ Blazing-Fast Native Binary
Your backend compiles to native machine code via Nim's C/C++ transpiler. Tiny memory footprint, instant startup time.
🔄 Two-Way Real-Time Events
Push data from Nim to your frontend at any time using the built-in WebSocket event bus — no polling, no complexity.
🖥️ Full Native OS Integration
Window management, system tray, native file dialogs, clipboard, single-instance lock, and Windows 11 Mica glass effect — all accessible from JavaScript.
🌐 Deploy as a Web App
Compile your desktop app into a pure web server with the --web flag. Zero code changes required.
🗄️ Built-in Local Settings Store
A built-in store.nim module persists user preferences (theme, language, window size…) in OS-appropriate config directories — AppData/Roaming on Windows, Library/Application Support on macOS, ~/.config on Linux.
🔥 Hot-Reload Development
jazzyd dev watches both your Nim backend and Vite frontend simultaneously, restarting only what changed.
Quick Start
Prerequisites
1. Install
nimble install jazzy_desktop
2. Create a New Project
jazzyd new my-awesome-app
cd my-awesome-app
3. Start Development
jazzyd dev
Both the Nim backend and the Vite frontend start together with Hot-Reload. Edit any file and see changes reflected instantly.
4. Build for Production
jazzyd build
Produces a single, self-contained executable with all frontend assets embedded inside via Nim's compile-time VFS.
Core Concepts
The {.expose.} Macro — RPC Made Trivial
This is the heart of Jazzy Desktop. Any Nim proc annotated with {.expose.} is automatically registered as an RPC endpoint callable from JavaScript — no routes, no fetch, no boilerplate.
Backend (src/app.nim):
import jazzy_desktop
# This function becomes directly callable from JavaScript.
proc greet(name: string, age: int): string {.expose.} =
return "Hello " & name & "! You are " & $age & " years old."
# Pass `ctx: Context` to access DB, headers, sessions.
# The macro knows not to expect `ctx` from the JS payload.
proc saveSettings(ctx: Context, theme: string): bool {.expose.} =
storeSet("theme", %theme)
return true
startDesktopApp(
title = "My Awesome App",
width = 1200,
height = 800,
devUrl = "http://localhost:5173",
prodDir = "../frontend/dist"
)
Frontend (frontend/src/App.jsx):
import { jazzy } from './jazzy';
// Calling Nim feels exactly like calling a local async function.
const message = await jazzy.greet("Caner", 25);
// → "Hello Caner! You are 25 years old."
await jazzy.saveSettings("dark-mode");
Two-Way Events — Pushing Data from Nim to the Frontend
Emit real-time data from a background Nim thread directly to your React components via the built-in WebSocket event bus.
Nim side:
import jazzy_desktop/events
proc runHeavyTask() {.expose.} =
for i in 1..100:
emit("progress", %*{"value": i})
sleep(50)
JavaScript side:
import { jazzy } from './jazzy';
// Subscribe on component mount
jazzy.on("progress", (data) => {
setProgress(data.value);
});
// Clean up on unmount
jazzy.off("progress");
Native OS APIs
All native capabilities are exposed to your JavaScript frontend via the window-level bridge injected by Jazzy's WebView layer.
💻 Window Management
jazzyWindowMinimize(); // Minimize to taskbar
jazzyWindowMaximize(); // Maximize window
jazzyWindowRestore(); // Restore from maximized state
jazzyWindowHide(); // Hide window and taskbar entry
jazzyWindowShow(); // Bring back to foreground
jazzyWindowCenter(); // Center on the current monitor
Build fully frameless windows with native drag support and Windows 11 Mica backdrop blur effect — no additional configuration required.
📂 Native File Dialogs
import jazzy_desktop/dialogs
# Open dialog — pick an existing file
let file = selectFileDialog(
"Choose an Image",
@[DialogFilter(name: "Images", extensions: "*.png;*.jpg;*.webp")],
multiSelect = false,
forSave = false
)
# Save dialog — choose where to write a new file
let dest = selectFileDialog(
"Save Export",
@[DialogFilter(name: "PDF", extensions: "*.pdf")],
multiSelect = false,
forSave = true
)
Supports open dialogs, save dialogs, folder pickers, and native OS message boxes.
🔔 System Tray
Add your app to the system tray notification area (bottom-right corner on Windows) with a fully native right-click context menu, driven from jazzy_desktop/tray.
📋 Clipboard & Browser
import jazzy_desktop/clipboard
import jazzy_desktop/browser
writeClipboard("Copied from Nim!")
let text = readClipboard()
# Open in the user's default browser, not inside the WebView
openBrowser("https://nim-lang.org")
🔒 Single Instance Lock
enforceSingleInstance()
# Prevents duplicate app launches.
# Focuses the existing window instead of opening a second one.
Web Mode
Jazzy Desktop is built on top of the Jazzy Framework — a fast, production-ready Nim web framework. When you build a Jazzy Desktop app, a local Jazzy HTTP server runs in the background, serving your RPC endpoints, handling WebSocket events, and powering the optional ORM layer.
This means your app can be deployed as a standard web application with a single CLI flag — without touching your application code.
# Develop in the browser (no native window opened)
jazzyd dev --web
# Build a standalone web server binary for deployment
jazzyd build --web
The resulting binary can run on a Linux VPS, listen on port 8080, and serve behind Nginx like any conventional web app. Your desktop UI and business logic are shared 100% between both targets.
Project Structure
my-app/
├── frontend/ # Vite-powered frontend (React / Vue / Svelte)
│ ├── src/
│ │ ├── App.jsx
│ │ └── jazzy.js # RPC client (JS Proxy, auto-generated)
│ └── vite.config.ts
│
├── src/
│ └── app.nim # Entry point — expose procs, start the app
│
└── my-app.nimble
Configuration
startDesktopApp(
title = "My App",
width = 1200,
height = 800,
devUrl = "http://localhost:5173",
prodDir = "../frontend/dist",
port = 7654, # Internal HTTP server port (default: 7654)
maxUploadSizeMb = 50 # File upload limit in MB (default: 10)
)
Roadmap
- [x] Zero-config
{.expose.}RPC macro with type validation - [x] Native WebView2 / WebKit integration
- [x] Window management API (minimize, maximize, center, frameless, Mica)
- [x] System Tray with native context menus
- [x] Native file open/save/folder dialogs
- [x] Clipboard & external browser support
- [x] Single-instance lock
- [x] Two-way WebSocket event bus
- [x] Hot-reload dev server (
jazzyd dev) - [x] Single-EXE production build with embedded frontend (VFS)
- [x]
--webflag for zero-change web deployment - [x] Built-in local settings store (
store.nim) - [x]
jazzyd newproject scaffolding CLI - [ ] macOS full support (native window controls, app bundle, code signing)
- [ ] OS-level dark/light mode detection API
- [ ] Native notification (OS toast / notification center)
- [ ] Global keyboard shortcuts (system-wide hotkeys)
- [ ] Screen & multi-monitor info API
- [ ] App auto-updater integration
Contributing
Jazzy Desktop is a young project and there is meaningful work ahead. Contributions are very welcome — especially around macOS support, new native APIs, and async macro improvements. Check the roadmap above for good first-contribution candidates.