# Understanding the Database Schema for Palmier Pro: JSON-Based Persistence Architecture

> Explore the Palmier Pro database schema. Discover how this project leverages JSON-based persistence with Codable, outlining its flat structure of Timeline, Track, and Clip structs.

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

---

**Palmier Pro does not use a traditional relational database; instead, it persists all project data as JSON files encoded with Swift’s `Codable` protocol, using a flat schema of structs including `Timeline`, `Track`, and `Clip`.**

The open-source video editing application Palmier Pro (`palmier-io/palmier-pro`) stores project state through a file-based persistence layer rather than connecting to an external SQL database. Understanding the database schema for Palmier Pro requires examining its Swift struct definitions in the source code, which directly dictate the JSON structure saved to disk.

## Project Registry Structure

The application maintains a global project registry separate from individual project files. This registry tracks recently opened projects and their metadata.

### ProjectEntry and Registry Storage

In [`Sources/PalmierPro/Project/ProjectRegistry.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Project/ProjectRegistry.swift), the `ProjectEntry` struct defines the schema for registry items with the following JSON fields:

- `id`: UUID
- `url`: URL (file location)
- `createdDate`: Date
- `lastOpenedDate`: Date

The `ProjectRegistry` class holds an array of these entries and persists them to a JSON file specified by `Project.registryFilename`. When the application launches, it decodes this array to populate the recent projects list.

```swift
// Accessing the shared registry
ProjectRegistry.shared.register(url: newProjectURL)

// The registry file stores: [ProjectEntry]
// Fields: id, url, createdDate, lastOpenedDate

```

## Timeline and Track Schema

The core project file (`.palmier` extension) contains a single `Timeline` object that represents the entire editing sequence.

### Timeline Global Settings

Defined in [`Sources/PalmierPro/Models/Timeline.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Models/Timeline.swift), the `Timeline` struct contains project-wide configuration and an array of tracks:

```swift
// Key JSON fields in Timeline
{
  "fps": 30,
  "width": 1920,
  "height": 1080,
  "settingsConfigured": true,
  "tracks": [...]
}

```

### Track Properties

Each `Track` represents a layer on the timeline (video, audio, image, or text) and includes:

- `id`: String (unique identifier)
- `type`: ClipType enum (video, audio, image, text)
- `muted`: Bool
- `hidden`: Bool
- `syncLocked`: Bool
- `clips`: Array of `Clip` objects

## Clip Data Model and Transformations

The `Clip` struct stores the majority of editing data, including media references, trimming, effects, and animation keyframes.

### Core Clip Fields

In [`Sources/PalmierPro/Models/Timeline.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Models/Timeline.swift), each clip persists:

- `mediaRef`: String (reference to source media)
- `mediaType` and `sourceClipType`: ClipType enum values
- `startFrame`: Int (timeline position)
- `durationFrames`: Int
- `trimStartFrame` and `trimEndFrame`: Int
- `speed`: Double (playback rate)
- `volume`: Double
- `fadeInFrames` and `fadeOutFrames`: Int
- `fadeInInterpolation` and `fadeOutInterpolation`: Interpolation type
- `opacity`: Double
- `linkGroupId`: Optional String
- `captionGroupId`: Optional String
- `textContent`: Optional String
- `textStyle`: Optional TextStyle

### Geometric Transforms

The `Transform` struct handles spatial properties:

- `centerX` and `centerY`: Double
- `width` and `height`: Double
- `rotation`: Double
- `flipHorizontal`: Bool
- `flipVertical`: Bool

### Cropping Data

The `Crop` struct stores normalized inset values:

- `left`: Double
- `top`: Double
- `right`: Double
- `bottom`: Double

## Animation and Keyframe Storage

Palmier Pro supports animation through generic keyframe tracks stored per clip.

### KeyframeTrack Implementation

In [`Sources/PalmierPro/Models/Keyframe.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Models/Keyframe.swift), the `KeyframeTrack<V>` generic struct stores animatable properties:

- `opacityTrack`: KeyframeTrack<Double>
- `positionTrack`: KeyframeTrack<AnimPair>
- `scaleTrack`: KeyframeTrack<AnimPair>
- `rotationTrack`: KeyframeTrack<Double>
- `cropTrack`: KeyframeTrack<Crop>
- `volumeTrack`: KeyframeTrack<Double>

Each track contains an array of keyframe objects with timing and value data.

### Media Manifest

Optional media tracking occurs in [`Sources/PalmierPro/Models/MediaManifest.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Models/MediaManifest.swift). The `MediaManifest` maintains an `entries` array of `MediaManifestEntry` objects containing `id`, `url`, `type`, and `duration` fields, enabling the project to locate source files even if moved.

## JSON Encoding and Decoding

All schema structs conform to `Codable`, enabling standard Swift JSON serialization. The persistence layer uses atomic writes to prevent data corruption.

### Loading a Project

```swift
import Foundation

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 Project

```swift
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)
}

```

### Enumerating Timeline Contents

```swift
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 is deliberately flat and version-friendly. Because the system uses JSON rather than rigid SQL tables, adding new properties to structs automatically introduces new keys in the serialized output.

Backwards compatibility is maintained through custom `init(from:)` implementations in `Track` and `Clip` that provide default values for missing fields. This allows older project files to load correctly even when opened in newer versions of the application that expect additional properties.

## Summary

- **Palmier Pro uses JSON files, not SQL**: All data persists as encoded Swift structs using the `Codable` protocol.
- **Two-tier storage**: The `ProjectRegistry` tracks recent projects separately from individual `.palmier` timeline files.
- **Core models defined in Timeline.swift**: The schema centers on `Timeline`, `Track`, and `Clip` structs with nested `Transform` and `Crop` objects.
- **Animation support**: Generic `KeyframeTrack<V>` structures in [`Keyframe.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Keyframe.swift) handle animated properties.
- **Atomic writes**: Projects save using `JSONEncoder` with `.atomic` write options to prevent corruption.
- **Schema evolution**: New properties automatically extend the JSON format while custom decoders maintain backwards compatibility.

## Frequently Asked Questions

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

No. According to the `palmier-io/palmier-pro` source code, the application does not use SQLite, Core Data, or any relational database. Instead, it relies entirely on JSON file persistence using Swift's `Codable` protocol, with project data stored as structured text files on disk.

### How are project files organized on the filesystem?

Project files use the `.palmier` extension and contain a single JSON-encoded `Timeline` object. A separate registry file (location determined by `Project.registryFilename` in [`ProjectRegistry.swift`](https://github.com/palmier-io/palmier-pro/blob/main/ProjectRegistry.swift)) stores the list of recent projects as a JSON array of `ProjectEntry` objects in the user's application support folder.

### What happens if the schema changes in a future update?

The schema handles evolution through Swift's default value support and custom `init(from:)` implementations. When new fields are added to structs like `Clip` or `Track`, the JSON decoder provides default values for missing keys, ensuring older project files remain compatible with newer application versions.

### How does Palmier Pro handle missing media files?

The optional `MediaManifest` struct (defined in [`MediaManifest.swift`](https://github.com/palmier-io/palmier-pro/blob/main/MediaManifest.swift)) maintains a catalog of imported assets with their IDs and URLs. While clips store `mediaRef` strings pointing to these entries, the application can use the manifest to attempt to relink media if files are moved, though the primary schema relies on persistent URL references stored in each `Clip` instance.