Back to prompts
CodingChatGPTClaudeGemini

macOS Document-Based App Builder

Create a native macOS document-based app with SwiftUI, supporting custom file formats, autosave, versioning, and iCloud Documents.

Prompt Template

You are a macOS app developer expert. Help me build a document-based macOS app using SwiftUI.

**App Purpose:** [e.g., "A markdown editor", "A pixel art editor", "A recipe organizer"]
**Document Content:** [what data each document contains]
**Custom File Format:** [describe your ideal file extension and format — e.g., ".recipe" files as JSON, or a package format]
**Features:**
- [e.g., "Multiple tabs/windows for different documents"]
- [e.g., "Export to PDF / HTML / other formats"]
- [e.g., "Undo/Redo support"]
- [e.g., "Quick Look preview support"]
**iCloud Documents:** [yes/no — should documents sync via iCloud Drive?]

Please provide:
1. **Document type definition** — UTType declaration, FileDocument or ReferenceFileDocument conformance
2. **File reading/writing** — serialization/deserialization with proper error handling
3. **Info.plist / UTType export** — declare your custom document type so Finder recognizes it
4. **DocumentGroup scene** — proper SwiftUI setup with toolbar, title, and file menu integration
5. **Undo/Redo** — UndoManager integration with the document
6. **Autosave** — ensure it works correctly with your document type
7. **Export functionality** — if needed, add export to standard formats
8. **Quick Look extension** — thumbnail and preview generator (optional but polished)
9. **Recent documents** — leveraging the system recent documents menu
10. **Complete compilable code** for the document struct and main view

Example Output

import SwiftUI

import UniformTypeIdentifiers

extension UTType {

static var recipe: UTType {

UTType(exportedAs: "com.example.recipe")

}

}

struct RecipeDocument: FileDocument {

static var readableContentTypes: [UTType] { [.recipe, .json] }

var recipe: Recipe

struct Recipe: Codable {

var title: String = "Untitled Recipe"

var ingredients: [Ingredient] = []

var steps: [String] = [""]

var servings: Int = 4

var prepTime: Int = 0

}

init() {

recipe = Recipe()

}

init(configuration: ReadConfiguration) throws {

guard let data = configuration.file.regularFileContents else {

throw CocoaError(.fileReadCorruptFile)

}

recipe = try JSONDecoder().decode(Recipe.self, from: data)

}

func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {

let encoder = JSONEncoder()

encoder.outputFormatting = [.prettyPrinted, .sortedKeys]

let data = try encoder.encode(recipe)

return FileWrapper(regularFileWithContents: data)

}

}

@main

struct RecipeApp: App {

var body: some Scene {

DocumentGroup(newDocument: RecipeDocument()) { file in

RecipeEditorView(document: file.$document)

}

.commands {

CommandGroup(after: .importExport) {

Button("Export as PDF...") { /* ... */ }

.keyboardShortcut("e", modifiers: [.command, .shift])

}

}

}

}

Info.plist UTType export:

<key>UTExportedTypeDeclarations</key>

<array>

<dict>

<key>UTTypeIdentifier</key>

<string>com.example.recipe</string>

<key>UTTypeDescription</key>

<string>Recipe Document</string>

<key>UTTypeConformsTo</key>

<array><string>public.json</string></array>

<key>UTTypeTagSpecification</key>

<dict>

<key>public.filename-extension</key>

<array><string>recipe</string></array>

</dict>

</dict>

</array>

Tips for Best Results

  • 💡Use FileDocument for simple value-type documents, ReferenceFileDocument for complex reference-type docs
  • 💡Test autosave thoroughly — make an edit, wait 30 seconds, force-quit, and reopen
  • 💡Add a Quick Look extension for a polished Finder experience with your custom files
  • 💡For package-based documents (folders disguised as files), use FileWrapper with directories