-
-
Notifications
You must be signed in to change notification settings - Fork 0
Tech Stack
Kenneth LaCroix edited this page Apr 13, 2026
·
1 revision
MoodHaven Journal is a local-first desktop app built on Tauri v2 (Rust backend) with a React/TypeScript frontend. All user data lives on-device in an encrypted SQLite database.
| Layer | Technology | Notes |
|---|---|---|
| Desktop shell | Tauri 2 (Rust) | Native OS integration |
| Frontend | React 18 + TypeScript | Strict mode, no any
|
| Styling | TailwindCSS 3 | Custom colour tokens |
| Rich text | TipTap | ProseMirror-based |
| State | Zustand | 4 stores |
| Database | SQLite via rusqlite (bundled) | Single file, no server |
| Encryption | AES-256-GCM + PBKDF2 | WebCrypto API |
| Peer identity | Ed25519 (ed25519-dalek) | Device signing key |
| Peer discovery | mDNS/DNS-SD (mdns-sd) | LAN auto-discovery |
| 2FA | totp-rs + native CTAP2/HID | TOTP + hardware keys |
| HTTP (Rust) | reqwest (json + stream features) | WebDAV sync, Oura API |
| Charts | Custom SVG | No charting library |
| Logging | tauri-plugin-log + src/lib/services/logger.ts
|
Rotating file (prod), stderr (dev) |
| Testing | Vitest + Testing Library | 693 tests |
| Build | Vite 8 + Tauri CLI | |
| Mobile | Kotlin + Wear OS Data Layer | MessageAPI + ChannelAPI |
The browser build replaces Tauri IPC with IndexedDB via Vite module aliasing:
| Module | Desktop | Browser |
|---|---|---|
| Data persistence | SQLite (rusqlite) | IndexedDB (src/lib/backend/browser.ts) |
| IPC layer |
@tauri-apps/api/core invoke |
src/lib/backend/browser-invoke.ts shim |
| Tauri-only plugins | Native | No-op stubs (src/lib/backend/browser-stubs.ts) |
| HTTP | @tauri-apps/plugin-http |
window.fetch |
| Store | What it holds |
|---|---|
appStore |
isInitialized, isUnlocked, theme, active view |
settingsStore |
All user preferences (AI, appearance, privacy, journal, health) |
booksStore |
books[], activeBookId
|
peerSyncStore |
identity, nearbyPeers, trustedDevices, isDiscovering
|
Component
│
▼
Hook (state + side effects)
│
▼
Service (IPC wrappers or pure functions, src/lib/)
│
▼
Tauri invoke → Rust command handler
Services are thin IPC wrappers or pure utilities — they hold no state. Components use hooks; hooks call services.
~109 Rust commands registered in src-tauri/src/lib.rs, split across ~21 modules in src-tauri/src/commands/. Each command is:
- Defined in
src-tauri/src/commands/<module>.rs - Declared in
src-tauri/src/commands/mod.rs - Registered in
src-tauri/src/lib.rsinsideinvoke_handler!(...) - Permitted in
src-tauri/capabilities/default.json - Wrapped in
src/lib/<service>.ts
Full command reference: docs/tauri-commands.md
- Engine: whisper.cpp binary as Tauri sidecar
- Models: on-demand download from Hugging Face to
app_data_dir/models/ - Audio: Web Audio API → 16 kHz mono WAV → sidecar → stdout text → insert at cursor → delete WAV
- All processing is local — no audio ever leaves the device
Navigation is handled by a ViewType enum in appStore. No URL routing library.
ViewType: writing | timeline | onthisday | insights | calendar | settings
Full architecture: docs/architecture.md