Manager pattern overview
Managers in Nook follow these principles:Single responsibility
Each manager handles one feature domain (tabs, profiles, extensions, etc.)
Observable state
Managers expose state via
@Observable or @Published for reactive UI updatesMainActor confinement
All managers are
@MainActor for thread-safe UI interactionEnvironment injection
Managers are injected via SwiftUI environment, not global singletons (goal)
Manager directory
Nook has 27 managers inNook/Managers/:
Core managers
BrowserManager
BrowserManager
Location:
Nook/Managers/BrowserManager/BrowserManager.swift:18Status: Legacy “god object” (~2800 lines) being refactoredResponsibilities:- Central coordinator that connects all other managers
- Owns TabManager, ProfileManager, ExtensionManager, etc.
- Routes commands from menu bar and keyboard shortcuts
- Handles window lifecycle and state synchronization
ObservableObject with @Published properties (Combine)Refactoring plan: Eliminate by making managers independent and environment-injectedTabManager
TabManager
Location: Pattern: Uses Swift actor for thread-safe persistence
Nook/Managers/TabManager/TabManager.swiftResponsibilities:- Tab lifecycle (create, close, reorder, pin)
- Space organization and active tab tracking
- Folder management within spaces
- Atomic persistence via
PersistenceActor - Session restoration from SwiftData
- Coalesced writes to prevent excessive I/O
- Backup/recovery on persistence failure
- Global pinned tabs (essentials) vs space-pinned tabs
ProfileManager
ProfileManager
Location:
Nook/Managers/ProfileManager/ProfileManager.swift:13Responsibilities:- Manage persistent profiles (each with isolated
WKWebsiteDataStore) - Create/delete/rename profiles
- Handle ephemeral/incognito profiles (non-persistent data stores)
- Profile switching and data isolation
- Each profile gets a unique
WKWebsiteDataStore(forIdentifier: profileId) - Ephemeral profiles use
WKWebsiteDataStore.nonPersistent() - Prevents deletion of last profile
WindowRegistry
WindowRegistry
Location:
Nook/Managers/WindowRegistry/WindowRegistry.swift:14Responsibilities:- Track all open browser windows
- Maintain active (focused) window state
- Coordinate window lifecycle (register, unregister, activate)
- Provide callbacks for window events
@Observable with callbacks for lifecycle eventsWebViewCoordinator
WebViewCoordinator
Location:
Nook/Managers/WebViewCoordinator/WebViewCoordinator.swift:14Responsibilities:- Manage webview instances across multiple windows
- Coordinate primary vs clone webviews for multi-window tabs
- Prevent duplicate webview creation
- Clean up webviews when windows close
WebViewCoordinator.swift:96-131):- If tab not shown in any window → create primary webview
- If tab already shown elsewhere → create clone webview
- If window already has webview for tab → return existing
Feature managers
ExtensionManager
ExtensionManager
Location:
Nook/Managers/ExtensionManager/ExtensionManager.swiftResponsibilities:WKWebExtensionControllerintegration (macOS 15.4+)- Extension installation, loading, updating
- Permission management (install-time and runtime)
- Native messaging host integration
- Extension bridge for
chrome.*APIs
HistoryManager
HistoryManager
Location:
Nook/Managers/HistoryManager/HistoryManager.swiftResponsibilities:- Track browsing history per profile
- Persist history entries to SwiftData (
HistoryEntity) - Search history by title/URL
- Clear history with date filters
DownloadManager
DownloadManager
Location:
Nook/Managers/DownloadManager/DownloadManager.swiftResponsibilities:- Handle
WKDownloadDelegatecallbacks - Track active downloads
- Provide download progress UI
- Manage download destination paths
CookieManager
CookieManager
CacheManager
CacheManager
Location:
Nook/Managers/CacheManager/CacheManager.swiftResponsibilities:- Manage
WKWebsiteDataStorecache - Clear cache per profile
- Calculate cache size estimates
SearchManager
SearchManager
Location:
Nook/Managers/SearchManager/SearchManager.swiftResponsibilities:- Handle search engine configuration
- Parse search queries vs URLs in address bar
- Provide autocomplete suggestions
DialogManager
DialogManager
Location:
Nook/Managers/DialogManager/DialogManager.swiftResponsibilities:- Show system dialogs (alerts, confirmations)
- Manage dialog queue and presentation
- Handle basic auth prompts
FindManager
FindManager
Location:
Nook/Managers/FindManager/FindManager.swiftResponsibilities:- In-page search (find bar)
- Highlight matches
- Navigate between results
ZoomManager
ZoomManager
Location:
Nook/Managers/ZoomManager/ZoomManager.swiftResponsibilities:- Track zoom levels per tab
- Apply zoom presets
- Persist zoom preferences
SplitViewManager
SplitViewManager
Location:
Nook/Managers/SplitViewManager/SplitViewManager.swiftResponsibilities:- Manage split-screen tab viewing
- Coordinate primary/secondary pane state
- Clean up split state on window close
UI managers
GradientColorManager
GradientColorManager
Location:
Nook/Managers/GradientColorManager/GradientColorManager.swiftResponsibilities:- Manage space gradient themes
- Generate gradient animations
- Persist gradient configurations
HoverSidebarManager
HoverSidebarManager
PeekManager
PeekManager
Location:
Nook/Managers/PeekManager/PeekManager.swiftResponsibilities:- Show link preview overlays (Option + hover)
- Manage peek webview lifecycle
- Handle peek-to-tab conversion
DragManager
DragManager
Location:
Nook/Managers/DragManager/TabDragManager.swiftResponsibilities:- Handle tab drag-and-drop
- Reorder tabs within spaces
- Move tabs between spaces and windows
Specialized managers
AIManager
AIManager
Location:
Nook/Managers/AIManager/AIService.swiftResponsibilities:- AI chat integration (OpenAI, Gemini, Ollama, OpenRouter)
- MCP (Model Context Protocol) server management
- Browser tool execution for AI actions
KeyboardShortcutManager
KeyboardShortcutManager
Location:
Nook/Managers/KeyboardShortcutManager/KeyboardShortcutManager.swiftResponsibilities:- Global keyboard shortcut registration
- Command routing to managers
- Conflict detection and warnings
AuthenticationManager
AuthenticationManager
Location:
Nook/Managers/AuthenticationManager/AuthenticationManager.swiftResponsibilities:- HTTP basic auth credential storage
- WebAuthn/Passkey integration
- Credential prompt handling
ImportManager
ImportManager
Location:
Nook/Managers/ImportManager/ImportManager.swiftResponsibilities:- Import bookmarks/history from Safari, Chrome, Firefox
- Parse browser export formats
- Merge imported data with existing tabs/spaces
PrivacyManager
PrivacyManager
Location:
Nook/Managers/PrivacyManager/PrivacyManager.swiftResponsibilities:- Configure tracking protection
- Manage content blockers
- Handle privacy-related WebKit settings
BrowserManager as coordinator
BrowserManager currently acts as the glue between all managers:
Refactoring roadmap
The goal is to eliminateBrowserManager by making managers independent:
Before (current):
- Migrating all managers to
@Observable(Swift Observation) - Removing cross-manager dependencies where possible
- Using protocols/callbacks for necessary coordination
Manager lifecycle
Initialization
Managers are created inNookApp.init() and BrowserManager.init():
Environment injection
Managers flow down the view hierarchy:Cleanup
Managers clean up resources inAppDelegate.applicationWillTerminate():
Best practices
When working with managers:Prefer environment injection over singletonsEven though some managers (like
ExtensionManager) use singletons for WebKit compatibility, new code should use environment injection.Use @MainActor for all managersSince managers interact with SwiftUI state, they must be
@MainActor confined to avoid data races.Avoid circular dependenciesIf Manager A needs Manager B, consider:
- Using a protocol/delegate pattern
- Injecting a callback closure
- Emitting events via NotificationCenter
Next steps
Models
Explore data models used by managers
State management
Learn about @Observable vs @Published patterns