Cross-platform desktop alarm clock built with Tauri 2, React 19, TypeScript, Tailwind CSS, and a Rust backend. Create recurring alarms, upload custom ringtones, and receive desktop notifications that keep ringing until you snooze or dismiss them.
- Features
- Architecture
- Getting Started
- Development Workflow
- Build & Distribution
- Alarm Lifecycle
- Sound Management
- Project Structure
- Troubleshooting
- Roadmap
- Full alarm management – Add, edit, delete, and toggle alarms on/off.
- Recurring schedules – Select any combination of weekdays per alarm.
- Custom durations – Configure how long each alarm rings before autostop.
- Snooze controls – Preset snooze durations (e.g., 5 and 10 minutes).
- Desktop notifications – Tauri native notifications when alarms fire.
- Persistent storage – JSON-based storage per user; no external services.
- Custom ringtones – Upload audio files (MP3, WAV, OGG, M4A, AAC, FLAC).
- Modern UI – Responsive React interface styled with Tailwind and Lucide icons.
- Background operation – System tray support keeps alarms active when minimized.
| Layer | Technologies | Responsibilities |
|---|---|---|
| Frontend | React 19, TypeScript, Vite, Tailwind CSS | Alarm CRUD UI, notification modal, sound playback via Tauri commands. |
| Backend | Rust, Tauri 2 | File-backed storage, alarm validation, scheduler loop, audio file access, notification commands. |
| Storage | Local filesystem (AppData/Library/~/.local) |
alarms.txt, logs.txt, and uploaded ringtones. |
Key flows:
- Alarm checking:
useAlarmCheckerhook polls every 10 seconds, matching current time/day and preventing duplicate triggers within the same minute (@filepath:src/hooks/useAlarmChecker.ts#1-59). - Sound playback: Frontend requests bytes for selected ringtone via Tauri command
get_sound_bytes; falls back to default tone if file is missing. - Persistence: Rust
StorageManagermanages JSON serialization and ringtone file IO in the app data directory.
- Node.js ≥ 18
- Rust (stable toolchain via
rustup) - Tauri CLI globally installed:
npm install -g @tauri-apps/cli - Windows only: Microsoft Visual C++ Build Tools or Visual Studio with C++ workload
-
Copy or extract the project into your working directory (e.g.
alarm-system/). -
Install JavaScript dependencies:
npm install
Rust crates will be resolved automatically the first time you run a Tauri command.
npm run tauri devStarts Vite on http://localhost:1420 and launches the Tauri window with hot module replacement enabled.
npm run lint # ESLint rules
npm run typecheck # TypeScript(Add these scripts if they are not yet present in package.json.)
Useful commands while iterating on the backend:
cd src-tauri
cargo check
cargo fmtnpm run build # Builds the React frontend
npm run tauri build # Produces platform-specific installers/bundlesOutput paths:
- Windows:
src-tauri/target/release/bundle/msi/*.msi - macOS:
src-tauri/target/release/bundle/dmg/*.dmg - Linux:
src-tauri/target/release/bundle/appimage/*.AppImage
- Alarms are stored in
alarms.txtand synchronized with the UI on launch. - The
useAlarmCheckerhook polls the active alarm list every 10 seconds (@filepath:src/hooks/useAlarmChecker.ts#1-59). - On match (time + weekday + active flag), the frontend raises an
AlarmNotificationmodal, plays the configured sound, and shows snooze/dismiss controls. - Snoozed alarms are rescheduled in-app; dismissed alarms stay enabled for their next scheduled day.
- Upload audio files through the UI (Sound Upload form) or place them directly in the app's
ringtonesdirectory:- Windows:
%LOCALAPPDATA%\AlarmSystem\ringtones - macOS:
~/Library/Application Support/AlarmSystem/ringtones - Linux:
~/.local/share/AlarmSystem/ringtones
- Windows:
- When an alarm fires, the frontend requests audio bytes from the backend Tauri command
get_sound_bytes, creates a blob URL, and plays it in a loop. - If custom playback fails, the app automatically falls back to the default generated tone to ensure alarms still ring.
alarm-system/
├── public/ # Static assets bundled by Vite
├── src/
│ ├── components/ # UI components (cards, forms, notifications)
│ ├── hooks/ # React hooks (alarm checker)
│ ├── utils/ # Time formatting and helpers
│ └── App.tsx # Root component integrating Tauri commands
├── src-tauri/
│ ├── src/ # Rust backend (storage, scheduler, commands)
│ ├── Cargo.toml # Rust dependencies
│ └── tauri.conf.json # Tauri application manifest
├── package.json
├── vite.config.ts
└── tailwind.config.js
| Issue | Checks |
|---|---|
| Alarm not firing | Ensure alarm is active, current weekday is selected, and system time is correct. Review logs.txt in the app data directory. |
| No audio playback | Confirm the sound file exists and is playable. Check console logs for get_sound_bytes errors; fall back to default.wav. |
| Build fails | Run cargo clean, reinstall Node dependencies, and make sure your Rust toolchain is up to date (rustup update). |
- Adjustable snooze durations per alarm
- Import/export alarm presets
- Per-alarm volume control
MIT