| Layer | Choice | Rationale |
|---|---|---|
| Shell | Electron 34 | Native Windows integration, title bar overlay, mature IPC. Rust/Tauri unavailable on target machine. |
| UI | React 19 + TypeScript | Component model, type safety, ecosystem for premium UI. |
| Styling | Tailwind CSS 3 | Design tokens, rapid iteration, consistent spacing. |
| Animation | Framer Motion | Spring physics, layout animations, 60 FPS GPU transforms. |
| State | Zustand | Minimal boilerplate, no context re-render storms. |
| Database | SQLite (sql.js) | WASM-based SQLite, no native compile step, works in Electron without Visual Studio Build Tools. |
| Charts | Recharts | Customizable, SVG-based, matches dark theme. |
| Command UI | cmdk | Linear/VS Code-style command palette. |
| Build | electron-vite + electron-builder | Fast HMR dev, optimized production bundles. |
- Tauri 2: Smaller binary, faster startup — rejected because Rust toolchain not installed; would add setup friction.
- PySide6 (existing TaskFlow): Good for simple apps — rejected; QSS cannot match glassmorphism reference at this fidelity.
- Flutter Desktop: Strong performance — rejected; smaller web component ecosystem for command palettes/charts.
- PostgreSQL: Overkill for local single-user app; SQLite is faster for embedded use.
┌─────────────────────────────────────────────────────────────┐
│ Renderer (React) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────────┐ │
│ │ Sidebar │ │ TaskList │ │ Detail │ │ Views (Analytics)│ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────────┬────────┘ │
│ └────────────┴────────────┴─────────────────┘ │
│ │ Zustand Store │
│ │ window.taskflow API │
├─────────────────────────┼───────────────────────────────────┤
│ Preload (contextBridge) │
├─────────────────────────┼───────────────────────────────────┤
│ Main Process │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ IPC Handlers → Services → SQLite (better-sqlite3) │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
- Single Responsibility: Each service owns one domain (tasks, categories, projects, analytics).
- Open/Closed: New IPC channels extend handlers without modifying existing services.
- Liskov Substitution: Service functions return consistent typed shapes.
- Interface Segregation: Preload exposes grouped APIs (
tasks,categories, etc.). - Dependency Inversion: Renderer depends on
window.taskflowabstraction, not SQLite.
taskflow/
├── electron/
│ ├── main/
│ │ ├── index.ts # App lifecycle, window
│ │ ├── database/ # SQLite init, schema, backup
│ │ ├── services/ # Business logic layer
│ │ └── ipc/ # IPC registration
│ └── preload/
│ └── index.ts # Secure API bridge
├── src/
│ ├── components/ # UI components
│ ├── views/ # Full-page views
│ ├── stores/ # Zustand state
│ ├── hooks/ # React hooks
│ ├── lib/ # Utilities
│ └── types/ # Shared TypeScript types
├── tests/ # Unit tests
├── docs/ # Documentation
└── scripts/ # Build scripts
- User action in React component
- Component calls
window.taskflow.*via preload - IPC invokes main process handler
- Service executes SQLite transaction
- Activity logged (if applicable)
- Result returned to renderer
- Zustand store refreshed
- WAL journal mode for crash safety
- Foreign key constraints enabled
- Auto-backup on startup (keeps last 10)
- Manual backup/recover in Settings
- Phase 2: Cloud sync (Supabase/Firebase), multi-device
- Phase 3: Plugin system for custom views
- Phase 4: Migrate to Tauri for smaller binary when Rust available
- Phase 5: Collaborative projects, real-time updates