How Palmier Pro Handles Project File Persistence: Inside the .palmier Package System
Palmier Pro implements project file persistence using a document‑oriented architecture that packages project data, media assets, and session logs into an atomic .palmier directory, coordinated by the VideoProject NSDocument subclass and the ProjectRegistry.
Palmier Pro, an open‑source video editing application from the palmier‑io/palmier‑pro repository, implements robust project file persistence through a specialized package format and thread‑safe serialization. The system treats each editing session as a self‑contained document bundle, ensuring that timelines, media references, and generation logs remain consistent across saves and relocations.
The .palmier Package Structure
Palmier Pro stores every editing session as a project package—a file bundle that uses the .palmier extension defined in Project.fileExtension (Sources/PalmierPro/Utilities/Constants.swift). The package is a directory containing multiple assets that preserve the complete state of an editing session:
project.json– The serialized timeline data.media.json– An optional media manifest tracking imported assets.generation‑log.json– A log of generation operations.thumbnail.jpg– A preview image of the project.media/– A subdirectory containing copied or referenced media files..chat-session/– A hidden directory storing conversation history.
This structure ensures that project file persistence remains atomic; moving or sharing a single .palmier folder transports both metadata and assets.
Loading and Deserialization
When opening a project, the VideoProject class (an NSDocument subclass) orchestrates the loading sequence across background and main threads.
Background Reading
The entry point VideoProject.load(from:) initiates the process, or the document system invokes read(from:ofType:). These methods call readProjectPackage on a background task to parse the JSON timeline and optional manifest:
// Load a project from a URL (e.g., from the recent-project list)
let url = URL(fileURLWithPath: "/Users/me/Documents/Palmier Pro/MyMovie.palmier")
Task {
let project = try await VideoProject.load(from: url)
// The project is now an NSDocument ready to be displayed
AppState.shared.showEditor(for: project)
}
The raw data is stored in temporary properties: loadedTimeline, loadedManifest, and loadedGenerationLog.
Applying to the View Model
Once the window controller builds via makeWindowControllers, the loaded data transfers into the active view model:
editorViewModel.timelinereceives the decoded timeline.editorViewModel.mediaManifestreceives the manifest.- Media assets restore from the manifest and cache for immediate use.
This separation ensures that heavy I/O occurs off the main thread while UI updates remain responsive.
Saving and Atomic Writing
The save operation follows a snapshot‑then‑write pattern to guarantee data integrity.
Capturing State
When a user triggers a save, captureSaveSnapshot() serializes the current editorViewModel into a ProjectPackageSnapshot. The snapshot temporarily stores in non‑isolated variables (snapshotTimeline, snapshotManifest, etc.) to prevent blocking the UI:
// Save the current document (normally invoked by the UI)
if let doc = AppState.shared.activeProject {
doc.save(to: doc.fileURL!, ofType: VideoProject.typeIdentifier) { error in
if let err = error {
print("Save failed: \(err)")
} else {
print("Project saved.")
}
}
}
Writing the Package
The write(to:ofType:) method delegates to writeProjectPackage, which performs the atomic file operations:
- Creates the package directory structure.
- Writes
project.json,media.json, andgeneration‑log.json. - Perserves or regenerates
thumbnail.jpg. - Copies the entire
media/folder if the project location changed. - Writes the hidden chat‑session directory.
By executing these steps on a background thread, Palmier Pro maintains project file persistence without freezing the interface.
Project Registry and Storage Management
Palmier Pro tracks recent projects using the ProjectRegistry singleton (Sources/PalmierPro/Project/ProjectRegistry.swift), which maintains a JSON list located at ~/Documents/Palmier Pro/project-registry.json (defined in Project.storageDirectory).
Registry Operations
register(_:)– Adds a newly opened project to the registry.updateURL– Called automatically whenVideoProject.fileURLchanges (via the setter), handling project moves or renames.remove(_:)anddelete(_:)– Clean up entries when projects close or delete.
The storage directory creates itself on‑demand via Project.ensureStorageDirectory, ensuring the registry always has a valid filesystem location:
// Register a newly-created project (handled automatically when the document is opened)
ProjectRegistry.shared.register(URL(fileURLWithPath: "/Users/me/Documents/Palmier Pro/NewProject.palmier"))
Thread Safety and Document Lifecycle
The project file persistence mechanism strictly separates concerns across threads:
- Read –
readProjectPackagedecodes JSON on a background thread. - Apply –
makeWindowControllersinjects the model into the view model on the main thread. - Write –
writeProjectPackagesnapshots and writes atomically on a background thread.
This architecture aligns with Apple's NSDocument recommendations while providing the performance necessary for video editing workloads.
Summary
- Palmier Pro uses a
.palmierpackage format (defined inConstants.swift) containing JSON timelines, media manifests, generation logs, and asset subdirectories. - The
VideoProjectclass (inVideoProject.swift) handles loading viaload(from:)and saving viacaptureSaveSnapshot()→writeProjectPackage(). - Media assets persist inside the
media/subdirectory, copied entirely when projects relocate. - The
ProjectRegistry(inProjectRegistry.swift) maintains recent project references in~/Documents/Palmier Pro/project-registry.json. - All file I/O operates on background threads, with view‑model updates restricted to the main thread.
Frequently Asked Questions
What file extension does Palmier Pro use for project files?
Palmier Pro uses the .palmier extension for its project packages. This is defined as a constant in Sources/PalmierPro/Utilities/Constants.swift (Project.fileExtension), and each package is technically a directory bundling JSON metadata and media assets.
How does Palmier Pro handle media assets during save operations?
During the writeProjectPackage phase, the system checks whether the project location has changed. If so, it copies the entire media/ subdirectory from the previous package to the new destination, ensuring that relative paths in media.json remain valid and that project file persistence remains self‑contained.
Where does Palmier Pro store the list of recent projects?
The application stores the recent project list in ~/Documents/Palmier Pro/project-registry.json, accessed through Project.storageDirectory. The ProjectRegistry singleton manages this JSON file, updating it automatically when projects open, move, or delete.
Is the project loading process thread‑safe?
Yes. The loading sequence executes readProjectPackage on a background thread to decode project.json and media.json, then transitions to the main thread only when makeWindowControllers applies the loaded data to editorViewModel. This prevents UI blocking while maintaining thread safety for Cocoa bindings.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →