Save and serialize designs in CE.SDK for later retrieval, sharing, or storage using string or archive formats.
CE.SDK provides two formats for persisting designs. Choose the format based on your storage and portability requirements.
Save Format Comparison#
| Format | Method | Assets | Best For |
|---|---|---|---|
| String | saveToString() |
Referenced by URL | Database storage, cloud sync |
| Archive | saveToArchive() |
Embedded in ZIP | Offline use, file sharing |
String format produces a lightweight serialized string where assets remain as URL references. Use this when asset URLs will remain accessible.
Archive format creates a self-contained ZIP with all assets embedded. Use this for portable designs that work offline.
Persist saved files of either format with the .imgly extension. The .scene and .zip extensions also load, and the same engine.scene.load(from:) call opens either kind.
Archive Preview Image#
Scene and block archives containing a page automatically include a root preview.png as the first ZIP entry. The PNG is stored without ZIP compression. Its local ZIP header records its byte length. Clients can read the preview without fetching the document, resources, or central directory. It shows the first exported page at its playback position when saving starts (0 for static scenes). Video pages use the exact frame at that captured time. Scene archives use scene page order. Block archives use export-root order, then depth-first hierarchy order.
The PNG preserves the page background and transparency. Preview generation starts after every archive resource has loaded, and uses fast lossless PNG compression. Both dimensions are capped at 512 px. Pages that fit within 512 × 512 px keep their dimensions without upscaling. Larger pages are scaled down proportionally: a 1920 × 1080 page produces 512 × 288 px, while a 320 × 180 page stays 320 × 180 px. Larger outputs may be resampled from the thumbnail pipeline’s internal render resolution.
Rendering or encoding failures and unsupported dimensions cause the engine to omit the preview. Archives without a page also omit it. The engine ignores the exact root preview.png when loading and regenerates it on each archive save.
External tools can extract this image from the ZIP without loading the design. File explorers require a compatible preview handler to display it automatically.
Save to String#
Serialize the current scene to a string suitable for database storage.
let sceneString = try await engine.scene.saveToString()The string contains the complete scene structure but references assets by their original URLs.
The default allowedResourceSchemes do not include data, so a scene that holds a data: URI fails to save with SCENE.DISALLOWED_SCHEMES. Add "data" to keep those URIs in the string:
// The default schemes have no "data", so a data: URI fails the save.// Add "data" to keep data: URIs in the string.let sceneWithDataURIs = try await engine.scene.saveToString( allowedResourceSchemes: ["blob", "bundle", "data", "file", "http", "https"],)An archive needs no option: it bundles every resource, data: URIs included.
Save to Archive#
Create a self-contained ZIP with the scene and all embedded assets.
let archiveBlob = try await engine.scene.saveToArchive()saveToArchive() returns a Blob (a Data value) that includes all pages, elements, and asset data in a single portable file.
Compare Saved Scenes#
Saving writes the scene as it is laid out at that moment. While a font loads, its text is laid out with another font. When the size of a text follows its content, a scene saved before the font arrives can differ from the same scene saved after it.
To compare two saved scenes, for example by a hash, load the fonts first with try await engine.block.forceLoadResources([engine.scene.get()!]). The call throws when a resource fails to load, and you can still save the scene then. To compare two archives, compare the scene.scene files inside them, because each archive entry stores the time of the save.
Compression Options#
Saved scenes are compressed with Zstd by default, which makes them much smaller and speeds up both saving and loading. Pass a format explicitly to change the level, or to turn compression off.
let compressed = try await engine.scene.saveToString( options: SaveToStringOptions( compression: CompressionOptions(format: .zstd, level: .default), ),)Compression Formats:
CompressionFormat.zstd— Zstd compression (default)CompressionFormat.none— No compression
Compression Levels:
CompressionLevel.fastest— Fastest compression, larger outputCompressionLevel.default— Balanced speed and size (recommended)CompressionLevel.best— Best compression, slower
An archive can compress its scene the same way. Bundled images, video and fonts are stored as they are, because they already are compressed formats.
let compressedArchive = try await engine.scene.saveToArchive( options: SaveToArchiveOptions( compression: CompressionOptions(format: .zstd, level: .default), ),)Compression adds minimal overhead while reducing scene size. The default level provides the best balance of speed and compression ratio.
Write to Disk#
Use Foundation’s file APIs to persist saved designs to the file system.
Scene strings can be written directly as text:
let sceneURL = outputDir.appendingPathComponent("scene.imgly")try sceneString.write(to: sceneURL, atomically: true, encoding: .utf8)Archives are returned as Data, which writes to disk in a single call:
let archiveURL = outputDir.appendingPathComponent("archive.imgly")try archiveBlob.write(to: archiveURL)Load Scene from File#
Read a previously saved .scene file from disk and restore it to the engine with engine.scene.load(from:).
let restoredString = try String(contentsOf: sceneURL, encoding: .utf8)try await engine.scene.load(from: restoredString)Scene files are lightweight but require the original asset URLs to remain accessible.
Load Archive from File#
Use engine.scene.load(from:) with a local file URL to restore a self-contained archive that includes all embedded assets — the same call that loads scene files, since the engine detects the file kind automatically.
try await engine.scene.load(from: archiveURL)Archives are portable and work offline since all assets are bundled within the file.
API Reference#
| Method | Description |
|---|---|
engine.scene.saveToString() |
Serialize scene to string with optional compression |
engine.scene.saveToArchive() |
Save scene with assets as ZIP Data |
engine.scene.load(from:) |
Load a scene or archive from a string or URL (file kind detected automatically) |
engine.scene.loadArchive(from:) |
Load a scene archive from a URL |
engine.block.saveToString() |
Serialize specific blocks to a string |
engine.block.saveToArchive(blocks:) |
Save specific blocks with assets as ZIP Data |
engine.block.load(from:) |
Load blocks from a serialized string or URL |
engine.block.loadArchive(from:) |
Load blocks from a ZIP archive URL |
Next Steps#
- Export Overview — Export designs to image, PDF, and video formats
- Load Scene — Load scenes from remote URLs and archives
- Store Custom Metadata — Attach metadata like tags or version info to designs
- Partial Export — Export individual blocks or selections