Initial commit - Core Cooldown v0.1.0
Portable Windows break timer to prevent RSI and eye strain. Tauri v2 + Svelte 5 + Tailwind CSS v4. No installer, no telemetry, no data leaves the machine. CC0 public domain.
This commit is contained in:
438
README.md
Normal file
438
README.md
Normal file
@@ -0,0 +1,438 @@
|
||||
<p align="center">
|
||||
<img src="src-tauri/icons/128x128@2x.png" alt="Core Cooldown" width="96" height="96" />
|
||||
</p>
|
||||
|
||||
<h1 align="center">Core Cooldown</h1>
|
||||
|
||||
<p align="center">
|
||||
<strong>A portable break timer for Windows that reminds you to rest.</strong><br />
|
||||
Because your time and your body belong to you — not to your screen.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/license-CC0_1.0-blue?style=flat-square" alt="CC0 1.0" />
|
||||
<img src="https://img.shields.io/badge/platform-Windows-0078D6?style=flat-square&logo=windows" alt="Windows" />
|
||||
<img src="https://img.shields.io/badge/tauri-v2-24C8D8?style=flat-square&logo=tauri" alt="Tauri v2" />
|
||||
<img src="https://img.shields.io/badge/svelte-5-FF3E00?style=flat-square&logo=svelte" alt="Svelte 5" />
|
||||
<img src="https://img.shields.io/badge/rust-2021-000000?style=flat-square&logo=rust" alt="Rust" />
|
||||
<img src="https://img.shields.io/badge/tailwind-v4-06B6D4?style=flat-square&logo=tailwindcss" alt="Tailwind v4" />
|
||||
</p>
|
||||
|
||||
<br />
|
||||
|
||||
---
|
||||
|
||||
<br />
|
||||
|
||||
## Why
|
||||
|
||||
Repetitive strain injury and eye strain are not personal failings. They are the predictable consequence of systems that treat human attention as an extractable resource. Every worker at a screen deserves a tool that gently interrupts the grind — one that serves *them*, not a subscription model, not an analytics dashboard, not a corporate wellness KPI.
|
||||
|
||||
Core Cooldown is a single portable `.exe` with no installer, no account, no telemetry, and no data leaving your machine. Drop it in a folder and run it. It will remind you to rest. That's it.
|
||||
|
||||
<br />
|
||||
|
||||
## Features
|
||||
|
||||
### Timer & Breaks
|
||||
|
||||
| Feature | Description |
|
||||
|:--------|:------------|
|
||||
| **Configurable intervals** | Set work sessions from 5–120 minutes and breaks from 1–60 minutes |
|
||||
| **Pre-break warnings** | Toast notification and optional sound alert before each break |
|
||||
| **Break enforcement** | Always-on-top break window, optional fullscreen mode |
|
||||
| **Strict mode** | When enabled, the skip and cancel buttons are removed entirely |
|
||||
| **Early end** | Optionally allow ending a break after 50% completion |
|
||||
| **Snooze** | Delay a break by a configurable number of minutes (with configurable limits) |
|
||||
| **Skip cooldown** | Prevent rapid-fire skipping with a configurable cooldown timer |
|
||||
| **Immediate breaks** | Skip the pre-break notification and go straight into the break |
|
||||
| **Manual break** | Start a break at any time from the dashboard or the tray menu |
|
||||
|
||||
### Idle Detection & Smart Breaks
|
||||
|
||||
| Feature | Description |
|
||||
|:--------|:------------|
|
||||
| **Idle auto-pause** | Detects inactivity via Windows API (`GetLastInputInfo`) and pauses the timer |
|
||||
| **Auto-resume** | Timer resumes automatically when you return |
|
||||
| **Smart breaks** | Recognizes natural breaks (stepping away from the keyboard) and optionally counts them toward your daily goal |
|
||||
| **Configurable thresholds** | Idle timeout (30–600s) and smart break threshold (2–15 min) are independently adjustable |
|
||||
|
||||
### Break Activities
|
||||
|
||||
Each break screen shows a randomized activity suggestion from a curated library of **70 activities** across four categories:
|
||||
|
||||
- **Eyes** — palming, distance focusing, figure-eights, warm compress visualization, peripheral awareness drills
|
||||
- **Stretch** — neck rolls, wrist flexion, shoulder blade squeezes, chest openers, spinal twists, hip flexor stretches
|
||||
- **Breathing** — box breathing, 4-7-8 technique, alternate nostril, diaphragmatic breathing, resonance breathing
|
||||
- **Movement** — standing calf raises, wall push-ups, balance exercises, gentle squats, toe touches, desk yoga
|
||||
|
||||
Activities cycle every 30 seconds and never repeat consecutively.
|
||||
|
||||
### Working Hours Schedule
|
||||
|
||||
A per-day schedule with support for multiple time ranges per day. The timer only runs during your configured working hours — outside of those hours, it pauses automatically.
|
||||
|
||||
- **Monday through Sunday** — each day independently togglable
|
||||
- **Multiple ranges per day** — for split shifts or non-contiguous work blocks
|
||||
- **Weekend defaults** — Saturday and Sunday are disabled by default
|
||||
|
||||
### Statistics & History
|
||||
|
||||
| Metric | Description |
|
||||
|:-------|:------------|
|
||||
| **Today's summary** | Breaks completed, skipped, snoozed, and total break time |
|
||||
| **Natural breaks** | Separately tracked idle breaks (with optional stat inclusion) |
|
||||
| **Compliance rate** | Ratio of completed breaks to total scheduled |
|
||||
| **Streak tracking** | Current and best consecutive-day streaks |
|
||||
| **7-day chart** | Canvas-rendered bar chart showing daily break history |
|
||||
|
||||
All statistics are stored locally in a plain JSON file next to the executable.
|
||||
|
||||
### Sound Effects
|
||||
|
||||
Synthesized notification sounds via the Web Audio API — no bundled audio files, no network requests.
|
||||
|
||||
**8 presets:** Bell, Chime, Soft, Digital, Harp, Bowl, Rain, Whistle
|
||||
|
||||
Each preset plays on break start, pre-break warning, and break completion. Volume is configurable from 0–100%.
|
||||
|
||||
### Global Keyboard Shortcuts
|
||||
|
||||
| Shortcut | Action |
|
||||
|:---------|:-------|
|
||||
| `Ctrl + Shift + P` | Pause / resume timer |
|
||||
| `Ctrl + Shift + B` | Start break now |
|
||||
| `Ctrl + Shift + S` | Show / hide main window |
|
||||
|
||||
These work system-wide, even when Core Cooldown is not focused.
|
||||
|
||||
### System Tray
|
||||
|
||||
- **Dynamic icon** — a 32×32 progress arc rendered in real-time: orange during focus, purple during breaks, dimmed when paused
|
||||
- **Countdown tooltip** — hover over the tray icon to see time remaining
|
||||
- **Context menu** — pause/resume, start break, toggle mini mode, show/hide, quit
|
||||
|
||||
### Mini Mode
|
||||
|
||||
A compact floating timer (200×50px) that sits on top of your other windows.
|
||||
|
||||
- **Click-through** — the mini timer is completely transparent to mouse events by default, so it never blocks what's underneath
|
||||
- **Hover to grab** — hover over it for a configurable number of seconds (default: 3) and it becomes draggable
|
||||
- **Double-click** — opens the main window
|
||||
- **Togglable** — enable/disable from the tray menu
|
||||
|
||||
### Appearance & Customization
|
||||
|
||||
| Setting | Range |
|
||||
|:--------|:------|
|
||||
| **UI zoom** | 50–200% with live preview |
|
||||
| **Accent color** | Hex color picker for the main UI accent |
|
||||
| **Break color** | Separate hex color for the break screen ring |
|
||||
| **Color schemes** | Ocean, Forest, Sunset, Midnight, Dawn |
|
||||
| **Countdown font** | Google Fonts selector for the timer display |
|
||||
| **Background blobs** | Animated gradient blobs with film grain overlay |
|
||||
| **Backdrop opacity** | 50–100% for the break screen overlay |
|
||||
| **Break title & message** | Fully customizable text shown during breaks |
|
||||
| **Dark mode** | Always on (it's the only civilized option) |
|
||||
|
||||
### Notifications
|
||||
|
||||
Native Windows toast notifications for:
|
||||
- Pre-break warnings (configurable seconds before break)
|
||||
- Break completion
|
||||
|
||||
### Window Behavior
|
||||
|
||||
- **Frameless window** with custom titlebar and drag region
|
||||
- **Transparent background** with frosted glass effects
|
||||
- **Window position persistence** — main and mini windows remember their position between launches
|
||||
- **Animated view transitions** — directional fly/scale/fade transitions (700ms, cubicOut easing) between all views
|
||||
|
||||
<br />
|
||||
|
||||
## Portability
|
||||
|
||||
Core Cooldown is fully portable. The executable carries everything it needs and stores everything it creates right next to itself:
|
||||
|
||||
```
|
||||
core-cooldown.exe ← the application
|
||||
config.json ← your settings (created on first run)
|
||||
stats.json ← your break history (created on first run)
|
||||
data/ ← WebView2 runtime data (created on first run)
|
||||
```
|
||||
|
||||
No installer. No registry entries. No writes to `%APPDATA%`, `%LOCALAPPDATA%`, or any other system directory. Move the folder anywhere — a USB stick, a shared drive, a different machine. It just works.
|
||||
|
||||
There is nothing to uninstall. Delete the folder and it's gone. No traces left behind.
|
||||
|
||||
<br />
|
||||
|
||||
## Installation
|
||||
|
||||
1. Download `core-cooldown.exe` from the [Releases](../../releases) page
|
||||
2. Put it in any folder you like
|
||||
3. Run it
|
||||
|
||||
That's it. No elevated permissions required. No runtime dependencies to install. The first launch may take a moment while Windows initializes the WebView2 runtime.
|
||||
|
||||
<br />
|
||||
|
||||
## Building from Source
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- **Node.js** (v18+) and **npm**
|
||||
- **Rust** toolchain (`rustup`) with the `x86_64-pc-windows-gnu` target
|
||||
- **MinGW-w64** — the GNU toolchain for Windows (provides the linker, windres, and dlltool)
|
||||
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://git.lashman.live/lashman/core-cooldown.git
|
||||
cd core-cooldown
|
||||
|
||||
# Install JavaScript dependencies
|
||||
npm install
|
||||
```
|
||||
|
||||
### Linker Configuration
|
||||
|
||||
Create or edit `src-tauri/.cargo/config.toml` to point to your MinGW installation:
|
||||
|
||||
```toml
|
||||
[build]
|
||||
target = "x86_64-pc-windows-gnu"
|
||||
|
||||
[target.x86_64-pc-windows-gnu]
|
||||
linker = "C:/path/to/mingw64/bin/gcc.exe"
|
||||
ar = "C:/path/to/mingw64/bin/ar.exe"
|
||||
```
|
||||
|
||||
### Development
|
||||
|
||||
```bash
|
||||
# Launch the app with hot-reload
|
||||
npm run tauri dev
|
||||
|
||||
# Check Rust code without building
|
||||
cd src-tauri && cargo check
|
||||
|
||||
# Build frontend only (no Tauri shell)
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Release Build
|
||||
|
||||
```bash
|
||||
# Build a release executable (no installer)
|
||||
npm run tauri build
|
||||
```
|
||||
|
||||
The compiled binary will be at:
|
||||
```
|
||||
src-tauri/target/x86_64-pc-windows-gnu/release/core-cooldown.exe
|
||||
```
|
||||
|
||||
<br />
|
||||
|
||||
## Architecture
|
||||
|
||||
Core Cooldown is a split-architecture desktop application: a Rust backend for system integration and timer logic, and a Svelte frontend rendered in a native WebView.
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ System Tray │
|
||||
│ (dynamic icon · tooltip · menu) │
|
||||
├──────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Main Window │ │ Break Window│ │ Mini Window │ │
|
||||
│ │ (WebView) │ │ (WebView) │ │ (WebView) │ │
|
||||
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
|
||||
│ │ │ │ │
|
||||
│ └─────────┬───────┴──────────────────┘ │
|
||||
│ │ Tauri IPC (commands + events) │
|
||||
│ ┌─────────┴─────────┐ │
|
||||
│ │ Rust Backend │ │
|
||||
│ │ │ │
|
||||
│ │ TimerManager │ ← state machine (tick/sec) │
|
||||
│ │ Config │ ← JSON persistence │
|
||||
│ │ Stats │ ← break history tracking │
|
||||
│ │ IdleDetector │ ← GetLastInputInfo polling │
|
||||
│ │ GlobalShortcuts │ ← Ctrl+Shift+P/B/S │
|
||||
│ │ TrayIcon │ ← RGBA ring rendering │
|
||||
│ │ Notifications │ ← Windows toast │
|
||||
│ └───────────────────┘ │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Backend (Rust)
|
||||
|
||||
| Module | Responsibility |
|
||||
|:-------|:---------------|
|
||||
| `lib.rs` | Tauri app builder, command registration, tray setup, timer tick thread, window management, global shortcuts |
|
||||
| `config.rs` | Configuration struct with serde serialization, validation (clamping all values to safe ranges), and file I/O |
|
||||
| `timer.rs` | Timer state machine (`Running` → `Paused` → `BreakActive`), idle detection via Windows API, working hours enforcement |
|
||||
| `stats.rs` | Daily break statistics, streak calculation, history queries |
|
||||
| `main.rs` | Entry point |
|
||||
|
||||
### Frontend (Svelte 5 + TypeScript)
|
||||
|
||||
| Layer | Files |
|
||||
|:------|:------|
|
||||
| **Views** | `Dashboard.svelte`, `BreakScreen.svelte`, `Settings.svelte`, `StatsView.svelte` |
|
||||
| **Windows** | `BreakWindow.svelte` (standalone break modal), `MiniTimer.svelte` (floating mini mode) |
|
||||
| **Components** | `TimerRing.svelte`, `Titlebar.svelte`, `ToggleSwitch.svelte`, `Stepper.svelte`, `ColorPicker.svelte`, `FontSelector.svelte`, `TimeSpinner.svelte`, `BackgroundBlobs.svelte` |
|
||||
| **Stores** | `timer.ts` (reactive timer state from IPC events), `config.ts` (config state with debounced auto-save) |
|
||||
| **Utilities** | `sounds.ts` (Web Audio synthesis), `activities.ts` (70 break activities), `animate.ts` (motion library actions) |
|
||||
|
||||
### IPC Contract
|
||||
|
||||
**Commands** (frontend → backend):
|
||||
`get_config`, `save_config`, `update_pending_config`, `reset_config`, `toggle_timer`, `start_break_now`, `cancel_break`, `snooze`, `get_timer_state`, `set_view`, `get_stats`, `get_daily_history`
|
||||
|
||||
**Events** (backend → frontend):
|
||||
`timer-tick` (every second), `break-started`, `break-ended`, `prebreak-warning`, `config-changed`
|
||||
|
||||
<br />
|
||||
|
||||
## Configuration Reference
|
||||
|
||||
All settings are stored in `config.json` next to the executable. The settings panel exposes every option with live validation, but the file is plain JSON and can be edited by hand if you prefer.
|
||||
|
||||
<details>
|
||||
<summary><strong>Full configuration schema</strong></summary>
|
||||
|
||||
| Key | Type | Default | Range | Description |
|
||||
|:----|:-----|:--------|:------|:------------|
|
||||
| `break_duration` | `u32` | `5` | 1–60 min | Duration of each break |
|
||||
| `break_frequency` | `u32` | `25` | 5–120 min | Interval between breaks |
|
||||
| `auto_start` | `bool` | `true` | — | Start timer on launch |
|
||||
| `break_title` | `string` | `"Rest your eyes"` | max 100 chars | Title shown on break screen |
|
||||
| `break_message` | `string` | `"Look away from the screen..."` | max 500 chars | Message shown during breaks |
|
||||
| `fullscreen_mode` | `bool` | `true` | — | Use fullscreen break window |
|
||||
| `strict_mode` | `bool` | `false` | — | Remove skip/cancel buttons |
|
||||
| `allow_end_early` | `bool` | `true` | — | Allow ending break after 50% |
|
||||
| `immediately_start_breaks` | `bool` | `false` | — | Skip pre-break notification |
|
||||
| `working_hours_enabled` | `bool` | `false` | — | Restrict timer to schedule |
|
||||
| `working_hours_schedule` | `array` | Mon–Fri 09:00–18:00 | 7 days | Per-day time ranges |
|
||||
| `dark_mode` | `bool` | `true` | — | Dark theme |
|
||||
| `color_scheme` | `string` | `"Ocean"` | 5 presets | Color scheme name |
|
||||
| `backdrop_opacity` | `f32` | `0.92` | 0.5–1.0 | Break screen backdrop opacity |
|
||||
| `notification_enabled` | `bool` | `true` | — | Enable toast notifications |
|
||||
| `notification_before_break` | `u32` | `30` | 0–300 sec | Pre-break warning time |
|
||||
| `snooze_duration` | `u32` | `5` | 1–30 min | Snooze delay |
|
||||
| `snooze_limit` | `u32` | `3` | 0–5 (0=unlimited) | Max snoozes per cycle |
|
||||
| `skip_cooldown` | `u32` | `60` | 0–600 sec | Cooldown between skips |
|
||||
| `sound_enabled` | `bool` | `true` | — | Play notification sounds |
|
||||
| `sound_volume` | `u32` | `70` | 0–100 | Sound volume percentage |
|
||||
| `sound_preset` | `string` | `"bell"` | 8 presets | Sound preset name |
|
||||
| `idle_detection_enabled` | `bool` | `true` | — | Enable idle auto-pause |
|
||||
| `idle_timeout` | `u32` | `120` | 30–600 sec | Idle threshold |
|
||||
| `smart_breaks_enabled` | `bool` | `true` | — | Detect natural breaks |
|
||||
| `smart_break_threshold` | `u32` | `300` | 120–900 sec | Natural break threshold |
|
||||
| `smart_break_count_stats` | `bool` | `false` | — | Count natural breaks in stats |
|
||||
| `show_break_activities` | `bool` | `true` | — | Show activity suggestions |
|
||||
| `ui_zoom` | `u32` | `100` | 50–200% | Interface zoom level |
|
||||
| `accent_color` | `string` | `"#ff4d00"` | hex | Main accent color |
|
||||
| `break_color` | `string` | `"#7c6aef"` | hex | Break screen ring color |
|
||||
| `countdown_font` | `string` | `""` | font family | Google Font for countdown |
|
||||
| `background_blobs_enabled` | `bool` | `false` | — | Animated background blobs |
|
||||
| `mini_click_through` | `bool` | `true` | — | Mini mode click-through |
|
||||
| `mini_hover_threshold` | `f32` | `3.0` | 1.0–10.0 sec | Hover time before drag |
|
||||
|
||||
</details>
|
||||
|
||||
<br />
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Rust
|
||||
|
||||
| Crate | Purpose |
|
||||
|:------|:--------|
|
||||
| `tauri 2` | Application shell, IPC, multi-window, system tray |
|
||||
| `tauri-plugin-shell 2` | Shell integration |
|
||||
| `tauri-plugin-notification 2` | Windows toast notifications |
|
||||
| `tauri-plugin-global-shortcut 2` | System-wide keyboard shortcuts |
|
||||
| `serde` / `serde_json` | Configuration and statistics serialization |
|
||||
| `chrono` | Date/time handling for schedules and statistics |
|
||||
| `dirs` | Platform directory resolution (unused — legacy dep) |
|
||||
| `anyhow` | Error handling |
|
||||
| `winapi` | Windows idle detection (`GetLastInputInfo`) |
|
||||
|
||||
### JavaScript
|
||||
|
||||
| Package | Purpose |
|
||||
|:--------|:--------|
|
||||
| `@tauri-apps/api` | Frontend IPC bindings |
|
||||
| `svelte 5` | Reactive UI framework (runes: `$state`, `$derived`, `$effect`) |
|
||||
| `tailwindcss 4` | Utility-first CSS |
|
||||
| `vite 6` | Build tool and dev server |
|
||||
| `motion` | Animation library |
|
||||
| `typescript 5` | Type safety |
|
||||
|
||||
<br />
|
||||
|
||||
## Contributing
|
||||
|
||||
This project belongs to no one and everyone. If you find it useful and want to make it better, you are welcome.
|
||||
|
||||
There are no contribution agreements to sign, no corporate CLAs, no licensing traps. Everything here is in the public domain. Your contributions will be too — freely given, freely shared, freely built upon by anyone who needs them.
|
||||
|
||||
**Some ways to help:**
|
||||
|
||||
- Report bugs or rough edges
|
||||
- Suggest new break activities (especially if you have physiotherapy or ergonomics knowledge)
|
||||
- Improve accessibility
|
||||
- Port idle detection to macOS/Linux
|
||||
- Translate the interface
|
||||
- Share it with someone who needs it
|
||||
|
||||
The best software is built through mutual aid — people helping people because it's the right thing to do, not because there's a profit motive attached.
|
||||
|
||||
<br />
|
||||
|
||||
## Philosophy
|
||||
|
||||
Core Cooldown exists because rest is not a luxury. It is a fundamental need that no productivity framework, no employer, and no software platform should be able to gatekeep behind a paywall or a subscription.
|
||||
|
||||
This application:
|
||||
|
||||
- **Collects nothing.** No analytics, no telemetry, no usage tracking, no crash reports phoned home. Your break habits are your own business.
|
||||
- **Costs nothing.** Not "free tier with limitations." Not "free for personal use." Free. Unconditionally. For everyone.
|
||||
- **Requires nothing.** No account, no email, no app store, no internet connection after download. It runs on your machine and answers to you alone.
|
||||
- **Owns nothing.** Released under CC0 — the most complete relinquishment of rights possible under law. There is no owner. There are no restrictions. The code belongs to the commons.
|
||||
|
||||
We believe that tools for human wellbeing should never be enclosed, never be scarce, and never serve a master other than the person using them.
|
||||
|
||||
<br />
|
||||
|
||||
## License
|
||||
|
||||
<p align="center">
|
||||
<a href="https://creativecommons.org/publicdomain/zero/1.0/">
|
||||
<img src="https://licensebuttons.net/p/zero/1.0/88x31.png" alt="CC0" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
**CC0 1.0 Universal — Public Domain Dedication**
|
||||
|
||||
To the extent possible under law, the author has waived all copyright and related or neighboring rights to this work. This work is published from the commons, for the commons.
|
||||
|
||||
You can copy, modify, distribute, and perform the work, even for commercial purposes, all without asking permission. No permission is needed. No attribution is required (though it's always appreciated).
|
||||
|
||||
See [`LICENSE`](LICENSE) for the full legal text.
|
||||
|
||||
<br />
|
||||
|
||||
---
|
||||
|
||||
<p align="center">
|
||||
<sub>
|
||||
Built with care. Shared without conditions.<br />
|
||||
Rest well.
|
||||
</sub>
|
||||
</p>
|
||||
Reference in New Issue
Block a user