Implementation

Updated March 31, 2026

8 min read

Image Upload & Storage

Upload, manage, and optimize images. Understand storage limits, quotas, and best practices.

image uploadstorage limitsmedia managementfile uploadstorage quota
Overview

Handover provides built-in image storage with automatic quota management. This guide covers the upload flow, storage limits, and best practices.

Upload Flow

The uploadImage() SDK method handles the complete three-step upload process automatically: request upload URL, upload to storage, save metadata.

const fileInput = document.querySelector("input[type=file]");
const file = fileInput.files[0];

try {
  const result = await handover.uploadImage(
    file,
    sessionToken,
    "Hero image for homepage" // optional alt text
  );
  
  console.log("Image uploaded:", result.url);
  console.log("Image ID:", result.imageId);
} catch (error) {
  if (error.code === "STORAGE_LIMIT_EXCEEDED") {
    // Show upgrade prompt
  }
}
typescript

Storage Limits

Handover enforces storage quotas based on subscription tier. Uploads that exceed the limit are automatically rejected.

  • Free tier: 100MB total storage
  • Pro tier: 10GB total storage
  • Storage is tracked per user across all projects
  • Deleting images reclaims quota immediately

Supported File Types

Only image files are accepted. The SDK validates the MIME type before uploading.

  • JPEG/JPG (image/jpeg)
  • PNG (image/png)
  • GIF (image/gif)
  • WebP (image/webp)
  • SVG (image/svg+xml)

Deleting Images

Remove unused images to free up storage quota. Deletion is immediate and cannot be undone.

await handover.deleteImage(imageId, sessionToken);
// Storage quota is updated immediately
typescript

Listing Images

Get all images for the project via getContent(). Each image includes URL, ID, and metadata.

const content = await handover.getContent();

content.images.forEach(image => {
  console.log(image.url);      // CDN URL
  console.log(image._id);      // Image ID
  console.log(image.altText);  // Alt text (optional)
  console.log(image.mimeType); // e.g., "image/jpeg"
});
typescript

Best Practices

Follow these guidelines to optimize storage usage and performance.

  • Compress images before upload (use tools like TinyPNG)
  • Use WebP format for better compression
  • Delete unused images regularly
  • Always provide alt text for accessibility
  • Consider lazy loading for multiple images
  • Use responsive images with srcset
Source doc

This page maps to convex/images.ts in the repository.