# Best Practices for Developing with Palmier Pro: Swift 6.2 & AI-Native Video Editing

> Master Palmier Pro development with Swift 6.2 and AI-native video editing. Discover best practices for UI, AI extensions, and thread-safe utilities. Elevate your project today.

- Repository: [Palmier/palmier-pro](https://github.com/palmier-io/palmier-pro)
- Tags: best-practices
- Published: 2026-06-23

---

**The essential rules for Palmier Pro development are: never hard-code UI constants—always use [`AppTheme.swift`](https://github.com/palmier-io/palmier-pro/blob/main/AppTheme.swift); prefer SwiftUI but implement parent drag-and-drop containers with AppKit to avoid shadowing bugs; extend AI capabilities via `ToolExecutor` extensions registered in [`ToolDefinitions.swift`](https://github.com/palmier-io/palmier-pro/blob/main/ToolDefinitions.swift); and reuse thread-safe utilities from `Utilities/` rather than writing ad-hoc solutions.**

Palmier Pro is an AI-native macOS video editor built with **Swift 6.2**, **SwiftUI**, **AppKit**, and **AVFoundation**. The `palmier-io/palmier-pro` repository follows a strict design-system approach that separates UI from media processing and supports a pluggable agent architecture. Following these conventions keeps the codebase consistent, testable, and ready for future AI-driven enhancements.

## Architectural Foundations for Palmier Pro Development

### Centralize UI Constants in AppTheme

All visual constants—including colors, spacing, fonts, radii, and shadows—live in [`Sources/PalmierPro/UI/AppTheme.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/UI/AppTheme.swift). Hard-coding numbers violates the design system and creates maintenance debt.

Always reference constants through `AppTheme` enums:

```swift
import SwiftUI

struct ExampleHeader: View {
    var body: some View {
        HStack {
            Text("Welcome to Palmier Pro")
                .font(.system(size: AppTheme.FontSize.title1,
                              weight: AppTheme.FontWeight.bold))
                .foregroundColor(AppTheme.Text.primaryColor)
            Spacer()
        }
        .padding(AppTheme.Spacing.lg)
        .background(AppTheme.Background.surfaceColor)
        .shadow(AppTheme.Shadow.md)
    }
}

```

This approach ensures that `padding(AppTheme.Spacing.md)` and `font(.system(size: AppTheme.FontSize.lg))` remain consistent across the macOS interface.

### SwiftUI and AppKit Integration Patterns

While **SwiftUI** is preferred for most interfaces, drag-and-drop areas containing nested drop targets must use native **AppKit**. The "parent-onDrop shadows children" bug requires implementing leaf drop zones with `.onDrop` while parent containers use the AppKit `NSView` subclass `MediaPanelDropArea` found in [`Sources/PalmierPro/MediaPanel/MediaTab/MediaPanelDropArea.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/MediaPanel/MediaTab/MediaPanelDropArea.swift).

When you need a parent drop area, subclass `NSView` instead of using SwiftUI modifiers:

```swift
import AppKit

final class CustomDropArea: NSView {
    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        registerForDraggedTypes([.fileURL])
    }

    required init?(coder: NSCoder) { fatalError() }

    override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
        guard let url = sender.draggedFileURLs?.first else { return false }
        // Forward to the SwiftUI side via NotificationCenter or Combine
        NotificationCenter.default.post(name: .customDrop, object: url)
        return true
    }
}

```

Use this pattern when the area contains other drop targets, as nested SwiftUI `.onDrop` modifiers interfere with child interactions.

### Timeline Architecture and State Management

Core timeline logic resides in `Sources/PalmierPro/Timeline/`, including [`TimelineView.swift`](https://github.com/palmier-io/palmier-pro/blob/main/TimelineView.swift), geometry calculations, ruler rendering, the `SnapEngine`, and `ClipRenderer`. Keep timeline state immutable where possible and delegate heavy computational work to `SnapEngine` and `ClipRenderer` rather than handling logic directly in views.

This separation allows the timeline to handle complex video editing operations while maintaining responsive UI updates through SwiftUI's state management.

### Extending the AI Agent with ToolExecutor

The in-app AI agent is built from modular `ToolExecutor` extensions. To add new capabilities—such as audio-sync or caption generation—extend `ToolExecutor` in a separate file under `Sources/PalmierPro/Agent/Tools/` (following the pattern of `ToolExecutor+AudioSync.swift`), then register the tool in [`Sources/PalmierPro/Agent/ToolDefinitions.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Agent/ToolDefinitions.swift).

Create the executor extension:

```swift
extension ToolExecutor {
    func executeMyNewTool(_ request: MyToolRequest) async throws -> MyToolResponse {
        Log.info("Running MyNewTool with payload: \(request.payload)")
        let result = try await performNetworkCall(request)
        return MyToolResponse(result: result)
    }
}

```

Then register in [`ToolDefinitions.swift`](https://github.com/palmier-io/palmier-pro/blob/main/ToolDefinitions.swift):

```swift
static let myNewTool = ToolDefinition(
    name: "my_new_tool",
    description: "Does something useful",
    executor: { executor, request in
        try await executor.executeMyNewTool(request as! MyToolRequest)
    })

```

This modular architecture keeps agent capabilities organized and discoverable by the AI system.

### Reuse Thread-Safe Utilities

Helpers such as `DiskCache`, `ImageEncoder`, and `Log` reside under `Sources/PalmierPro/Utilities/`. These utilities already respect the app's thread-safety and caching policies. Reuse them instead of writing ad-hoc code to ensure consistency across the codebase when handling media encoding, persistent caching, or structured logging.

### Testing Requirements

The test suite lives under `Tests/PalmierProTests/` and covers media import, timeline round-tripping, and AI-generated assets. Write unit tests for new modules and run `swift test` locally before committing changes to ensure regression coverage for the video editing pipeline.

## Code Examples for Palmier Pro Development

### Adding a New AI Tool Capability

When developing new AI features for Palmier Pro, following the `ToolExecutor` pattern ensures compatibility with the agent system:

```swift
import Foundation

struct MyToolRequest: Codable {
    let payload: String
}

struct MyToolResponse: Codable {
    let result: String
}

extension ToolExecutor {
    func executeMyNewTool(_ request: MyToolRequest) async throws -> MyToolResponse {
        // Reuse existing logging and error handling utilities
        Log.info("Running MyNewTool with payload: \(request.payload)")
        // Core logic – maybe call a local ML model or MCP endpoint
        let result = try await performNetworkCall(request)
        return MyToolResponse(result: result)
    }
}

```

Remember to keep comments minimal and explain *why* something is done, not *what*, as specified in [`AGENTS.md`](https://github.com/palmier-io/palmier-pro/blob/main/AGENTS.md).

## Key Source Files and Organization

Understanding the repository structure is critical for effective Palmier Pro development:

- **[`Sources/PalmierPro/UI/AppTheme.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/UI/AppTheme.swift)** — Centralized design-system constants (colors, spacing, fonts, shadows)
- **`Sources/PalmierPro/Timeline/`** — Timeline view, geometry, snap engine, and clip rendering via [`TimelineView.swift`](https://github.com/palmier-io/palmier-pro/blob/main/TimelineView.swift)
- **`Sources/PalmierPro/MediaPanel/`** — Media-panel UI, import handling, drag-and-drop, and thumbnail generation
- **`Sources/PalmierPro/Agent/Tools/ToolExecutor+*.swift`** — Modular AI-agent tool implementations (audio sync, captions, etc.)
- **`Sources/PalmierPro/Utilities/`** — Shared helpers for caching (`DiskCache`), logging (`Log`), keychain access, and image encoding (`ImageEncoder`)
- **`Tests/PalmierProTests/`** — Unit and integration tests for media import, timeline round-trip, and AI features
- **[`AGENTS.md`](https://github.com/palmier-io/palmier-pro/blob/main/AGENTS.md)** — Coding-style guidelines and architectural notes

Follow the file-structure conventions: UI components go to `UI/`, media handling to `MediaPanel/`, timeline logic to `Timeline/`, and agent extensions to `Agent/`. Use descriptive enum cases and extensions (e.g., `ClipType.themeColor`) to maintain readability.

## Summary

- **Always pull UI constants from `AppTheme`** and never hard-code visual values; use [`AppTheme.Spacing.md`](https://github.com/palmier-io/palmier-pro/blob/main/AppTheme.Spacing.md), `AppTheme.FontSize.lg`, and [`AppTheme.Shadow.md`](https://github.com/palmier-io/palmier-pro/blob/main/AppTheme.Shadow.md) throughout SwiftUI views
- **Prefer SwiftUI for interfaces**, but use AppKit `NSView` implementations (like `MediaPanelDropArea`) for parent drag-and-drop containers to avoid the "parent-onDrop shadows children" bug
- **Keep timeline state immutable** and delegate heavy work to `SnapEngine` and `ClipRenderer` rather than processing directly in [`TimelineView.swift`](https://github.com/palmier-io/palmier-pro/blob/main/TimelineView.swift)
- **Extend AI capabilities via `ToolExecutor` extensions** in `Sources/PalmierPro/Agent/Tools/` and register them in [`ToolDefinitions.swift`](https://github.com/palmier-io/palmier-pro/blob/main/ToolDefinitions.swift)
- **Reuse utilities from `Utilities/`** for caching, logging, and image encoding to maintain thread safety and caching policies
- **Write unit tests** for every new component and run `swift test` before merging to ensure media processing and timeline features remain stable

## Frequently Asked Questions

### How do I add a new color or spacing value to Palmier Pro?

Add new design constants to [`Sources/PalmierPro/UI/AppTheme.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/UI/AppTheme.swift) following the existing enum structure for colors, spacing, fonts, and shadows. Reference these constants throughout the UI using [`AppTheme.Spacing.md`](https://github.com/palmier-io/palmier-pro/blob/main/AppTheme.Spacing.md) or `AppTheme.Text.primaryColor` rather than hard-coding values. This ensures consistency with the macOS design system and simplifies future theme updates across the video editor interface.

### When should I use AppKit instead of SwiftUI in Palmier Pro?

Use AppKit's `NSView` for parent drag-and-drop containers that contain nested drop targets. SwiftUI's `.onDrop` modifier shadows child drop zones, causing interaction bugs where children cannot receive drop events. Implement leaf drop zones with SwiftUI `.onDrop`, but parent containers should use `MediaPanelDropArea` or similar `NSView` subclasses defined in [`Sources/PalmierPro/MediaPanel/MediaTab/MediaPanelDropArea.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/MediaPanel/MediaTab/MediaPanelDropArea.swift) to maintain proper event propagation.

### What is the correct way to implement a new AI agent tool?

Create a new file in `Sources/PalmierPro/Agent/Tools/` extending `ToolExecutor` with your async execution method (following the `ToolExecutor+AudioSync.swift` pattern). Then register the tool in [`Sources/PalmierPro/Agent/ToolDefinitions.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Agent/ToolDefinitions.swift) by adding a `ToolDefinition` entry that maps the tool name to your executor extension. This modular approach keeps agent capabilities organized and discoverable by the AI system while maintaining clean separation of concerns.

### Where should I place utility functions in the Palmier Pro codebase?

Place reusable helpers in `Sources/PalmierPro/Utilities/` alongside existing utilities like `DiskCache`, `ImageEncoder`, and `Log`. These utilities are engineered for thread safety and respect the app's caching policies. Avoid creating ad-hoc utility files in feature directories; instead, extend existing utilities or add new ones to the central `Utilities/` folder to ensure consistent behavior across the media processing pipeline.