Nimbus is an ultra-lightweight, premium cross-platform desktop productivity and health companion that lives entirely in your system tray/menu bar. Designed with contemporary macOS and Apple-utility aesthetics in mind, Nimbus helps you maintain an optimal focus rhythm, prevent burnout, and manage your daily streaks using Pomodoro-based focus periods, native OS notifications, and zero-asset programmatically synthesized ambient audio alerts.
Productivity β’ Wellness β’ Pomodoro β’ Desktop Utility
View all releases & alternative formats
To run Nimbus as a standalone desktop utility on your system:
nimbus_0.1.0_x64-setup.exe or .msi.nimbus_0.1.0_x64.dmg.nimbus_0.1.0_aarch64.dmg.Nimbus is designed to look like a premium, integrated desktop utility, sitting seamlessly on top of other applications.
The main panel utilizes a sharp rectangular metallic surface, customized with centered Lucide-style vector controls, today's statistics, and a linear gradient circular progress ring.
Upon launch, Nimbus minimizes into the Windows system tray. The tray icon uses your custom leaf-cloud logo πΏ and opens the dashboard on left-click.
Clicking the settings gear button slides in a modal overlay, featuring custom Web Audio-styled sliders, translucent thin scrollbars, and switches to toggle notifications and zen soundscapes.
Nimbus bridges SvelteKit's static client views with a highly-secure Rust core using Tauri v2 capability permissions:
graph TD
subgraph Frontend [SvelteKit + Svelte 5 + Tailwind v4]
UI[Glassmorphic Tray Window]
Store[Svelte Runes State Engine]
Audio[Web Audio Calming Synthesizer]
end
subgraph Backend [Tauri v2 + Rust Core]
Tray[System Tray Icon & Menu]
WinMgr[Screen Position & Blur Hiding]
StorePlg[Tauri Store Plugin]
NotifPlg[Tauri Notification Plugin]
end
UI <--> Store
Store <--> StorePlg
Store <--> NotifPlg
Tray --> WinMgr
WinMgr --> UI
src-tauri/src/lib.rs)The Rust backend tracks system tray events, handles window focus loss (blur), and calculates screen coordinates:
// Helper function to position the window at the bottom-right corner, just above the taskbar.
fn position_window(window: &tauri::WebviewWindow) {
if let Ok(Some(monitor)) = window.primary_monitor() {
let scale_factor = monitor.scale_factor();
let monitor_size = monitor.size();
let monitor_pos = monitor.position();
let window_width = (360.0 * scale_factor) as u32;
let window_height = (520.0 * scale_factor) as u32;
let padding_x = (16.0 * scale_factor) as i32;
let padding_y = (60.0 * scale_factor) as i32;
let x = monitor_pos.x + (monitor_size.width as i32) - (window_width as i32) - padding_x;
let y = monitor_pos.y + (monitor_size.height as i32) - (window_height as i32) - padding_y;
let _ = window.set_position(tauri::PhysicalPosition::new(x, y));
}
}
Focus loss triggers automatic hiding in the background:
// Setup blur hiding (auto-hide when clicking outside)
let w = window.clone();
window.on_window_event(move |event| {
if let tauri::WindowEvent::Focused(false) = event {
let _ = w.hide();
}
});
src/lib/stores/timer.svelte.ts)We use Svelte 5's $state and $derived inside a TypeScript class to govern our Pomodoro state machine:
export class TimerEngine {
// Svelte 5 runes for premium reactive state
state = $state<TimerState>('work');
status = $state<'idle' | 'running' | 'paused'>('idle');
timeLeft = $state<number>(25 * 60);
durationWork = $state<number>(25);
// Derived values are automatically calculated on state change
totalDuration = $derived(
this.state === 'work' ? this.durationWork * 60 :
this.state === 'shortBreak' ? this.durationShortBreak * 60 :
this.durationLongBreak * 60
);
}
On transition boundaries, Svelte synthesizes an arpeggiated A Major chord (A4, C#5, E5) programmatically, staggering notes to create a zither strum:
public playCalmingChime() {
if (!this.soundEnabled) return;
try {
const AudioContextClass = window.AudioContext || (window as any).webkitAudioContext;
const ctx = new AudioContextClass();
const now = ctx.currentTime;
const frequencies = [440.00, 554.37, 659.25]; // A Major Chord
frequencies.forEach((freq, idx) => {
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.type = 'sine';
osc.frequency.setValueAtTime(freq, now + idx * 0.12); // Stagger notes
// Envelope: Fast attack, slow exponential decay
gain.gain.setValueAtTime(0, now + idx * 0.12);
gain.gain.linearRampToValueAtTime(0.12, now + idx * 0.12 + 0.08);
gain.gain.exponentialRampToValueAtTime(0.0001, now + idx * 0.12 + 2.4);
osc.connect(gain);
gain.connect(ctx.destination);
osc.start(now + idx * 0.12);
osc.stop(now + idx * 0.12 + 2.6);
});
} catch (e) { console.error(e); }
}
src/routes/layout.css)To prevent the Webview2 layout container from displaying standard white background borders, custom overrides force transparency:
/* Force Webview transparency on all root containers to eliminate white corners */
html, body, #svelte, [style*="display: contents"] {
background: transparent !important;
background-color: transparent !important;
}
Below are the exact versions utilized in the development, compilation, and packaging of Nimbus:
v1.95.0 (Rust 2021 Edition)v24.14.1v11.11.0src-tauri/Cargo.toml)v2.11.2 (with tray-icon support)v2.6.2tauri-plugin-notification: v2 (Native OS Notifications)tauri-plugin-store: v2 (Persistent State Storage)tauri-plugin-shell: v2tauri-plugin-process: v2tauri-plugin-log: v2package.json)v5.55.2 (Svelte 5 Runes)v2.57.0 (with static adapter v3.0.10)v4.2.2 (via @tailwindcss/vite compiler)v8.0.7v6.0.2Ensure you have Node.js, npm, and the Rust toolchain installed.
npm install
npx tauri dev
Vite compiles the frontend on custom port 5183 (preventing collisions with other local servers) while Cargo watches the Rust backend for changes.
npm run build
This compiles TypeScript and exports SvelteKit statically to /build using @sveltejs/adapter-static.
Bundle, optimize, and compile a standalone production-ready Windows binary:
npx tauri build
Tauri compiles under the release profile, embedding static frontend assets directly inside the binary. The resulting standalone executable (app.exe) and OS installers (.exe/.msi) are compiled under src-tauri/target/release/ and are only ~10MB!
Port 5173 is in use)If you have another Vite project (e.g. Voxely) running on the default port 5173, Vite will automatically shift your dev server to 5174. However, since Tauri looks for the frontend at 5173, it will render the wrong app!
5183 inside Svelte's vite.config.ts and set to strictPort: true. Tauri's tauri.conf.json is set to read from 5183. This guarantees isolated, clash-free execution.Access is denied - os error 5)If you try to run npx tauri build or npx tauri dev while an instance of Nimbus is running in your system tray, the Cargo compiler will fail to overwrite app.exe because the file is locked by Windows.
Stop-Process -Name "app" -Force -ErrorAction SilentlyContinue
nimbus/
βββ src/ # SvelteKit + Svelte 5 Frontend
β βββ lib/
β β βββ assets/ # SVG icons and visual assets
β β βββ stores/
β β βββ timer.svelte.ts # Svelte 5 Runes state machine
β βββ routes/
β β βββ +layout.svelte # Root HTML layout renderer
β β βββ +layout.ts # Disable SSR, enable SPA prerender
β β βββ +page.svelte # Timer UI, sliders & settings
β β βββ layout.css # Tailwind v4 import & transparency overrides
β βββ app.d.ts # TypeScript global definitions
β βββ app.html # Custom fonts, scrollbar styles & transparent wrapper
βββ src-tauri/ # Tauri Rust Backend
β βββ capabilities/
β β βββ default.json # Granular Svelte-to-Rust capability permissions
β βββ icons/ # System Tray & Application icon files
β βββ src/
β β βββ lib.rs # Tray icons, blur-hide & dynamic coordinates
β β βββ main.rs # Core entry point
β βββ build.rs # Tauri compiler build script
β βββ Cargo.toml # Rust manifest declaring plugins & tray-icon feature
β βββ tauri.conf.json # App definitions, opaque overlays, and build paths
βββ static/ # Global Static Web Assets
β βββ logo.png # Generated holographic green leaf cloud logo
β βββ screenshot-dashboard.png # Copied user request dashboard screenshot
β βββ screenshot-settings.png # Copied settings panel screenshot
β βββ screenshot-tray.png # Copied system tray placement screenshot
βββ package.json # Svelte dependencies and Tauri CLI shortcommands
βββ vite.config.ts # Vite custom port configuration (locked to 5183)
βββ README.md # Project Walkthrough & Developer Documentation