Skip to main content
The Images API closes the “slides as code” loop for local files. Instead of hosting images externally before referencing them in a slide, you upload the raw bytes through the SDK and get back a CDN URL that you can pass straight to image(url) or use in an imageFill. The SDK uploads the bytes to Ablo’s hosted storage on your behalf — your API key is the only credential required. The returned URL is a stable CDN edge URL that remains valid across subsequent renders.

ablo.images.upload(params)UploadedImage

Uploads image bytes to Ablo’s CDN and returns the hosted URL.
params.bytes
Uint8Array | ArrayBuffer
required
The raw image bytes. Accepts either a Uint8Array (the type you get from fs.readFileSync in Node.js) or an ArrayBuffer.
params.contentType
ImageMime
required
The MIME type of the image. Must be one of the allowed types:
ValueFormat
'image/jpeg'JPEG
'image/png'PNG
'image/gif'GIF
'image/webp'WebP
'image/svg+xml'SVG
'image/avif'AVIF
Passing an unlisted MIME type throws a validation error before any network request is made.
params.fileName
string
Optional cosmetic file name used to form the S3 key. Does not affect the returned URL. Useful for debugging storage keys.
params.deckId
string
Optional deck id that scopes the storage key. Images uploaded with a deckId are namespaced under that deck in storage. Omitting it still works — the file is stored under a random id.
Returns UploadedImage
url
string
The CDN URL for the uploaded image. Pass this to image(url), imageFill(url), or use it directly in an { type: 'image', url, at } layer object.
s3Key
string
The S3 key where the file is stored. Informational — you don’t need this for slide authoring.

Examples

Upload a local file with Node.js

Read a file from disk using fs.readFileSync, then upload it and use the CDN URL as an image layer.
import fs from 'fs';
import Decks, { image } from '@abloatai/decks';

const ablo = new Decks(process.env.ABLO_API_KEY!);

// Read the file — readFileSync returns a Buffer, which extends Uint8Array.
const bytes = fs.readFileSync('./assets/hero.png');

const uploaded = await ablo.images.upload({
  bytes,
  contentType: 'image/png',
  fileName: 'hero.png',
  deckId: deck.id,         // optional — scopes the storage key
});

console.log('CDN URL:', uploaded.url);

// Use it directly as a slide layer.
const slide = await ablo.slides.create({
  deckId: deck.id,
  order: 0,
  layers: [
    {
      type: 'image',
      url: uploaded.url,   // the CDN URL from the upload
      objectFit: 'cover',
      at: { x: 960, y: 0, w: 960, h: 1080 },
    },
  ],
});

Upload and use with the image() builder

When you’re filling a layout placeholder or using the functional builder style, pass the URL to image().
import fs from 'fs';
import Decks, { image } from '@abloatai/decks';

const ablo = new Decks(process.env.ABLO_API_KEY!);
const deck  = await ablo.decks.create({ title: 'Product Launch' });

// Upload multiple assets up front.
const [heroCdn, logoCdn] = await Promise.all([
  ablo.images.upload({
    bytes: fs.readFileSync('./assets/hero.jpg'),
    contentType: 'image/jpeg',
    fileName: 'hero.jpg',
  }),
  ablo.images.upload({
    bytes: fs.readFileSync('./assets/logo.svg'),
    contentType: 'image/svg+xml',
    fileName: 'logo.svg',
  }),
]);

// Reference the CDN URLs in slide layers.
await ablo.decks.create({
  title: 'Product Launch',
  slides: [
    {
      title: 'Cover',
      layers: [
        {
          type: 'image',
          url: heroCdn.url,
          objectFit: 'cover',
          at: { x: 0, y: 0, w: 1920, h: 1080 },
        },
        {
          type: 'image',
          url: logoCdn.url,
          objectFit: 'contain',
          at: { x: 80, y: 40, w: 200, h: 60 },
        },
      ],
    },
  ],
});

Upload from a browser File input

In a browser context, read the file as an ArrayBuffer and upload it.
async function uploadFromInput(file: File, deckId: string): Promise<string> {
  const buffer = await file.arrayBuffer();
  const uploaded = await ablo.images.upload({
    bytes: buffer,
    contentType: file.type as ImageMime,
    fileName: file.name,
    deckId,
  });
  return uploaded.url;
}