# ngoxuanchien/timepaper architecture

> Architecture diagram of the GitHub repository ngoxuanchien/timepaper, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-25). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/ngoxuanchien/timepaper
- Repository: https://github.com/ngoxuanchien/timepaper

## Overview

Timepaper is a native macOS menu-bar app that turns a user’s weekly class schedule and optional Calendar events into per-display desktop wallpapers. The main workflow runs through AppState: it gathers schedule inputs, coordinates rendering and caching, applies images, persists display references, and triggers safe cleanup. AutomationEngine refreshes this workflow on scheduled boundaries and system events. The README documents the major capabilities; unsampled source means some internal call links are shown only where the excerpts or documentation establish them.

Main entry points: [`Timepaper/App/AppState.swift`](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/App/AppState.swift) (AppState), [`Timepaper/Core/AutomationEngine.swift`](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/AutomationEngine.swift) (Automation engine), [`Timepaper/Services/CalendarService.swift`](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Services/CalendarService.swift) (Calendar sync), [`Timepaper/Services/WallpaperCleanupService.swift`](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Services/WallpaperCleanupService.swift) (Storage cleanup)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_app["App coordination"]
  node_appstate["AppState<br/>[AppState.swift]"]
  node_notifications["Class reminders"]
end

subgraph group_inputs["Schedule and settings"]
  node_entrymodel[("Schedule entries")]
  node_displayconfig[("Display configuration")]
  node_wallpaperitem[("Imported wallpapers")]
  node_settings["App settings<br/>[AppSettings.swift]"]
  node_calendarservice["Calendar sync"]
  node_scheduleengine["Schedule queries"]
end

subgraph group_wallpaper["Wallpaper pipeline"]
  node_importservice["Wallpaper import"]
  node_renderrequest["Render request"]
  node_renderer["Wallpaper renderer"]
  node_cache["Render cache"]
  node_displaymanager["Display discovery"]
  node_wallpaperservice["Desktop apply"]
  node_cleanup["Storage cleanup"]
  node_cleanupplanner["Cleanup planner"]
end

subgraph group_automation["Automation"]
  node_automation["Automation engine"]
  node_scheduler["Next-fire scheduler"]
end

subgraph group_ui["User interface"]
  node_popover["Menu bar popover"]
  node_settingsui["Settings views"]
end

node_user(("User"))
node_os(("macOS events"))
node_calendar(("Calendar.app data"))
node_swiftdata[("SwiftData store")]
node_desktop["macOS desktop"]

node_user -->|"opens"| node_popover
node_user -->|"edits"| node_settingsui
node_popover -->|"invokes"| node_appstate
node_settingsui -->|"invokes"| node_appstate
node_appstate -->|"reads and writes"| node_entrymodel
node_appstate -->|"reads and writes"| node_displayconfig
node_appstate -->|"reads and writes"| node_wallpaperitem
node_appstate -->|"reads"| node_settings
node_entrymodel -->|"persists"| node_swiftdata
node_displayconfig -->|"persists"| node_swiftdata
node_wallpaperitem -->|"persists"| node_swiftdata
node_appstate -->|"requests events"| node_calendarservice
node_calendarservice -->|"reads events"| node_calendar
node_appstate -->|"queries schedule"| node_scheduleengine
node_appstate -->|"builds"| node_renderrequest
node_appstate -->|"requests image"| node_cache
node_cache -->|"renders on miss"| node_renderer
node_appstate -->|"discovers displays"| node_displaymanager
node_appstate -->|"applies image"| node_wallpaperservice
node_wallpaperservice -->|"sets wallpaper"| node_desktop
node_appstate -->|"requests cleanup"| node_cleanup
node_cleanup -->|"plans deletion"| node_cleanupplanner
node_cleanup -->|"scans generated files"| node_cache
node_appstate -->|"starts and configures"| node_automation
node_automation -->|"computes next fire"| node_scheduler
node_os -->|"signals changes"| node_automation
node_calendarservice -->|"posts change event"| node_automation
node_automation -->|"dispatches refresh"| node_appstate
node_appstate -->|"schedules reminders"| node_notifications
node_settingsui -->|"imports images"| node_importservice
node_importservice -->|"provides metadata"| node_wallpaperitem

