Database Schema for Palmier Pro: JSON-Based Persistence Model Explained

Palmier Pro uses a JSON-based persistence layer instead of a traditional relational database, storing project data as Swift structs conforming to Codable in files with .palmier extensions.

The database schema for Palmier Pro is implemented entirely through Swift's Codable protocol rather than external database engines. In the palmier-io/palmier-pro repository, all persistent data—from project registries to timeline compositions—lives as structured JSON files on disk. This architecture provides a flat, version-friendly storage system that requires no SQL migrations or complex schema management.

Project Registry Schema

The project registry maintains a list of recently opened projects outside of the individual .palmier files.

ProjectEntry

In Sources/PalmierPro/Project/ProjectRegistry.swift, the ProjectEntry struct represents a single entry in the recent-projects list with the following JSON fields:

  • id: UUID
  • url: URL
  • createdDate: Date
  • lastOpenedDate: Date

ProjectRegistry

The same file defines ProjectRegistry, which encapsulates an array of ProjectEntry objects. The registry reads from and writes to a file specified by Project.registryFilename, storing the entire collection as a single JSON array.

Timeline and Composition Schema

The core data model resides in Sources/PalmierPro/Models/Timeline.swift, defining the structure of individual project files.

Timeline

The root object of every .palmier file contains global project settings and track data:

  • fps: Int
  • width: Int
  • height: Int
  • settingsConfigured: Bool
  • tracks: [Track]

Track

Each track represents a layer on the timeline with these properties:

  • id: String
  • type: ClipType
  • muted: Bool
  • hidden: Bool
  • syncLocked: Bool
  • clips: [Clip]

Clip

The Clip struct stores media references, trimming data, and animation tracks:

  • id: String
  • mediaRef: String
  • mediaType: ClipType
  • sourceClipType: ClipType
  • startFrame: Int
  • durationFrames: Int
  • trimStartFrame: Int
  • trimEndFrame: Int
  • speed: Double
  • volume: Double
  • fadeInFrames: Int
  • fadeOutFrames: Int
  • fadeInInterpolation: Interpolation
  • fadeOutInterpolation: Interpolation
  • opacity: Double
  • transform: Transform
  • crop: Crop
  • linkGroupId: String?
  • captionGroupId: String?
  • textContent: String?
  • textStyle: TextStyle?
  • opacityTrack: KeyframeTrack?
  • positionTrack: KeyframeTrack?
  • scaleTrack: KeyframeTrack?
  • rotationTrack: KeyframeTrack?
  • cropTrack: KeyframeTrack?
  • volumeTrack: KeyframeTrack?

Transform and Crop

Geometric transformations are defined as separate structs:

Transform contains:

  • centerX: Double
  • centerY: Double
  • width: Double
  • height: Double
  • rotation: Double
  • flipHorizontal: Bool
  • flipVertical: Bool

Crop defines normalized inset values:

  • left: Double
  • top: Double
  • right: Double
  • bottom: Double

ClipType Enumeration

The ClipType enum in Timeline.swift defines supported media types including video, audio, image, and text.

Keyframe Animation System

In Sources/PalmierPro/Models/Keyframe.swift, the generic KeyframeTrack<V> struct stores animation data for clip properties. Each track contains a keyframes array of Keyframe<Value> objects, supporting animated opacity, position, scale, rotation, crop, and volume values over time.

Media Asset Management

The optional MediaManifest struct in Sources/PalmierPro/Models/MediaManifest.swift tracks imported assets. It contains an entries array of MediaManifestEntry objects, each storing id, url, type, and duration to locate source files referenced by the timeline.

Reading and Writing the Schema

All structs conform to Codable, enabling standard JSON encoding and decoding. The database schema is deliberately flat—no nested SQL tables—making persistence straightforward.

Loading a Timeline

import Foundation
import PalmierPro

func loadTimeline(from url: URL) throws -> Timeline {
    let data = try Data(contentsOf: url)
    let decoder = JSONDecoder()
    return try decoder.decode(Timeline.self, from: data)
}

Saving a Timeline

func saveTimeline(_ timeline: Timeline, to url: URL) throws {
    let encoder = JSONEncoder()
    encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
    let data = try encoder.encode(timeline)
    try data.write(to: url, options: .atomic)
}

Registering Projects

func registerProject(at url: URL) {
    ProjectRegistry.shared.register(url)
}

Enumerating Timeline Contents

for track in timeline.tracks {
    for clip in track.clips {
        print("Clip \(clip.id) of type \(clip.mediaType) starts at \(clip.startFrame)")
    }
}

Schema Evolution and Backwards Compatibility

The database schema for Palmier Pro handles versioning through custom init(from:) implementations in Track and Clip. Adding new properties to any struct automatically introduces new keys in the JSON output, while default values ensure older project files remain readable. This approach eliminates the need for migration scripts or version stamps.

Summary

  • Palmier Pro uses JSON files rather than SQL databases, with Swift structs conforming to Codable defining the schema.
  • ProjectRegistry.swift manages the recent-projects list as an array of ProjectEntry objects.
  • Timeline.swift contains the core composition data: Timeline, Track, Clip, Transform, and Crop.
  • Keyframe.swift provides generic animation tracks via KeyframeTrack<V>.
  • MediaManifest.swift optionally tracks imported media assets and their metadata.
  • The schema is flat, human-readable, and supports backwards compatibility through default values in custom decoders.

Frequently Asked Questions

Does Palmier Pro use SQLite or Core Data for its database schema?

No. According to the palmier-io/palmier-pro source code, Palmier Pro does not use SQLite, Core Data, or any traditional relational database engine. Instead, it persists all data as JSON files encoded through Swift's Codable protocol, storing project files with the .palmier extension and registry data in the application's support folder.

How are media assets referenced in the database schema?

Media assets are referenced through the mediaRef string field in the Clip struct, which points to entries in an optional MediaManifest. The manifest, defined in MediaManifest.swift, maps these references to actual file URLs and metadata such as duration and type, enabling the project to locate source files without embedding binary data in the JSON schema.

What happens when the database schema changes in a new version of Palmier Pro?

The schema handles evolution through custom init(from:) implementations in Track and Clip structs. When new properties are added, the JSON encoder automatically includes them in output files, while the decoder provides default values for missing keys when reading older files. This ensures backwards compatibility without requiring explicit migration code or version checks.

Where is the project registry stored on disk?

The project registry is stored separately from individual project files in the user's application support folder. Defined in ProjectRegistry.swift, the registry uses the filename specified by Project.registryFilename and contains a JSON array of ProjectEntry objects tracking paths, creation dates, and last-opened dates for recent projects.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →