@sirv/sanity-plugin

Add Sirv as a media source inside Sanity Studio v3, v4 and v5.

v0.1.3

Overview

Connect your Sirv account to browse your Sirv DAM (folders, search, thumbnails) and pick images, videos, 360 spins or any file to add to your page.

Your Sirv assets stay on Sirv (you store the path + delivery domain + dimensions) and render on the frontend with the companion package @sirv/react. It includes automatically scaled images to suit each users' device, lazy loading, image zoom, 360 spins, galleries, GLB models and video streaming.

Install

Install the Studio plugin and the companion frontend renderer:

npm install @sirv/sanity-plugin
# to display picked assets on your site
npm install @sirv/react

Peer deps (already in a Studio): sanity, @sanity/ui, @sanity/icons, react, react-dom, styled-components.

Configure

Add the plugin in sanity.config.ts - it registers everything automatically.

import { defineConfig } from 'sanity';
import { sirv } from '@sirv/sanity-plugin';

export default defineConfig({
  // ...
  plugins: [sirv()],
});

Connect your account

  1. Open the Sirv tool in the Studio's top tool menu (cog icon).
  2. Paste your account's REST Client ID and Client secret (Sirv → Account → Settings → API).
  3. Pick a delivery domain (a *.sirv.com host or a custom domain).
  4. Done - the connection is saved (encrypted) in the dataset and reused silently. Use Disconnect to switch accounts.
Use a private dataset. The connection is stored as a dataset document; a private dataset keeps it from being publicly readable. Credentials are never bundled into the Studio JavaScript, and the plugin ships none of its own.

Browse Sirv on image & file fields

Every standard image and file field gains a Browse Sirv option in its Select menu. Picking imports the file into Sanity. Image fields show images only; file fields show all types, including generic files (PDF, ZIP).

defineField({ name: 'cover', type: 'image' });    // gets "Browse Sirv"
defineField({ name: 'brochure', type: 'file' });  // any Sirv file (PDF/zip/...)

sirvMedia field (recommended)

A single Sirv-native asset. It stays on Sirv; the field stores its path, delivery domain, dimensions and optional transformations. Restrict the pickable types with options.allowedTypes. Auto-fills Alt/Caption from the asset's Sirv metadata.

defineField({
  name: 'hero',
  type: 'sirvMedia',
  options: { allowedTypes: ['image', 'video'] }, // image | video | spin | view
});

sirvMediaList field (gallery)

An ordered list of Sirv-native assets with a persistent add button and multi-select in the browser (tick several, add them together).

defineField({
  name: 'gallery',
  type: 'sirvMediaList',
  options: { allowedTypes: ['image', 'video', 'spin', 'view'] },
});

sirvAssetUrl field

A url field whose value is a picked Sirv asset's delivery URL (any type, generic files included). Use it when you just need a string URL.

defineField({ name: 'downloadUrl', type: 'sirvAssetUrl' });

Supported asset types

TypeExtensionsRendered by @sirv/react as
Imagejpg, png, webp, avif, gif, ...<SirvImage> (responsive srcset + lazy)
Videomp4, mov, webm, ...<SirvVideo> (poster + controls)
360 Spin.spin<SirvSpin> (sirv.js)
Sirv View.view<SirvView> (sirv.js composite)
Filepdf, zip, ...imported into Sanity / plain URL

Stored value

A sirvMedia value (and each sirvMediaList item):

{
  "_type": "sirvMedia",
  "mediaType": "image",            // image | video | spin | view
  "sirvPath": "/products/shoe.jpg",
  "sirvAlias": "demo.sirv.com",    // chosen delivery domain
  "originalUrl": "https://demo.sirv.com/products/shoe.jpg",
  "width": 2000, "height": 1500,
  "alt": "...", "caption": "...",
  "transformations": { "quality": 82 }
}

sirvAssetUrl stores a plain URL string. Image/file Asset Source fields store standard Sanity asset references.

Render on the frontend

Fetch the fields as-is with GROQ (they are plain objects), then render with @sirv/react:

import { SirvProvider, SirvMedia, SirvGallery, fromSanityMedia } from '@sirv/react';

<SirvProvider alias="demo.sirv.com" quality={82}>
  <SirvMedia value={fromSanityMedia(post.hero)} width={800} />
  <SirvGallery items={post.gallery.map(fromSanityMedia)} layout="viewer" />
</SirvProvider>

See the @sirv/react docs for every component and the next/image loader.