Skip to content
⚠️ This document is AI-translated. The Chinese version is the authoritative source.

macOS Native App AI Development Guide

This document is intended for AI assistants to guide the development of Presto's future macOS native version. As of March 2026, extracted from Presto/docs/native-app-refactoring.md.


Scope

This guide applies to:

  • Target project: Presto's future macOS native version (Swift + SwiftUI)
  • Current status: Presto is currently a Go + SvelteKit + Wails application; this document prepares for a future refactor
  • AI assistant role: Generate code following Apple HIG principles and SwiftUI best practices

Note: The current Presto repository contains no Swift code. This document is a preparatory specification.


Tech Stack

LayerTechnologyVersionNotes
LanguageSwift6.0Swift Concurrency (async/await, actors)
UI FrameworkSwiftUI5.0@Observable macro, NavigationSplitView
PersistenceSwiftData1.0@Model macro, CloudKit integration
PlatformmacOS14.0+Sonoma and above
PlatformiOS/iPadOS17.0+iPhone and iPad (optional)
TypesettingTypst0.14.2Via CLI or library call
Build ToolXcode16.0+Swift Package Manager

Apple HIG Core Principles

All AI-generated UI code must follow these four principles:

1. Clarity

  • Interfaces are easy to understand, with legible text and sharp icons
  • Clear visual hierarchy so users can identify focus at a glance
  • In practice: Use system fonts (SF Pro), standard sizes, high-contrast color schemes

2. Deference

  • UI steps back to let content take center stage
  • Use translucency, blur, and subtle UI elements
  • In practice: Avoid excessive decoration, use standard system controls (.buttonStyle(.bordered))

3. Depth

  • Visual layers and fluid transitions help users understand position and navigation relationships
  • In practice: Use NavigationStack/NavigationSplitView, system transition animations

4. Consistency

  • Maintain consistent interaction patterns within the app and across platforms
  • In practice: Follow macOS menu bar conventions, standard keyboard shortcuts, system icons (SF Symbols)

SwiftUI Code Conventions

Architecture Pattern

Use the MVVM + Repository pattern:

swift
// Model: SwiftData @Model
@Model
final class RecentDocument {
    var fileURL: URL
    var lastOpened: Date
}

// ViewModel: @Observable
@Observable
final class ConversionPipeline {
    var isConverting = false
    var previewPages: [PreviewPage] = []

    func convert(markdown: String, templateId: String) async throws { }
}

// Repository: actor isolation
actor TemplateManager {
    func listTemplates() throws -> [InstalledTemplate] { }
}

// View: SwiftUI
struct ContentView: View {
    @Binding var document: PrestoDocument
    @StateObject private var pipeline = ConversionPipeline()
}

Component Naming Conventions

TypeNaming RuleExamples
ViewFeature + View suffixContentView, MarkdownEditorView
ViewModelFeature + no suffixConversionPipeline, ScrollSyncManager
ModelNoun, no suffixRecentDocument, Manifest
RepositoryFeature + ManagerTemplateManager, TypstCompiler
ProtocolFeature + ServicePrestoService
EnumNounPageContent, EditorTheme

State Management

Use the SwiftUI 5 @Observable macro (NOT @ObservableObject):

swift
@Observable
final class ConversionPipeline {
    var isConverting = false          // Automatically triggers UI updates
    var typstSource: String = ""

    func convert() async { }
}

// Usage in View
struct ContentView: View {
    @State private var pipeline = ConversionPipeline()
    // Or inject via @Environment
}

Property wrapper selection:

WrapperUsageExample
@StateView-local mutable state@State private var showSheet = false
@BindingTwo-way binding@Binding var text: String
@ObservableObservable object@Observable final class VM { }
@EnvironmentGlobal dependency injection@Environment(\.openDocument)
@AppStorageUserDefaults@AppStorage("fontSize") var fontSize = 14

macOS three-column layout:

swift
NavigationSplitView {
    // Sidebar: File navigation, template list
    SidebarView()
} detail: {
    // Main Content
    HSplitView {
        MarkdownEditorView()
        DocumentPreview()
    }
}

iOS/iPadOS adaptive layout:

swift
NavigationStack {
    // iPhone: Single column
    // iPad landscape: Split View
    // iPad portrait: Tab switching
}

macOS-Specific Conventions

Standard menus (auto-generated by macOS):

  • App menu: About Presto, Preferences (Command-,), Quit (Command-Q)
  • File menu: New (Command-N), Open (Command-O), Save (Command-S), Export PDF (Command-E)
  • Edit menu: Undo (Command-Z), Redo (Command-Shift-Z), Cut, Copy, Paste, Find (Command-F)
  • View menu: Show/Hide Sidebar (Command-Shift-S), Show Preview (Command-Shift-P)

