Prismic Integration

CMS Assets has first-class support for Prismic. It handles both Prismic CDN URL patterns and provides a response transformer that rewrites asset URLs in your Prismic API responses.


Supported URL patterns

Prismic serves images and video from two different CDN domains. CMS Assets handles both:

Images (with optional Image CDN query params):

https://images.prismic.io/your-repo/path/to/image.png?auto=format,compress&w=1024&fm=webp&q=80

Video:

https://your-repo.cdn.prismic.io/your-repo/path/to/video.mp4

Both are rewritten to your tenant URL (query params on images are preserved):

https://your-tenant.cmsassets.com/your-repo/path/to/image.png?auto=format,compress&w=1024&fm=webp&q=80
https://your-tenant.cmsassets.com/your-repo/path/to/video.mp4

Tenant setup

When creating your tenant, select Prismic as the CMS type and provide your repository name:

FieldValue
CMSPrismic
Repository nameyour-repo
Website domainyour-site.com

Two origins are used: https://your-repo.cdn.prismic.io (video and some assets) and https://images.prismic.io/your-repo (images with Image CDN). CMS Assets routes requests to the correct origin based on the URL pattern.

Note: The website domain is important for Prismic. It's sent as the Referer header when fetching from origin, which prevents AccessDenied errors from Prismic's S3-backed storage.


Response transformer

Install the response transformer to automatically rewrite Prismic asset URLs in your API responses:

npm install @synchronized-studio/response-transformer

Basic usage

import { transformPrismicAssetUrls } from "@synchronized-studio/response-transformer"

const data = await prismicClient.getAllByType("page")

const transformed = transformPrismicAssetUrls(data, {
  repository: "your-repo",
  cmsAssetsUrl: "https://your-tenant.cmsassets.com"
})

What gets transformed

The transformer processes the entire JSON response and rewrites all matching URLs. This includes:

  • Document fields
  • Rich text content
  • Image fields
  • Media links
  • Slices and nested structures

Any URL matching your-repo.cdn.prismic.io or images.prismic.io/your-repo is rewritten to your CMS Assets proxy URL.

Using an environment variable

Set CMS_ASSETS_URL in your environment and omit the cmsAssetsUrl option:

CMS_ASSETS_URL=https://your-tenant.cmsassets.com
const transformed = transformPrismicAssetUrls(data, {
  repository: "your-repo"
})

Nuxt / SSR integration

For Nuxt or other SSR frameworks, wrap your Prismic client or API layer:

// composables/usePrismicData.ts
import { transformPrismicAssetUrls } from "@synchronized-studio/response-transformer"

export async function usePrismicData(type: string) {
  const data = await prismicClient.getAllByType(type)

  return transformPrismicAssetUrls(data, {
    repository: "your-repo",
    cmsAssetsUrl: useRuntimeConfig().public.cmsAssetsUrl
  })
}

Query params

Prismic often appends query parameters like ?auto=format&w=800 to image URLs. The transformer strips these during URL rewriting since the edge cache ignores query parameters for image types. This prevents duplicate cache entries and ensures consistent caching.


Preview & fresh-fetch bypass

By default, API proxy responses are cached at the edge (typically 60 seconds). For preview mode or fresh-fetch use cases — where you need guaranteed-fresh data from Prismic — you can bypass the cache per request.

The edge proxy already supports this: any API request with ?preview=1 skips cache entirely and fetches directly from upstream. The withCacheBypass wrapper makes it easy to apply this from your app code.

Setup

Create a small wrapper around createCmsAssetsFetch:

// utils/withCacheBypass.ts

export function withCacheBypass(
  baseFetch: typeof fetch,
  bypass: boolean | (() => boolean),
  param = 'preview',
): typeof fetch {
  return function bypassFetch(input, init) {
    const active = typeof bypass === 'function' ? bypass() : bypass
    if (!active) return baseFetch(input, init)

    const url = typeof input === 'string'
      ? input
      : input instanceof URL ? input.href : input.url
    if (!url) return baseFetch(input, init)

    const parsed = new URL(url)
    if (!parsed.searchParams.has(param)) {
      parsed.searchParams.set(param, '1')
    }

    if (input instanceof Request) {
      return baseFetch(new Request(parsed.toString(), input), init)
    }
    return baseFetch(parsed.toString(), init)
  }
}

Nuxt integration example

// plugins/prismic.ts
import * as prismic from '@prismicio/client'
import { createCmsAssetsFetch } from '@synchronized-studio/cmsassets-core'
import { withCacheBypass } from '~/utils/withCacheBypass'

export default defineNuxtPlugin(() => {
  const { enabled: isPreview } = usePreviewMode()

  const baseFetch = createCmsAssetsFetch({
    tenant: 'my-site',
    provider: 'prismic',
  })

  // When preview mode is active, all API requests bypass edge cache
  const cmsFetch = withCacheBypass(baseFetch, () => isPreview.value)

  const client = prismic.createClient('my-repo', {
    fetch: cmsFetch,
  })

  return { provide: { prismic: { client } } }
})

How it works

  • Normal requests go through the proxy and are served from edge cache when available (X-Cache: HIT or MISS)
  • Preview/fresh requests have ?preview=1 appended automatically, which tells the proxy to skip cache and fetch directly from Prismic (X-Cache: BYPASS)
  • The bypass signal is evaluated per request, so switching preview mode on/off takes effect immediately

Static bypass

If you need a client that always bypasses cache (e.g., for a dedicated preview endpoint), pass true instead of a function:

const previewFetch = withCacheBypass(baseFetch, true)
const previewClient = prismic.createClient('my-repo', { fetch: previewFetch })

What this does not do

  • Does not bypass asset proxy caching. The ?preview=1 param only affects /~api routes. Asset URLs are unaffected — this is intentional, since preview use cases are about fresh API data, not fresh images.
  • Does not change how Prismic preview refs work. Prismic's own preview mechanism uses a ref parameter to point to a draft release. That ref flows through the proxy as a normal query parameter. withCacheBypass ensures the proxy doesn't serve a stale cached version of the previous ref.

Advanced options

Custom transformers

You can add additional transformers that run after the default Prismic ones:

const transformed = transformPrismicAssetUrls(data, {
  repository: "your-repo",
  transformers: [
    (jsonStr, { base }) => {
      // Custom string replacement on the serialized JSON
      return jsonStr.replaceAll("old-pattern", "new-pattern")
    }
  ]
})

Post-transform hook

Run a function on the parsed result after all URL replacements:

const transformed = transformPrismicAssetUrls(data, {
  repository: "your-repo",
  postTransform: (data) => {
    // Modify the final parsed object
    return data
  }
})

Error handling

By default, transform errors are logged as warnings and the original data is returned unchanged. You can provide a custom error handler:

const transformed = transformPrismicAssetUrls(data, {
  repository: "your-repo",
  onError: (error) => {
    Sentry.captureException(error)
  }
})
Need help understanding this?Ask CMS Assets Copilot about features, setup, or integrations.
Ask Copilot →