Giving your users the option to use their own images within their creations will boost their creative output to new levels. CE.SDK provides a built-in upload handler that stores files locally in memory. For production use cases where files need to persist across sessions, you can register a custom upload handler.

Local Uploads#
CE.SDK includes a default local upload handler that allows uploading images locally. The “Add file” button appears in the image library without any configuration.
// Local upload is the default behaviorconst cesdk = await CreativeEditorSDK.create(container, config);Local uploads only store files in memory. They won’t be available when opening the same scene in a different environment or after a page reload. For production use, implement a custom upload handler.
Adding Upload Demo Asset Sources#
To enable upload functionality in demo asset sources, you must explicitly pass the withUploadAssetSources option when calling addDemoAssetSources():
const cesdk = await CreativeEditorSDK.create(container, config);
// Enable upload demo asset sourcescesdk.addDemoAssetSources({  sceneMode: 'Design',  withUploadAssetSources: true,});Without this option, demo asset sources will not include upload functionality.
Remote Uploads#
To persist uploads across sessions, register a custom upload handler using the Callbacks API after SDK initialization:
const cesdk = await CreativeEditorSDK.create(container, config);
// Register custom upload handlercesdk.actions.register('uploadFile', async (file, onProgress, context) => {  // Upload file to your CDN or storage service  const formData = new FormData();  formData.append('file', file);
  const response = await fetch('/api/upload', {    method: 'POST',    body: formData,  });
  const { url, thumbnailUrl } = await response.json();
  // Return asset definition  return {    id: `asset-${Date.now()}`,    label: {      en: file.name,    },    meta: {      uri: url,      thumbUri: thumbnailUrl,      kind: 'image',    },  };});Accessing the Default Local Upload#
The default local upload handler can be accessed through the Utils API:
cesdk.actions.register('uploadFile', async (file, onProgress, context) => {  // Conditionally use different upload strategies  if (shouldUseLocalStorage(file)) {    // Use the utils API for local upload    return await cesdk.utils.localUpload(file, context);  }
  // Otherwise use your custom upload logic  return await uploadToStorage(file, onProgress, context);});This pattern allows you to conditionally choose between local storage and remote storage based on your application’s requirements.