Build print-ready t-shirt designs with a focused mobile UI. Runs entirely on the mobile device with no server dependencies.

Pre-Requisites#
This guide assumes basic familiarity with iOS and Swift. You will need:
- Latest Xcode
- Swift 5.9 or later
- iOS 16.0+
Get Started#
Start with a complete, runnable iOS starter kit project.
Step 1: Clone the Repository#
git clone -b v1.73.0 https://github.com/imgly/starterkit-apparel-editor-ios.gitcd starterkit-apparel-editor-iosStep 2: Open and Run#
Open the project in Xcode and run on a simulator or connected device:
- Open
starterkit-apparel-editor-ios.xcodeprojin Xcode - Select your target device or simulator
- Press ⌘R to build and run
The sample app shows a “Launch Editor” button. Tapping it presents the apparel editor:
var body: some View { Editor(settings) .imgly.configuration { ApparelEditorConfiguration() }}Get Started#
Integrate the starter kit files into your existing iOS app.
Step 1: Add the IMG.LY Swift Package#
Add the CE.SDK dependency via Swift Package Manager:
- In Xcode, go to File → Add Package Dependencies…
- Enter the repository URL:
https://github.com/imgly/IMGLYUI-swift
- Select version
1.73.0and add theIMGLYApparelEditorproduct to your target
Step 2: Copy the Starter Kit Files#
Download and extract the starter kit files into your project:
repo="starterkit-apparel-editor-ios"version="1.73.0"curl -L "https://codeload.github.com/imgly/${repo}/tar.gz/refs/heads/v${version}" | tar -xz --strip-components=1 "${repo}-v${version}/starter-kit"Step 3: Add Files to Your Xcode Project#
Drag the starter-kit/ folder into your Xcode project. Make sure “Copy items if needed” is checked and the files are added to your app target.
Step 4: Launch the Editor From Your UI#
Present the editor from any SwiftUI view:
Editor(settings) .imgly.configuration { ApparelEditorConfiguration() }The full implementation of the starter kit lives in the starter-kit/ folder:
starter-kit/├── ApparelEditorStarterKit.swift # SwiftUI view that launches the editor├── ApparelEditorConfiguration.swift # Editor configuration (callbacks + UI components)├── callbacks/│ ├── OnCreate+Apparel.swift # Editor initialization logic (outline setup)│ ├── OnExport+Apparel.swift # Export flow and handling (PDF)│ └── OnChanged+Apparel.swift # Gesture, page, and view mode handling└── components/ ├── CanvasMenu+Apparel.swift # Canvas menu configuration ├── Dock+Apparel.swift # Dock configuration ├── InspectorBar+Apparel.swift # Inspector bar configuration └── NavigationBar+Apparel.swift # Navigation bar configurationConfiguring the Starter Kit#
The starter kit provides a generic structure and behavior that you can customize to match your needs. Since the implementation is part of your codebase, you can add, remove, or modify functionality as you wish.
The entry point is ApparelEditorStarterKit.swift, which creates the Editor view and applies the configuration:
Editor(settings) .imgly.configuration { ApparelEditorConfiguration() }You can configure the editor based on your business logic — for example, loading a scene from a previous editing session or displaying different UI for different users. Add properties to ApparelEditorStarterKit and use them in the .imgly.onCreate callback to customize scene loading or other behavior.
Set Up a Scene#
The scene setup logic is located in OnCreate+Apparel.swift as part of the defaultCreateScene callback:
let sceneURL = Bundle(for: ApparelEditorConfiguration.self).url( forResource: "apparel-ui-b-empty", withExtension: "scene",)!try await engine.scene.load(from: sceneURL)CE.SDK offers multiple ways to load a scene into the editor — from a template archive, a blank canvas, or a .scene file.
Customize Assets#
The asset source setup is located in OnCreate+Apparel.swift as part of the defaultLoadAssetSources callback. Enable or disable individual sources:
let assetSources: [String: URL] = [ Engine.DefaultAssetSource.sticker.rawValue: Engine.assetBaseURL, Engine.DefaultAssetSource.vectorPath.rawValue: Engine.assetBaseURL, Engine.DefaultAssetSource.filterLut.rawValue: Engine.assetBaseURL, Engine.DefaultAssetSource.filterDuotone.rawValue: Engine.assetBaseURL, Engine.DefaultAssetSource.colorsDefaultPalette.rawValue: Engine.assetBaseURL, Engine.DefaultAssetSource.effect.rawValue: Engine.assetBaseURL, Engine.DefaultAssetSource.blur.rawValue: Engine.assetBaseURL, Engine.DefaultAssetSource.typeface.rawValue: Engine.assetBaseURL, Engine.DefaultAssetSource.cropPresets.rawValue: Engine.assetBaseURL, Engine.DefaultAssetSource.pagePresets.rawValue: Engine.assetBaseURL,
Engine.DemoAssetSource.image.rawValue: Engine.assetBaseURL, Engine.DemoAssetSource.textComponents.rawValue: Engine.assetBaseURL,]
try await withThrowingTaskGroup(of: Void.self) { group in for assetSource in assetSources { group.addTask { try await engine.populateAssetSource(id: assetSource.key, baseURL: assetSource.value) } } try await group.waitForAll()}
try engine.asset.addLocalSource( sourceID: Engine.DemoAssetSource.imageUpload.rawValue, supportedMimeTypes: Engine.DemoAssetSource.imageUpload.mimeTypes,)
try await engine.asset.addSource(TextAssetSource(engine: engine))try engine.asset.addSource(PhotoRollAssetSource(engine: engine))For production deployments, self-hosting assets is required—the IMG.LY CDN is intended for development only. See Serve Assets for downloading assets, configuring baseURL and excluding unused sources to optimize load times.
Customize Export Functionality#
Export handling logic is located in OnExport+Apparel.swift as part of the onExport callback.
The default implementation exports the scene as PDF and opens the system share sheet:
guard let scene = try engine.scene.get() else { throw EditorError("No scene was found.")}let data = try await engine.block.export(scene, mimeType: .pdf) { engine in try engine.scene.getPages().forEach { try engine.block.setScopeEnabled($0, key: "layer/visibility", enabled: true) try engine.block.setVisible($0, visible: true) }}let url = FileManager.default.temporaryDirectory.appendingPathComponent("Export", conformingTo: .pdf)try data.write(to: url, options: [.atomic])eventHandler.send(.shareFile(url))Customize (Optional)#
Base URL#
The starter kit uses Engine.assetBaseURL by default, which points to https://cdn.img.ly/packages/imgly/cesdk-engine/1.73.0/assets. To self-host assets, download the asset zip file and pass a custom baseURL to your EngineSettings.
Color Scheme#
CE.SDK supports light and dark modes out of the box, plus automatic system preference detection. Apply SwiftUI’s .preferredColorScheme modifier to the Editor view to switch themes.
See Theming for more details.
Localization#
See Localization for supported languages, adding support for new languages, and replacing existing keys.
UI Layout#
All configurable components are located in the components/ folder:
CanvasMenu+Apparel.swift— see Canvas Menu for full configuration optionsDock+Apparel.swift— see Dock for full configuration optionsInspectorBar+Apparel.swift— see Inspector Bar for full configuration optionsNavigationBar+Apparel.swift— see Navigation Bar for full configuration options
Troubleshooting#
Editor doesn’t load#
- Check onCreate: Ensure the
onCreatecallback loads a scene successfully - Verify the baseURL: Assets must be accessible from the CDN or your self-hosted location
- Check Xcode console: Look for errors in the Xcode debug console
Assets don’t appear#
- Check network requests: Make sure the device or simulator is connected to the internet
- Self-host assets for production: See Serve Assets to host assets on your infrastructure
- Check Xcode console: Look for errors in the Xcode debug console
Export fails or produces blank documents#
- Wait for content to load: Ensure all elements are fully loaded before exporting
- Check Xcode console: Look for errors in the Xcode debug console
Watermark appears in production#
- Add your license key: Set the
licenseproperty in yourEngineSettings - Sign up for a trial: Get a free trial license at img.ly/forms/free-trial
Next Steps#
- Configuration – Complete list of initialization options
- Serve Assets – Self-host engine assets for production
- Theming – Customize colors and appearance
- Localization – Add translations and language support