Skip to main content

max / goingson

14.3 KB · 366 lines History Blame Raw
1 # GoingsOn Architecture
2
3 Email, calendar, tasks in one place. Project management for individuals and small teams.
4
5 A Rust-based productivity application built with Tauri 2 (Rust backend + Vanilla JS frontend), SQLite with sqlx 0.8, and a "Neobrute" design aesthetic. 3 crates: `core` (domain models), `db-sqlite` (repository), `plugin-runtime` (Rhai plugins).
6
7 ## High-Level Overview
8
9 ```
10 ┌─────────────────────────────────────────────────────────┐
11 │ User Interface │
12 │ ┌────────────────────────────────────────────────────┐ │
13 │ │ Tauri Desktop (Vanilla JS) │ │
14 │ └─────────────────────┬──────────────────────────────┘ │
15 │ │ │
16 │ ┌─────────────────────▼──────────────────────────────┐ │
17 │ │ Tauri Commands (src-tauri/) │ │
18 │ └─────────────────────┬──────────────────────────────┘ │
19 └────────────────────────┼─────────────────────────────────┘
20
21 ┌────────────────────────▼─────────────────────────────────┐
22 │ goingson-core │
23 │ ┌──────────┐ ┌──────────┐ ┌────────────┐ ┌────────────┐ │
24 │ │ Models │ │Repository│ │ Urgency │ │ Parser │ │
25 │ │ │ │ Traits │ │ Calculator │ │ (Quick-Add)│ │
26 │ └──────────┘ └────┬─────┘ └────────────┘ └────────────┘ │
27 └────────────────────┼─────────────────────────────────────┘
28
29 ┌──────▼───────────┐
30 │ goingson-db- │
31 │ sqlite │
32 │ (Desktop) │
33 └──────────────────┘
34
35 Additional crates:
36 plugin-runtime Rhai plugin system (import plugins)
37 ```
38
39 ## Workspace Structure
40
41 ```
42 goingson/
43 ├── crates/
44 │ ├── core/ # Domain models, traits, business logic
45 │ ├── db-sqlite/ # SQLite repository implementations
46 │ └── plugin-runtime/ # Rhai plugin system
47 ├── src-tauri/ # Tauri desktop app (single-user)
48 └── migrations/
49 └── sqlite/ # SQLite schema migrations (33 files)
50 ```
51
52 ## Crate Dependencies
53
54 ```
55 goingson-desktop (src-tauri)
56 ├── goingson-db-sqlite
57 │ └── goingson-core
58 └── plugin-runtime
59 └── goingson-core (for shared types)
60 ```
61
62 ## Core Crate (`crates/core/`)
63
64 The core crate defines domain models and repository traits, independent of persistence.
65
66 ### Modules
67
68 | Module | Purpose |
69 |--------|---------|
70 | `models/` | Domain types (17 model files) |
71 | `repository.rs` | Repository traits (data access contracts) |
72 | `urgency.rs` | TaskWarrior-inspired urgency calculation algorithm |
73 | `parser.rs` | Quick-add natural language parser |
74 | `recurrence.rs` | Task/event recurrence logic |
75 | `validation.rs` | Input validation trait |
76 | `constants.rs` | Named constants for thresholds, formats |
77 | `error.rs` | Unified CoreError type |
78
79 ### Key Types
80
81 ```rust
82 // Domain entities
83 Project, Task, Event, Email, EmailAccount, User
84 Contact, ContactEmail, ContactPhone, SocialHandle, ContactCustomField
85 SavedView, Annotation, Subtask, Milestone
86 WeeklyReview, BackupSettings
87
88 // Enums with display/parse support
89 ProjectType, ProjectStatus, TaskStatus, Priority, Recurrence
90 SortDirection, SortField, TaskSortColumn
91 ViewType, ViewFilters, BlockType
92 EmailAuthType, MilestoneStatus
93
94 // DTOs for creation/updates
95 NewProject, NewTask, NewEvent, NewEmail
96 UpdateProject, UpdateTask, UpdateEvent
97
98 // Newtype IDs
99 ProjectId, TaskId, EventId, EmailId, ContactId
100 EmailAccountId, AnnotationId, SubtaskId, SavedViewId
101 MilestoneId, CustomFieldId
102 ```
103
104 ### Repository Traits
105
106 ```rust
107 ProjectRepository, TaskRepository, EventRepository
108 EmailRepository, EmailAccountRepository, ContactRepository
109 SearchRepository, StatsRepository, SavedViewRepository
110 AnnotationRepository, SubtaskRepository, MilestoneRepository
111 WeeklyReviewRepository, BackupSettingsRepository
112 UserRepository
113 ```
114
115 ## Database Layer (`crates/db-sqlite/`)
116
117 SQLite persistence for the desktop app. Single-user, local storage. 50 migrations in `migrations/sqlite/`.
118
119 ```
120 src/
121 ├── lib.rs # SQLite pool initialization
122 ├── utils.rs # format_datetime, parse_uuid, email validation
123 └── repository/
124 ├── mod.rs # Re-exports all repositories
125 ├── project_repo.rs
126 ├── task_repo.rs
127 ├── event_repo.rs
128 ├── email_repo.rs
129 ├── email_account_repo.rs
130 ├── contact_repo.rs
131 ├── user_repo.rs
132 ├── search_repo.rs # FTS5 full-text search
133 ├── stats_repo.rs # Dashboard aggregations
134 ├── saved_view_repo.rs
135 ├── annotation_repo.rs
136 ├── subtask_repo.rs
137 ├── milestone_repo.rs
138 ├── weekly_review_repo.rs
139 └── backup_settings_repo.rs
140 ```
141
142 ## Tauri Desktop App (`src-tauri/`)
143
144 Single-user desktop application.
145
146 ```
147 src/
148 ├── main.rs # Tauri app setup, command registration
149 ├── state.rs # AppState with repository instances
150 ├── notifications.rs # Snooze watcher, native notifications
151 ├── email/ # IMAP/SMTP client
152 └── commands/
153 ├── mod.rs # Re-exports all commands
154 ├── error.rs # Error type definitions
155 ├── task.rs # Task CRUD, annotations, subtasks, snoozing, waiting
156 ├── project.rs # Project management
157 ├── event.rs # Calendar events
158 ├── email.rs # Email CRUD, threading, archive
159 ├── email_account.rs # Email account setup, sync interval
160 ├── email_sync.rs # IMAP/SMTP sync orchestration
161 ├── contact.rs # Contact CRUD, emails, phones, social handles
162 ├── search.rs # Full-text search across all entities
163 ├── stats.rs # Dashboard statistics
164 ├── day_planning.rs # Time blocking
165 ├── weekly_review.rs # Weekly review workflow
166 ├── saved_views.rs # Custom filter views
167 ├── milestone.rs # Milestone CRUD and reordering
168 ├── plugin.rs # Plugin registry, hot-reload, import
169 ├── oauth.rs # OAuth2 flows (Fastmail, Google, Microsoft)
170 ├── export.rs # JSON, CSV, ICS export; backup/restore
171 ├── sync.rs # Cloud sync via SyncKit
172 ├── themes.rs # Theme list and color queries
173 └── window.rs # Window management, compose window
174 ```
175
176 ### Command Pattern
177
178 Tauri commands are async functions that:
179 1. Accept `State<Arc<AppState>>` for repository access
180 2. Deserialize input from frontend via `#[serde(rename_all = "camelCase")]`
181 3. Call repository methods
182 4. Serialize response types back to frontend
183
184 ```rust
185 #[tauri::command]
186 pub async fn create_task(
187 state: State<'_, Arc<AppState>>,
188 input: TaskInput,
189 ) -> Result<TaskResponse, String> {
190 state.tasks
191 .create(DESKTOP_USER_ID, new_task)
192 .await
193 .map(TaskResponse::from)
194 .map_err(|e| e.to_string())
195 }
196 ```
197
198 ## Frontend Architecture (Tauri Desktop)
199
200 The desktop frontend uses vanilla JavaScript organized under the `GoingsOn` global namespace. 66 source files.
201
202 ### Namespace Organization
203
204 ```
205 window.GoingsOn = {
206 api: { ... }, // Tauri IPC abstraction layer
207 state: { ... }, // Centralized state with pub/sub
208 ui: { ... }, // Modal, toast, form utilities
209 utils: { ... }, // HTML escaping, validation
210
211 // Domain modules (IIFE-wrapped)
212 projects: { ... },
213 tasks: { ... },
214 events: { ... },
215 emails: { ... },
216 contacts: { ... },
217
218 // Feature modules
219 savedViews: { ... },
220 snooze: { ... },
221 navigation: { ... },
222 settings: { ... },
223 app: { ... },
224
225 // Infrastructure
226 VirtualScroller, // Virtual scrolling for large lists
227 SelectionManager, // Multi-select with shift/ctrl
228 PaginationManager, // Page navigation
229 };
230 ```
231
232 ### Module Pattern
233
234 Each domain module is wrapped in an IIFE and exposes its public API through the namespace:
235
236 ```javascript
237 (function() {
238 'use strict';
239 // Private state and helpers
240 async function load() { ... }
241 function openNew() { ... }
242
243 // Public API
244 GoingsOn.myModule = { load, openNew };
245 })();
246 ```
247
248 ### Pre-computed Response Fields
249
250 Rust response types include pre-computed display values so JS never calculates dates, formatting, or derived state:
251
252 | Response Type | Pre-computed Fields |
253 |--------------|---------------------|
254 | TaskResponse | `dueFormatted`, `urgencyClass`, `isOverdue`, `isSnoozed`, `subtaskCount`, `subtaskCompleted`, `subtaskProgress` |
255 | EventResponse | `timeFormatted`, `dateFormatted`, `isPast`, `proximityClass`, `proximityLabel` |
256 | EmailResponse | `receivedFormatted` |
257 | EmailAccountResponse | `lastSyncFormatted` |
258
259 ### Centralized State
260
261 All shared data lives in `GoingsOn.state` with reactive pub/sub:
262
263 ```javascript
264 GoingsOn.state.set('tasks', updatedTasks); // Triggers subscribers
265 GoingsOn.state.subscribe('tasks', (newVal, oldVal) => { ... });
266 ```
267
268 ### File Organization
269
270 ```
271 src-tauri/frontend/
272 ├── css/
273 │ └── styles.css # Design system + all components
274 ├── fonts/
275 │ └── Reglo-Bold.woff2 # Display font
276 ├── js/
277 │ ├── goingson.js # Namespace root (window.GoingsOn)
278 │ ├── api.js # Tauri IPC abstraction
279 │ ├── state.js # Centralized state + pub/sub
280 │ ├── utils.js # Escaping, validation, debounce
281 │ ├── router.js # View routing
282 │ ├── app.js # App initialization, menu listeners
283 │ │
284 │ ├── components.js # Toast, confirm dialog
285 │ ├── components-modal.js # Modal system
286 │ ├── form-modal.js # Form modal (openFormModal)
287 │ ├── navigation.js # View switching, sidebar
288 │ ├── keyboard.js # Keyboard shortcuts
289 │ ├── selection-manager.js # Multi-select with shift/ctrl
290 │ ├── pagination-manager.js # Page navigation
291 │ ├── virtual-scroller.js # Virtual scrolling for large lists
292 │ ├── context-menus.js # Right-click context menus
293 │ ├── bulk-actions.js # Multi-select bulk operations
294 │ ├── touch.js # Touch event handling
295 │ ├── mobile.js # Mobile-specific behavior
296 │ │
297 │ ├── tasks.js # Task list, CRUD
298 │ ├── tasks-render.js # Task rendering
299 │ ├── tasks-kanban.js # Kanban board view
300 │ ├── projects.js # Project list, detail, CRUD
301 │ ├── projects-render.js # Project rendering
302 │ ├── events.js # Event list, CRUD
303 │ ├── emails.js # Email list, threading, CRUD
304 │ ├── email-accounts.js # Email account management
305 │ ├── contacts.js # Contact CRUD
306 │ ├── contacts-render.js # Contact rendering
307 │ │
308 │ ├── day-planning.js # Time-blocking day planner
309 │ ├── day-planning-render.js # Day plan rendering
310 │ ├── weekly-review.js # Weekly review workflow
311 │ ├── weekly-review-render.js # Weekly review rendering
312 │ ├── snooze.js # Snooze modal + actions
313 │ ├── settings.js # Settings, export
314 │ ├── settings-sync.js # Cloud sync settings
315 │ ├── themes.js # Theme switching
316 │ ├── export.js # Data export
317 │ ├── import.js # Data import from JSON
318 │ ├── seed-data.js # Demo data seeding
319 │ │
320 │ └── tests/
321 │ ├── test-runner.js # Test framework
322 │ └── run.js # Test execution
323 └── index.html # Entry point
324 ```
325
326 ## Data Flow
327
328 ```
329 Frontend (JS)
330 → invoke("command_name", { args })
331 → Tauri IPC
332 → commands/module.rs
333 → Repository trait method
334 → SQLite query
335 → Response (with pre-computed display fields) → Frontend
336 → JS renders pre-computed values directly to DOM
337 ```
338
339 ## Key Design Decisions
340
341 ### Clean Architecture
342 - Core domain models have no dependencies on persistence
343 - Repository traits define contracts, implementations are separate crates
344 - Easy to swap databases or add new ones
345
346 ### Vanilla Frontend
347 - No JavaScript framework — vanilla JS with IIFE modules
348 - All code under `GoingsOn` global namespace (no `window.*` exports)
349 - Centralized state via `GoingsOn.state` with pub/sub reactivity
350 - IPC via Tauri invoke
351 - Virtual scrolling for large lists (`GoingsOn.VirtualScroller`)
352 - Optimized for desktop-class performance
353
354 ### TaskWarrior-Inspired Features
355 - Urgency calculation algorithm
356 - Quick-add parser with natural language
357 - Annotations and recurring tasks
358
359 ## Testing Strategy
360
361 - 658 Rust tests + 48 JS tests
362 - Unit tests in core crate for business logic
363 - Integration tests for repository implementations
364 - Tauri command tests
365 - JS tests in `frontend/js/tests/`
366