click node_appstate "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/App/AppState.swift"
click node_entrymodel "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Models/ScheduleEntry.swift"
click node_displayconfig "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Models/DisplayConfiguration.swift"
click node_wallpaperitem "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Models/WallpaperItem.swift"
click node_settings "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Services/AppSettings.swift"
click node_calendarservice "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Services/CalendarService.swift"
click node_scheduleengine "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/ScheduleEngine.swift"
click node_importservice "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Services/WallpaperImportService.swift"
click node_renderrequest "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/RenderRequest.swift"
click node_renderer "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/WallpaperRenderer.swift"
click node_cache "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/WallpaperCacheManager.swift"
click node_displaymanager "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/DisplayManager.swift"
click node_wallpaperservice "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Services/WallpaperService.swift"
click node_cleanup "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Services/WallpaperCleanupService.swift"
click node_cleanupplanner "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/WallpaperCleanupPlanner.swift"
click node_automation "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/AutomationEngine.swift"
click node_scheduler "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/AutomationScheduler.swift"
click node_popover "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/UI/MenuBarPopover.swift"
click node_settingsui "https://github.com/ngoxuanchien/timepaper/tree/main/Timepaper/UI/Settings"
click node_notifications "https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Services/NotificationService.swift"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_appstate,node_notifications,node_user toneBlue
class node_entrymodel,node_displayconfig,node_wallpaperitem,node_settings,node_calendarservice,node_scheduleengine,node_swiftdata toneAmber
class node_importservice,node_renderrequest,node_renderer,node_cache,node_displaymanager,node_wallpaperservice,node_cleanup,node_cleanupplanner toneMint
class node_automation,node_scheduler toneRose
class node_popover,node_settingsui,node_os,node_calendar,node_desktop toneIndigo
```

## Components

### App coordination

- [AppState](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/App/AppState.swift): `Timepaper/App/AppState.swift`
- [Class reminders](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Services/NotificationService.swift): `Timepaper/Services/NotificationService.swift`

### Schedule and settings

- [Schedule entries](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Models/ScheduleEntry.swift): `Timepaper/Models/ScheduleEntry.swift`
- [Display configuration](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Models/DisplayConfiguration.swift): `Timepaper/Models/DisplayConfiguration.swift`
- [Imported wallpapers](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Models/WallpaperItem.swift): `Timepaper/Models/WallpaperItem.swift`
- [App settings](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Services/AppSettings.swift): `Timepaper/Services/AppSettings.swift`
- [Calendar sync](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Services/CalendarService.swift): `Timepaper/Services/CalendarService.swift`
- [Schedule queries](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/ScheduleEngine.swift): `Timepaper/Core/ScheduleEngine.swift`

### Wallpaper pipeline

- [Wallpaper import](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Services/WallpaperImportService.swift): `Timepaper/Services/WallpaperImportService.swift`
- [Render request](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/RenderRequest.swift): `Timepaper/Core/RenderRequest.swift`
- [Wallpaper renderer](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/WallpaperRenderer.swift): `Timepaper/Core/WallpaperRenderer.swift`
- [Render cache](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/WallpaperCacheManager.swift): `Timepaper/Core/WallpaperCacheManager.swift`
- [Display discovery](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/DisplayManager.swift): `Timepaper/Core/DisplayManager.swift`
- [Desktop apply](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Services/WallpaperService.swift): `Timepaper/Services/WallpaperService.swift`
- [Storage cleanup](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Services/WallpaperCleanupService.swift): `Timepaper/Services/WallpaperCleanupService.swift`
- [Cleanup planner](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/WallpaperCleanupPlanner.swift): `Timepaper/Core/WallpaperCleanupPlanner.swift`

### Automation

- [Automation engine](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/AutomationEngine.swift): `Timepaper/Core/AutomationEngine.swift`
- [Next-fire scheduler](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/Core/AutomationScheduler.swift): `Timepaper/Core/AutomationScheduler.swift`

### User interface

- [Menu bar popover](https://github.com/ngoxuanchien/timepaper/blob/main/Timepaper/UI/MenuBarPopover.swift): `Timepaper/UI/MenuBarPopover.swift`
- [Settings views](https://github.com/ngoxuanchien/timepaper/tree/main/Timepaper/UI/Settings): `Timepaper/UI/Settings`

### Other components

- **User**
- **macOS events**
- **Calendar.app data**
- **SwiftData store**
- **macOS desktop**

## Connections

- User → Menu bar popover: opens
- User → Settings views: edits
- Menu bar popover → AppState: invokes
- Settings views → AppState: invokes
- AppState → Schedule entries: reads and writes
- AppState → Display configuration: reads and writes
- AppState → Imported wallpapers: reads and writes
- AppState → App settings: reads
- Schedule entries → SwiftData store: persists
- Display configuration → SwiftData store: persists
- Imported wallpapers → SwiftData store: persists
- AppState → Calendar sync: requests events
- Calendar sync → Calendar.app data: reads events
- AppState → Schedule queries: queries schedule
- AppState → Render request: builds
- AppState → Render cache: requests image
- Render cache → Wallpaper renderer: renders on miss
- AppState → Display discovery: discovers displays
- AppState → Desktop apply: applies image
- Desktop apply → macOS desktop: sets wallpaper
- AppState → Storage cleanup: requests cleanup
- Storage cleanup → Cleanup planner: plans deletion
- Storage cleanup → Render cache: scans generated files
- AppState → Automation engine: starts and configures
- Automation engine → Next-fire scheduler: computes next fire
- macOS events → Automation engine: signals changes
- Calendar sync → Automation engine: posts change event
- Automation engine → AppState: dispatches refresh
- AppState → Class reminders: schedules reminders
- Settings views → Wallpaper import: imports images
- Wallpaper import → Imported wallpapers: provides metadata