Custom menus (via SwiftUI Commands):

swift
struct PrestoMenuCommands: Commands {
    var body: some Commands {
        CommandMenu("Typesetting") {
            Button("Switch Template") { }
                .keyboardShortcut("t")
            Button("Compile & Preview") { }
                .keyboardShortcut("r")
        }
    }
}

Keyboard Shortcuts

ShortcutActionNotes
Command-OOpen fileCross-platform
Command-SSaveSystem default
Command-EExport PDFCustom
Command-TSwitch templateCustom
Command-RCompile & previewCustom
Command-Shift-PShow/Hide previewmacOS
Control-Command-1/2/3Switch view modemacOS

Code example:

swift
.buttonStyle(.bordered)
.keyboardShortcut("e", modifiers: .command)

Window Management

Singleton windows (Settings, Template Store):

swift
@main
struct PrestoApp: App {
    var body: some Scene {
        DocumentGroup(newDocument: PrestoDocument()) { file in
            ContentView(document: file.$document)
        }

        #if os(macOS)
        Settings {
            SettingsView()
        }

        Window("Template Store", id: "template-store") {
            TemplateStoreView()
        }
        .defaultSize(width: 800, height: 600)
        #endif
    }
}

Window size constraints:

swift
.frame(minWidth: 800, minHeight: 600)
.frame(maxWidth: .infinity, maxHeight: .infinity)

System Integration

Spotlight Search:

  • Index via NSUserActivity
  • Core Spotlight API for document content indexing

Quick Look Preview:

swift
.quickLookPreview($selectedDocumentURL)

Share Extension:

swift
.shareLink(item: pdfData, preview: SharePreview("document.pdf", image: thumbnail))

Drag and Drop support:

swift
.onDrop(of: [.fileURL], isTargeted: nil) { providers in
    // Handle file drop
}

Accessibility Requirements

Full VoiceOver support:

swift
MarkdownEditorView(text: $document.markdown)
    .accessibilityLabel("Markdown Editor")
    .accessibilityHint("Enter Markdown content here")

DocumentPreview(pages: pipeline.previewPages)
    .accessibilityLabel("Document Preview")
    .accessibilityValue("\(pages.count) pages total")

Dynamic Type support:

swift
@Environment(\.sizeCategory) var sizeCategory

var editorFont: Font {
    .system(
        size: UIFontMetrics.default.scaledValue(for: 14),
        design: .monospaced
    )
}

Reduce Motion adaptation:

swift
@Environment(\.accessibilityReduceMotion) var reduceMotion

.animation(reduceMotion ? nil : .easeInOut(duration: 0.2), value: isConverting)

Minimum touch target:

  • All interactive elements must be at least 44x44 pt
  • macOS may use slightly smaller targets (mouse precision), but iOS must comply

Prohibited Practices

Do not use deprecated APIs:

  • No NavigationView -- use NavigationStack / NavigationSplitView
  • No @ObservableObject -- use @Observable (SwiftUI 5)
  • No UIAlertController -- use SwiftUI .alert() modifier

Do not hard-code dimensions:

  • No .frame(width: 375, height: 812) (iPhone dimensions)
  • Use .frame(maxWidth: .infinity) or GeometryReader instead

Do not ignore accessibility:

  • No visual-only feedback (color changes only)
  • Use VoiceOver labels + Dynamic Type + Reduce Motion

Do not override system behavior:

  • No overriding Command-Q quit logic
  • Use standard system behavior

Do not perform time-consuming operations on the main thread:

  • No synchronous Typst compilation
  • Use Task { try await typstCompiler.compile() }

Do not use unsupported APIs across platforms:

  • No calling NSOpenPanel on iOS
  • Use #if os(macOS) conditional compilation

Reference Resources

Apple official documentation:

Presto internal documentation:

  • Presto/docs/native-app-refactoring.md -- Complete refactoring plan (97KB, detailed architecture design)
  • Presto-homepage/docs/ai-guide.md -- Organization-level AI development guide

Key design decisions:

  • Prefer PDFKit for PDF rendering over SVG (Apple has no public runtime SVG rendering API)
  • Document-Based App architecture (DocumentGroup), with automatic iCloud Drive support
  • Template binaries executed via Process (macOS); iOS uses Swift-native built-in templates
  • SwiftUI + SwiftData + CloudKit for iCloud three-device sync

2025-2026 trends:

  • Liquid Glass design language (WWDC25)
  • visionOS spatial computing guidelines (if Vision Pro support is needed)
  • Apple Intelligence AI integration guide

Last updated: 2026-03-01 Based on: Presto/docs/native-app-refactoring.md (as of March 2026)

Presto — Markdown to PDF