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