# Home Tab Architecture

> **Note:** Do not add a file structure section to this document. File layout is navigable directly in the project and goes stale quickly.

## Pattern: MVVM + Coordinator + Domain Controllers

Each screen in Home Tab follows MVVM with a single shared Coordinator that handles navigation and page view lifecycle. Domain state lives in `HomeTabStore` and its sub-controllers, which are independent of the UI layer. `UIFactory` centralises all view and ViewModel construction.

```mermaid
graph TD
    Feature["HomeTabFeature\n(long-lived owner)"]
    Controller["HomeTabStore"]
    Documents["DocumentsStore"]
    Tools["ToolsStore"]
    Factory["UIFactory"]
    Coord["HomeTabCoordinator"]
    NavState["HomeTabNavigationStateContainer"]
    VC["HomeTabViewController\n(lifecycle root)"]
    VM["HomeTabViewModel"]
    Cache["pages cache\n[HomeTabPage → NSView]"]
    Hosting["NSHostingView"]
    PageView["PageView (SwiftUI)"]
    PageVM["PageViewModel"]

    Feature -->|strong| Controller
    Controller -->|strong| Documents
    Controller -->|strong| Tools

    Feature -->|creates per call| Factory
    Factory -->|strong| Controller
    Feature -->|creates per call| Coord
    Coord -->|strong| Factory
    Coord -->|strong| NavState
    Coord -->|strong| Cache

    Factory -->|creates| VC
    Factory -->|creates| VM

    VC -->|strong| Coord
    VC -->|strong| VM

    VM -->|weak| Coord
    VM -->|subscribes| NavState

    Cache -->|strong| Hosting
    Hosting -->|strong| PageView
    PageView -->|strong| PageVM

    PageVM -->|weak| Coord
    PageVM -->|strong| Controller
```

## Ownership Rules

**`HomeTabViewController` is the lifecycle root** for a single tab instance. It holds strong references to both the coordinator and the view model. Domain state lives longer — it is owned by `HomeTabFeature`.

| Reference | Strength | Reason |
|---|---|---|
| `HomeTabFeature` → `HomeTabStore` | **strong** | Domain state outlives any individual VC instance. |
| `HomeTabFeature` → `UIFactory` | transient (per call) | Feature creates a factory per `makeHomeTabViewController()` call and hands it to the coordinator. |
| `HomeTabCoordinator` → `UIFactory` | **strong** | Coordinator delegates all creation to the factory for the duration of its lifetime. |
| `UIFactory` → `HomeTabStore` | **strong** | Factory injects the controller into every ViewModel it creates. |
| `HomeTabCoordinator` → `HomeTabNavigationStateContainer` | **strong** | Coordinator owns the navigation state and drives page transitions. |
| `HomeTabViewController` → `HomeTabCoordinator` | **strong** | Retention anchor. Coordinator lives as long as the VC. |
| `HomeTabViewController` → `HomeTabViewModel` | **strong** | VC owns its model. |
| `HomeTabViewModel` → `HomeTabCoordinator` | **weak** | VM calls `setCurrentPage` on the coordinator, but must not extend its lifetime. |
| `HomeTabViewModel` → `HomeTabNavigationStateContainer` | subscription (`AnyCancellable`) | VM observes page changes; subscription is cancelled when VM is deallocated. |
| `HomeTabCoordinator` → page `NSView` cache | **strong** | Coordinator is responsible for page view lifecycle. |
| `PageViewModel` → `HomeTabCoordinator` | **weak** | Coordinator owns the page view (via cache) which owns the ViewModel — strong would be a retain cycle. |
| `PageViewModel` → `HomeTabStore` | **strong** | ViewModels read and mutate domain state. `HomeTabStore` is not owned by the VC, so no cycle. |

## Creation Flow

`HomeTabFeature` creates `HomeTabStore` once and keeps it alive. Each call to `makeHomeTabViewController()` creates a fresh `UIFactory` and coordinator pair backed by the shared controller:

```swift
// HomeTabFeature.makeHomeTabViewController()
let factory = UIFactory(controller: self.controller)
let coordinator = HomeTabCoordinator(factory: factory)
return coordinator.start()

// HomeTabCoordinator.start()
factory.makeHomeTabViewController(coordinator: self, navigationState: self.navigationState)

// UIFactory.makeHomeTabViewController(coordinator:navigationState:)
let model = HomeTabViewModel(coordinator: coordinator, navigationState: navigationState)
return HomeTabViewController(coordinator: coordinator, model: model)
```

Navigation state is decoupled via `HomeTabNavigationStateContainer`: the coordinator drives it, and the view model subscribes to it — no direct back-reference from VM to coordinator is needed for state observation.

Page views are created lazily by the coordinator and cached:

```swift
// HomeTabCoordinator.reusePageView(for:)
factory.makePageView(for: page, coordinator: self)  // UIFactory injects controller into PageViewModel
```

## Domain Controllers

`HomeTabStore` is a lightweight container for the feature's sub-controllers:

| Controller | Responsibility |
|---|---|
| `DocumentsStore` | Source of truth for all documents. Owns `allDocuments`, `recentDocumentIDs` (`OrderedSet`), `favoriteDocumentIDs` (`OrderedSet`). Notifies observers on mutation. |
| `ToolsStore` | Static list of tool categories and tools shown on the Tools page. |

`DocumentsStore` uses a manual observer pattern (not Combine `@Published`) so that `@MainActor`-isolated mutations and notifications are explicit. Observers register via `addObserver(_:) -> AnyCancellable`.

## Roles

**`HomeTabFeature`**
- Long-lived owner of `HomeTabStore`.
- Factory for `HomeTabViewController` instances; each call returns a new independent VC backed by the shared controller.

**`UIFactory`**
- Centralises all view and ViewModel construction.
- Holds `HomeTabStore` and injects it into every ViewModel it creates.
- Created fresh per `makeHomeTabViewController()` call; lifetime is tied to the coordinator.

**`HomeTabCoordinator`**
- Caches page `NSView`s (one per `HomeTabPage`, created lazily via `UIFactory`).
- Owns `HomeTabNavigationStateContainer` and drives page transitions via `setCurrentPage(_:)`.
- Delegates all construction to `UIFactory`; contains no `HomeTabStore` reference itself.

**`HomeTabNavigationStateContainer`**
- Source of truth for the currently active page.
- Decouples the coordinator (writer) from the view model (reader) without a direct reference between them.

**`HomeTabViewModel`**
- Observes `HomeTabNavigationStateContainer` to keep `currentPage` in sync with SwiftUI.
- Forwards `setSelectedPage` calls to the coordinator (weak ref).

**`HomeTabViewController`**
- Hosts the SwiftUI root view (`HomeTabRootView`).
- Single strong owner of both coordinator and view model for the tab's lifetime.

**`PageViewModel` (e.g. `RecentsPageViewModel`)**
- Owns the UI state for a single page.
- Holds `HomeTabStore` strongly to read/mutate domain state.
- Calls coordinator weakly to trigger navigation to another page.

## Adding a New Page

1. Add a case to `HomeTabPage`.
2. Add the display name to `HomeTabSidebarView.pageTitle(for:)`.
3. Create `Pages/<Name>/<Name>Page.swift` with a SwiftUI `View` named `<Name>PageView` and an `ObservableObject` ViewModel named `<Name>PageViewModel`. The ViewModel takes `coordinator: HomeTabCoordinator` (stored `private weak`) and `controller: HomeTabStore` (stored `private let`).
4. Add a `case` to `UIFactory.makePageView(for:coordinator:)` that instantiates the ViewModel and wraps the view in `NSHostingView`.
