@sirv/sanity-plugin
v0.2.1
Published
Add Sirv as a media source inside Sanity Studio v3, v4 and v5: connect your account, browse the Sirv DAM, and pick images, videos, 360 spins or any file. Your assets stay on Sirv and render on the frontend with @sirv/react.
Readme
@sirv/sanity-plugin
Add Sirv as a media source inside Sanity Studio v3, v4 and v5. 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.
- No backend required - Sanity Studio talks directly to Sirv's REST API.
- No credentials exposed - REST credentials are encrypted in the dataset's secrets.
- Self-host friendly - designed for a locally-run / self-hosted Studio.
Install
npm install @sirv/sanity-plugin
# frontend renderer (to display the picked assets on your site)
npm install @sirv/reactPeer dependencies (already present in a Studio): sanity, @sanity/ui, @sanity/icons,
react, react-dom, styled-components.
Configure
Add the plugin in sanity.config.ts:
import { defineConfig } from 'sanity';
import { sirv } from '@sirv/sanity-plugin';
export default defineConfig({
// ...
plugins: [sirv()],
});That's it - the plugin registers everything below automatically.
Connect your Sirv account (first run)
- Open the Sirv tool in the Studio's top tool menu (cog icon).
- Paste your account's REST API Client ID and Client secret. Find them in Sirv under Account → Settings → API (https://my.sirv.com/#/account/settings/api).
- Pick a delivery domain (your
*.sirv.comhost or a custom domain). - Done. The connection is stored in the dataset (encrypted secret) and reused silently next time. Use Disconnect in the same tool to switch accounts.
Use a private dataset. The connection (your REST credentials) is saved as a dataset document. A private dataset keeps it from being publicly readable. The credentials are never bundled into the Studio JavaScript.
What you get
1. "Browse Sirv" on image & file fields (Asset Source)
Every standard image and file field gains a Browse Sirv option in its Select menu.
Picking imports the file into Sanity (served from Sanity's CDN afterward).
- Image fields show images only.
- File fields show all asset types, including generic files (PDF, ZIP, ...).
defineField({ name: 'cover', title: 'Cover', type: 'image' }); // gets "Browse Sirv"
defineField({ name: 'brochure', title: 'Brochure', type: 'file' }); // any Sirv file2. sirvMedia - a single Sirv-native asset (recommended)
The asset stays on Sirv; the field stores its path, delivery domain, dimensions, and
optional transformations. Restrict the pickable types with options.allowedTypes.
defineField({
name: 'hero',
title: 'Hero',
type: 'sirvMedia',
options: { allowedTypes: ['image', 'video'] }, // image | video | spin | view | model
});- Auto-fills Alt text and Caption from the asset's Sirv metadata (
?info). - Per-asset controls: image quality, and video playback flags (controls/autoplay/loop/muted).
3. sirvMediaList - a gallery (multi-select)
An ordered list of Sirv-native assets with a persistent Add asset from Sirv button and multi-select in the browser (tick several, add them all at once).
defineField({
name: 'gallery',
title: 'Gallery',
type: 'sirvMediaList',
options: { allowedTypes: ['image', 'video', 'spin', 'view'] },
});4. sirvAssetUrl - a URL field backed by the Sirv picker
A url field whose value is a picked Sirv asset's delivery URL (any type, generic files
included). Useful when you just need a string URL.
defineField({ name: 'downloadUrl', title: 'Download URL', type: 'sirvAssetUrl' });5. Settings tool
The Sirv tool shows the connected account and delivery domain, a Disconnect button, and a Help & support link.
Asset types
| Type | Extensions | Rendered by @sirv/react as |
|---|---|---|
| Image | jpg, png, webp, avif, gif, ... | <SirvImage> (responsive srcset + lazy) |
| Video | mp4, mov, webm, ... | <SirvVideo> (poster + controls) |
| 360 Spin | .spin | <SirvSpin> (sirv.js) |
| Sirv View | .view | <SirvView> (sirv.js composite) |
| 3D Model | .glb | <SirvModel> (sirv.js) |
| File | pdf, zip, ... | imported into Sanity / plain URL |
Stored value (sirvMedia / items of sirvMediaList)
{
"_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 with @sirv/react
Fetch the fields as-is with GROQ (they're plain objects), then render:
import { SirvProvider, SirvMedia, SirvGallery, fromSanityMedia } from '@sirv/react';
export function Post({ post }) {
return (
<SirvProvider alias="demo.sirv.com" quality={82}>
{/* single asset (image/video/spin/view) */}
<SirvMedia value={fromSanityMedia(post.hero)} width={800} />
{/* gallery: separate items, or one combined Sirv Media Viewer */}
<SirvGallery items={post.gallery.map(fromSanityMedia)} layout="viewer" />
</SirvProvider>
);
}See the @sirv/react docs for <SirvImage>, <SirvVideo>, <SirvSpin>, <SirvView>,
<SirvGallery>, and the next/image loader.
Requirements
- Sanity Studio v3, v4, or v5
- React 18 or 19
- A Sirv account with REST API credentials (free to create at https://sirv.com)
License
MIT
