# GoingsOn Architecture Email, calendar, tasks in one place. Project management for individuals and small teams. 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). ## High-Level Overview ``` ┌─────────────────────────────────────────────────────────┐ │ User Interface │ │ ┌────────────────────────────────────────────────────┐ │ │ │ Tauri Desktop (Vanilla JS) │ │ │ └─────────────────────┬──────────────────────────────┘ │ │ │ │ │ ┌─────────────────────▼──────────────────────────────┐ │ │ │ Tauri Commands (src-tauri/) │ │ │ └─────────────────────┬──────────────────────────────┘ │ └────────────────────────┼─────────────────────────────────┘ │ ┌────────────────────────▼─────────────────────────────────┐ │ goingson-core │ │ ┌──────────┐ ┌──────────┐ ┌────────────┐ ┌────────────┐ │ │ │ Models │ │Repository│ │ Urgency │ │ Parser │ │ │ │ │ │ Traits │ │ Calculator │ │ (Quick-Add)│ │ │ └──────────┘ └────┬─────┘ └────────────┘ └────────────┘ │ └────────────────────┼─────────────────────────────────────┘ │ ┌──────▼───────────┐ │ goingson-db- │ │ sqlite │ │ (Desktop) │ └──────────────────┘ Additional crates: plugin-runtime Rhai plugin system (import plugins) ``` ## Workspace Structure ``` goingson/ ├── crates/ │ ├── core/ # Domain models, traits, business logic │ ├── db-sqlite/ # SQLite repository implementations │ └── plugin-runtime/ # Rhai plugin system ├── src-tauri/ # Tauri desktop app (single-user) └── migrations/ └── sqlite/ # SQLite schema migrations (33 files) ``` ## Crate Dependencies ``` goingson-desktop (src-tauri) ├── goingson-db-sqlite │ └── goingson-core └── plugin-runtime └── goingson-core (for shared types) ``` ## Core Crate (`crates/core/`) The core crate defines domain models and repository traits, independent of persistence. ### Modules | Module | Purpose | |--------|---------| | `models/` | Domain types (17 model files) | | `repository.rs` | Repository traits (data access contracts) | | `urgency.rs` | TaskWarrior-inspired urgency calculation algorithm | | `parser.rs` | Quick-add natural language parser | | `recurrence.rs` | Task/event recurrence logic | | `validation.rs` | Input validation trait | | `constants.rs` | Named constants for thresholds, formats | | `error.rs` | Unified CoreError type | ### Key Types ```rust // Domain entities Project, Task, Event, Email, EmailAccount, User Contact, ContactEmail, ContactPhone, SocialHandle, ContactCustomField SavedView, Annotation, Subtask, Milestone WeeklyReview, BackupSettings // Enums with display/parse support ProjectType, ProjectStatus, TaskStatus, Priority, Recurrence SortDirection, SortField, TaskSortColumn ViewType, ViewFilters, BlockType EmailAuthType, MilestoneStatus // DTOs for creation/updates NewProject, NewTask, NewEvent, NewEmail UpdateProject, UpdateTask, UpdateEvent // Newtype IDs ProjectId, TaskId, EventId, EmailId, ContactId EmailAccountId, AnnotationId, SubtaskId, SavedViewId MilestoneId, CustomFieldId ``` ### Repository Traits ```rust ProjectRepository, TaskRepository, EventRepository EmailRepository, EmailAccountRepository, ContactRepository SearchRepository, StatsRepository, SavedViewRepository AnnotationRepository, SubtaskRepository, MilestoneRepository WeeklyReviewRepository, BackupSettingsRepository UserRepository ``` ## Database Layer (`crates/db-sqlite/`) SQLite persistence for the desktop app. Single-user, local storage. 50 migrations in `migrations/sqlite/`. ``` src/ ├── lib.rs # SQLite pool initialization ├── utils.rs # format_datetime, parse_uuid, email validation └── repository/ ├── mod.rs # Re-exports all repositories ├── project_repo.rs ├── task_repo.rs ├── event_repo.rs ├── email_repo.rs ├── email_account_repo.rs ├── contact_repo.rs ├── user_repo.rs ├── search_repo.rs # FTS5 full-text search ├── stats_repo.rs # Dashboard aggregations ├── saved_view_repo.rs ├── annotation_repo.rs ├── subtask_repo.rs ├── milestone_repo.rs ├── weekly_review_repo.rs └── backup_settings_repo.rs ``` ## Tauri Desktop App (`src-tauri/`) Single-user desktop application. ``` src/ ├── main.rs # Tauri app setup, command registration ├── state.rs # AppState with repository instances ├── notifications.rs # Snooze watcher, native notifications ├── email/ # IMAP/SMTP client └── commands/ ├── mod.rs # Re-exports all commands ├── error.rs # Error type definitions ├── task.rs # Task CRUD, annotations, subtasks, snoozing, waiting ├── project.rs # Project management ├── event.rs # Calendar events ├── email.rs # Email CRUD, threading, archive ├── email_account.rs # Email account setup, sync interval ├── email_sync.rs # IMAP/SMTP sync orchestration ├── contact.rs # Contact CRUD, emails, phones, social handles ├── search.rs # Full-text search across all entities ├── stats.rs # Dashboard statistics ├── day_planning.rs # Time blocking ├── weekly_review.rs # Weekly review workflow ├── saved_views.rs # Custom filter views ├── milestone.rs # Milestone CRUD and reordering ├── plugin.rs # Plugin registry, hot-reload, import ├── oauth.rs # OAuth2 flows (Fastmail, Google, Microsoft) ├── export.rs # JSON, CSV, ICS export; backup/restore ├── sync.rs # Cloud sync via SyncKit ├── themes.rs # Theme list and color queries └── window.rs # Window management, compose window ``` ### Command Pattern Tauri commands are async functions that: 1. Accept `State>` for repository access 2. Deserialize input from frontend via `#[serde(rename_all = "camelCase")]` 3. Call repository methods 4. Serialize response types back to frontend ```rust #[tauri::command] pub async fn create_task( state: State<'_, Arc>, input: TaskInput, ) -> Result { state.tasks .create(DESKTOP_USER_ID, new_task) .await .map(TaskResponse::from) .map_err(|e| e.to_string()) } ``` ## Frontend Architecture (Tauri Desktop) The desktop frontend uses vanilla JavaScript organized under the `GoingsOn` global namespace. 66 source files. ### Namespace Organization ``` window.GoingsOn = { api: { ... }, // Tauri IPC abstraction layer state: { ... }, // Centralized state with pub/sub ui: { ... }, // Modal, toast, form utilities utils: { ... }, // HTML escaping, validation // Domain modules (IIFE-wrapped) projects: { ... }, tasks: { ... }, events: { ... }, emails: { ... }, contacts: { ... }, // Feature modules savedViews: { ... }, snooze: { ... }, navigation: { ... }, settings: { ... }, app: { ... }, // Infrastructure VirtualScroller, // Virtual scrolling for large lists SelectionManager, // Multi-select with shift/ctrl PaginationManager, // Page navigation }; ``` ### Module Pattern Each domain module is wrapped in an IIFE and exposes its public API through the namespace: ```javascript (function() { 'use strict'; // Private state and helpers async function load() { ... } function openNew() { ... } // Public API GoingsOn.myModule = { load, openNew }; })(); ``` ### Pre-computed Response Fields Rust response types include pre-computed display values so JS never calculates dates, formatting, or derived state: | Response Type | Pre-computed Fields | |--------------|---------------------| | TaskResponse | `dueFormatted`, `urgencyClass`, `isOverdue`, `isSnoozed`, `subtaskCount`, `subtaskCompleted`, `subtaskProgress` | | EventResponse | `timeFormatted`, `dateFormatted`, `isPast`, `proximityClass`, `proximityLabel` | | EmailResponse | `receivedFormatted` | | EmailAccountResponse | `lastSyncFormatted` | ### Centralized State All shared data lives in `GoingsOn.state` with reactive pub/sub: ```javascript GoingsOn.state.set('tasks', updatedTasks); // Triggers subscribers GoingsOn.state.subscribe('tasks', (newVal, oldVal) => { ... }); ``` ### File Organization ``` src-tauri/frontend/ ├── css/ │ └── styles.css # Design system + all components ├── fonts/ │ └── Reglo-Bold.woff2 # Display font ├── js/ │ ├── goingson.js # Namespace root (window.GoingsOn) │ ├── api.js # Tauri IPC abstraction │ ├── state.js # Centralized state + pub/sub │ ├── utils.js # Escaping, validation, debounce │ ├── router.js # View routing │ ├── app.js # App initialization, menu listeners │ │ │ ├── components.js # Toast, confirm dialog │ ├── components-modal.js # Modal system │ ├── form-modal.js # Form modal (openFormModal) │ ├── navigation.js # View switching, sidebar │ ├── keyboard.js # Keyboard shortcuts │ ├── selection-manager.js # Multi-select with shift/ctrl │ ├── pagination-manager.js # Page navigation │ ├── virtual-scroller.js # Virtual scrolling for large lists │ ├── context-menus.js # Right-click context menus │ ├── bulk-actions.js # Multi-select bulk operations │ ├── touch.js # Touch event handling │ ├── mobile.js # Mobile-specific behavior │ │ │ ├── tasks.js # Task list, CRUD │ ├── tasks-render.js # Task rendering │ ├── tasks-kanban.js # Kanban board view │ ├── projects.js # Project list, detail, CRUD │ ├── projects-render.js # Project rendering │ ├── events.js # Event list, CRUD │ ├── emails.js # Email list, threading, CRUD │ ├── email-accounts.js # Email account management │ ├── contacts.js # Contact CRUD │ ├── contacts-render.js # Contact rendering │ │ │ ├── day-planning.js # Time-blocking day planner │ ├── day-planning-render.js # Day plan rendering │ ├── weekly-review.js # Weekly review workflow │ ├── weekly-review-render.js # Weekly review rendering │ ├── snooze.js # Snooze modal + actions │ ├── settings.js # Settings, export │ ├── settings-sync.js # Cloud sync settings │ ├── themes.js # Theme switching │ ├── export.js # Data export │ ├── import.js # Data import from JSON │ ├── seed-data.js # Demo data seeding │ │ │ └── tests/ │ ├── test-runner.js # Test framework │ └── run.js # Test execution └── index.html # Entry point ``` ## Data Flow ``` Frontend (JS) → invoke("command_name", { args }) → Tauri IPC → commands/module.rs → Repository trait method → SQLite query → Response (with pre-computed display fields) → Frontend → JS renders pre-computed values directly to DOM ``` ## Key Design Decisions ### Clean Architecture - Core domain models have no dependencies on persistence - Repository traits define contracts, implementations are separate crates - Easy to swap databases or add new ones ### Vanilla Frontend - No JavaScript framework — vanilla JS with IIFE modules - All code under `GoingsOn` global namespace (no `window.*` exports) - Centralized state via `GoingsOn.state` with pub/sub reactivity - IPC via Tauri invoke - Virtual scrolling for large lists (`GoingsOn.VirtualScroller`) - Optimized for desktop-class performance ### TaskWarrior-Inspired Features - Urgency calculation algorithm - Quick-add parser with natural language - Annotations and recurring tasks ## Testing Strategy - 658 Rust tests + 48 JS tests - Unit tests in core crate for business logic - Integration tests for repository implementations - Tauri command tests - JS tests in `frontend/js/tests/`