Skip to content

CDN Adapters

vue-image-kit/cdn provides URL builders for popular image CDNs — no dependencies, pure functions.

ts
import {
  cloudinary,
  imgix,
  bunny,
  sanity,
  storyblok,
  contentful,
  vercel,
  cloudflare,
  imagekit,
  twicpics,
  netlify,
  gumlet,
} from 'vue-image-kit/cdn'

All adapters share the same interface:

ts
adapter.url(path, options?)     // → single URL string
adapter.srcset(path, widths, options?)  // → ready srcset string

Cloudinary:

ts
const cdn = cloudinary({ cloudName: 'my-cloud' })

cdn.url('photo.jpg', { width: 800, format: 'webp' })
// → https://res.cloudinary.com/my-cloud/w_800,q_auto,f_webp/image/upload/photo.jpg

cdn.srcset('photo.jpg', [400, 800, 1200])
// → 'https://res.cloudinary.com/my-cloud/w_400,... 400w, ...'

imgix:

ts
const cdn = imgix('https://mysite.imgix.net')

cdn.url('photo.jpg', { width: 800, dpr: 2 })
// → https://mysite.imgix.net/photo.jpg?w=800&dpr=2&auto=format

cdn.srcset('photo.jpg', [400, 800, 1200])

Bunny CDN:

ts
const cdn = bunny('https://myzone.b-cdn.net')
cdn.url('photo.jpg', { width: 800, format: 'webp', quality: 85 })

Sanity:

ts
const cdn = sanity({ projectId: 'abc123', dataset: 'production' })
cdn.url('image-abc123-800x600-jpg', { width: 400 })

Storyblok:

ts
const cdn = storyblok()
cdn.url('https://a.storyblok.com/f/12345/photo.jpg', { width: 800 })

Contentful:

ts
const cdn = contentful()
cdn.url('https://images.ctfassets.net/space/token/photo.jpg', { width: 800 })

Vercel Image Optimization:

ts
const cdn = vercel({ origin: 'https://myapp.vercel.app' })
cdn.url('/photo.jpg', { width: 800, quality: 75 })
// → https://myapp.vercel.app/_vercel/image?url=%2Fphoto.jpg&w=800&q=75

Cloudflare Images:

ts
const cdn = cloudflare('https://example.com')
cdn.url('/photo.jpg', { width: 800, format: 'webp' })
// → https://example.com/cdn-cgi/image/width=800,format=webp/photo.jpg

ImageKit.io:

ts
const cdn = imagekit('https://ik.imagekit.io/your_id')
cdn.url('photo.jpg', { width: 800, format: 'webp' })
// → https://ik.imagekit.io/your_id/photo.jpg?tr=w-800,f-webp

TwicPics:

ts
const cdn = twicpics('https://demo.twic.pics')
cdn.url('photo.jpg', { width: 800, format: 'webp' })
// → https://demo.twic.pics/photo.jpg?twic=v1/resize=800/output=webp

Netlify Image CDN:

ts
const cdn = netlify({ origin: 'https://myapp.netlify.app' })
cdn.url('/photo.jpg', { width: 800, format: 'webp', quality: 75 })
// → https://myapp.netlify.app/.netlify/images?url=%2Fphoto.jpg&w=800&fm=webp&q=75

Gumlet:

ts
const cdn = gumlet('https://demo.gumlet.io')
cdn.url('photo.jpg', { width: 800, format: 'webp' })
// → https://demo.gumlet.io/photo.jpg?w=800&format=webp

Use with VImage:

vue
<script setup lang="ts">
import { cloudinary } from 'vue-image-kit/cdn'
const cdn = cloudinary({ cloudName: 'my-cloud' })
</script>

<template>
  <VImage
    src="/photo.jpg"
    alt="Photo"
    :srcset="cdn.srcset('/photo.jpg', [400, 800, 1200])"
    sizes="(max-width: 768px) 100vw, 50vw"
  />
</template>

Auto CDN detection

autoLoader() looks at a URL's hostname and picks the right adapter for you — no per-provider wiring when the asset is already served from a recognizable CDN host. It fingerprints 8 of the 12 adapters this way: Cloudinary, imgix, Bunny, ImageKit, Sanity, Storyblok, Contentful, Gumlet. Returns the URL unchanged when nothing matches, so it's safe to run over every src unconditionally — a local /images/photo.jpg just passes through.

ts
import { autoLoader } from 'vue-image-kit/cdn'

autoLoader('https://res.cloudinary.com/demo/image/upload/photo.jpg', { width: 800 })
// → https://res.cloudinary.com/demo/w_800,q_auto,f_auto/image/upload/photo.jpg

autoLoader('/local/photo.jpg', { width: 800 })
// → '/local/photo.jpg' — no recognized CDN host, unchanged

The other 4 adapters (Netlify, Vercel, Cloudflare, TwicPics) run on your own domain rather than a distinctive one, so there's no hostname to fingerprint — pass them explicitly via config.hosts, keyed by your actual domain:

ts
import { autoLoader, netlify } from 'vue-image-kit/cdn'

autoLoader(
  src,
  { width: 800 },
  {
    hosts: { 'myapp.netlify.app': netlify({ origin: 'https://myapp.netlify.app' }) },
  },
)

autoSrcset() is the same detection, building a real per-width srcset (one distinct URL per width, via the adapter's own .srcset()) instead of a single URL — unlike autoLoader, it returns undefined rather than the input unchanged when nothing is detected, since there's no sensible "unchanged srcset" to fall back to:

ts
import { autoSrcset } from 'vue-image-kit/cdn'

autoSrcset('https://mysite.imgix.net/photo.jpg', [400, 800, 1200])
// → 'https://mysite.imgix.net/photo.jpg?w=400&auto=format 400w, ...'

Auto CDN detection with VImage

VImage's cdn prop wires autoLoader()/autoSrcset() straight into the component — no manual detection, no manual src rewriting:

vue
<VImage src="https://res.cloudinary.com/demo/image/upload/photo.jpg" alt="Photo" cdn />

Combined with widths, each candidate gets a real CDN-transformed URL via the adapter's .srcset() instead of widths' usual "same URL, different w descriptor" behavior (generateSrcset — see Network-aware loading for why that limitation exists for the non-CDN case):

vue
<VImage src="https://mysite.imgix.net/photo.jpg" alt="Photo" cdn :widths="[400, 800, 1200]" />

Pass an AutoLoaderConfig object instead of true to cover the "your own domain" providers (Netlify/Vercel/Cloudflare/TwicPics) via hosts, same as autoLoader() itself:

vue
<script setup lang="ts">
import { netlify } from 'vue-image-kit/cdn'
const cdnConfig = {
  hosts: { 'myapp.netlify.app': netlify({ origin: 'https://myapp.netlify.app' }) },
}
</script>

<template>
  <VImage src="https://myapp.netlify.app/photo.jpg" alt="Photo" :cdn="cdnConfig" />
</template>

Has no effect on an unrecognized host (passthrough, same as autoLoader), or on an explicit SrcSet object / densities — those are already format/resolution choices you made by hand.