Type something to search...
Using Sanity Media Library Plugins

Using Sanity Media Library Plugins

Sanity media library plugins extend Sanity Studio's basic asset picker with proper asset management. The most widely used is sanity-plugin-media, which adds a Media tool to Studio for browsing, searching, tagging and organising images and files into folders, and also replaces the picker on image and file fields. Asset source plugins, such as sanity-plugin-asset-source-unsplash and sanity-plugin-cloudinary, let editors pull assets from external services. For organisation-wide asset management across several projects, Sanity also offers Media Library, a separate app available as an add-on for certain Enterprise plans, which you connect to Studio with mediaLibrary: { enabled: true } in sanity.config.ts.

Out of the box, Studio lets editors upload a file or pick one they've uploaded before, and that's about it. There's no search by tag, no folders and no way to see where an asset is used or delete unused ones in bulk. That's fine for a small blog and painful for a team with thousands of images. This guide explains what each option does, how to install and configure it, how the data is stored and queried, and how to choose between them.

What the Default Asset Picker Does

Every image and file field in Studio has an upload button and a browse option. Browsing shows a grid of previously uploaded assets of the right type, which you can select to reuse. That covers the basics, but it lacks:

  • Organisation: No tags, folders or collections.
  • Search: Limited ways to find a specific asset among thousands.
  • Asset-level metadata editing: No interface for the title, description and altText fields that exist on asset documents.
  • Bulk actions: No multi-select delete or tagging.

Each tool below fills some or all of these gaps. If you haven't worked with asset documents yet, managing files and assets in Sanity explains how they're stored.

Your Options at a Glance

ToolWhat it isWhere assets livePlans
Default asset sourceBuilt-in upload and browseYour datasetAll
sanity-plugin-mediaStudio tool and asset source with tags and foldersYour datasetAll (open source plugin)
Asset source pluginsPickers for Unsplash, Cloudinary and other servicesCopied into your dataset, or referenced externallyAll, plus the service's own terms
Media LibraryOrganisation-wide asset management appA shared library for your organisationAdd-on for certain Enterprise plans

You can combine them. Many teams use the Media plugin for day-to-day management and add Unsplash for stock photos.

The Media Plugin

sanity-plugin-media is an open source plugin that now lives in Sanity's official plugins repository. It adds a Media tool to your Studio navigation and registers itself as an asset source on image and file fields.

Install and Configure

npm install sanity-plugin-media
// sanity.config.ts
import { defineConfig } from "sanity";
import { structureTool } from "sanity/structure";
import { visionTool } from "@sanity/vision";
import { media } from "sanity-plugin-media";
import { schemaTypes } from "./schemaTypes";

export default defineConfig({
  name: "default",
  title: "My Studio",
  projectId: "abc123",
  dataset: "production",
  plugins: [structureTool(), media(), visionTool()],
  schema: { types: schemaTypes },
});

That's all you need. Editors now see a Media tool in the top navigation, and the browse menu on image and file fields gains a Media option.

What You Get

According to the plugin's README, its main features are:

  • Batch uploads with drag and drop.
  • Editing asset fields such as title, description, altText and originalFilename directly on the asset.
  • Tags that you can create, rename and assign individually or in bulk.
  • Folders in a sidebar, with drag and drop to move assets between them.
  • Faceted search by tag, folder, usage, file size, orientation, type and more, plus text search across title, description and alt text.
  • Bulk selection and deletion, with shift-click and cmd or ctrl-click.
  • Previews for audio and video, and a subset of EXIF data when it's been extracted.
  • Virtualised grid and table views that stay fast with thousands of assets, plus real-time updates from other editors.

Plugin Options

The plugin accepts a configuration object. These are the options you're most likely to use:

media({
  creditLine: {
    enabled: true,
    excludeSources: ["unsplash"],
  },
  maximumUploadSize: 10_000_000, // bytes
  directUploads: true,
  excludeTags: ["archived"],
});
  • creditLine: Adds a credit line field for photographer or licence information. excludeSources stops editors overwriting credits that come from services like Unsplash.
  • maximumUploadSize: Caps uploads through the plugin, in bytes. Useful for stopping 50 MB camera files.
  • directUploads: Set to false to stop uploads through the plugin interface.
  • excludeTags: Hides assets with these tag slugs from the browser and picker.
  • locales: An array of { id, title } objects that makes title, alt text, description and credit line localisable, with a tab per language.

Where the Data Is Stored

This is the most important thing to understand about the plugin. It writes directly to asset documents (sanity.imageAsset and sanity.fileAsset), not to the documents that use them:

  • Text fields like altText, title and description are part of Sanity's asset schema, so they're stored as top-level properties on the asset.
  • Tags are media.tag documents, stored as weak references in opt.media.tags on each asset.
  • Folders are media.folder documents, with the asset's folder stored as a weak reference at opt.media.folder.

Because the values live on the asset, they're global. Set the alt text once and every document that uses the image can read it. That's ideal for values that describe the image itself, but not for context-specific ones. A caption that changes per article still belongs in the image field's own fields.

Query Plugin Data

Dereference the asset to read plugin fields:

*[_type == "post" && slug.current == $slug][0]{
  title,
  mainImage{
    alt,
    asset->{
      url,
      altText,
      title,
      description,
      "tags": opt.media.tags[]->name.current,
      "folder": opt.media.folder->name
    }
  }
}

A common pattern is to prefer the document-level alt text and fall back to the asset's:

"alt": coalesce(mainImage.alt, mainImage.asset->altText)

That gives editors a sensible default while still letting them override it per use. The full approach to alt text is covered in alt text requirements for Sanity images.

The README notes that opt.media tags and folders aren't available through Sanity's GraphQL API, because opt isn't part of Sanity's asset schema. Use GROQ if you need them.

Auto-Tagging Fields

You can pre-filter the browser and tag assets automatically when an editor selects them in a specific field. The mediaField helper wires this up:

// schemaTypes/product.ts
import { defineType, defineField } from "sanity";
import { mediaField } from "sanity-plugin-media";

export const product = defineType({
  name: "product",
  type: "document",
  fields: [
    defineField({ name: "name", type: "string" }),
    mediaField({
      name: "image",
      type: "image",
      mediaTags: ["product"],
    }),
  ],
});

Editors choosing a product image see product-tagged assets first, and any asset they pick gets the product tag. Tags that don't exist yet are created automatically unless you set createTagsOnUpload: false.

Hide the Tag Type From Structure

The plugin registers a media.tag document type. If you use the default structure, it appears in your content list. To hide it, define a custom structure with Structure Builder that lists your own document types and leaves media.tag out.

Asset Source Plugins

Asset source plugins add new options to the browse menu on image and file fields. When there's more than one source, the select button becomes a drop-down.

Unsplash

npm install sanity-plugin-asset-source-unsplash
// sanity.config.ts
import { unsplashImageAsset } from "sanity-plugin-asset-source-unsplash";

export default defineConfig({
  // ...
  plugins: [structureTool(), media(), unsplashImageAsset()],
});

Editors can search Unsplash from inside Studio. Selected photos are copied into your dataset as normal image assets, with source information on the asset document so you can trace them back. Check Unsplash's licence and attribution guidelines for your use.

Cloudinary

sanity-plugin-cloudinary provides three plugins for different setups:

  • cloudinaryAssetSourcePlugin: Adds Cloudinary as an asset source. Images are copied into Sanity and served from Sanity's CDN.
  • cloudinarySchemaPlugin: Adds a cloudinary.asset field type. Assets stay in Cloudinary and are served from Cloudinary's CDN.
  • cloudinaryReferencePlugin: Stores Cloudinary assets as reusable document references.
import { cloudinaryAssetSourcePlugin } from "sanity-plugin-cloudinary";

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

Choose the asset source mode if you want everything in Sanity, and the schema mode if your organisation already relies on Cloudinary's transformations and delivery.

Other Sources

Sanity's official plugins repository also includes integrations for Aprimo, Bynder, Shopify assets and Mux video, among others. The Sanity Exchange lists community plugins too. Video is a good example of where an external service makes sense, because Content Lake stores video as a plain file with no streaming.

Control Which Sources Appear

You can control sources globally in sanity.config.ts through form.image.assetSources and form.file.assetSources, or per field with options.sources.

The global options accept either an array or a function, and they behave differently. Sanity's docs explain that a static array appends to the existing sources, while a function replaces them with whatever it returns:

// sanity.config.ts
import { mediaAssetSource } from "sanity-plugin-media";
import { unsplashAssetSource } from "sanity-plugin-asset-source-unsplash";

export default defineConfig({
  // ...
  form: {
    image: {
      // Function: replaces the list. Remove Unsplash from the 'logo' image type only.
      assetSources: (previous, { schema }) =>
        schema.name === "logo"
          ? previous.filter((source) => source !== unsplashAssetSource)
          : previous,
    },
    file: {
      // Don't offer the Media plugin for file fields
      assetSources: (previous) =>
        previous.filter((source) => source !== mediaAssetSource),
    },
  },
});

Per field, options.sources limits that field to specific sources, and an empty array removes the browse option entirely so the field is upload-only:

defineField({
  name: "heroImage",
  type: "image",
  options: { sources: [mediaAssetSource] },
});

If no plugin fits, you can write your own asset source: a React component that calls onSelect with a URL, file, base64 string or existing asset ID. Sanity's custom asset sources documentation walks through the API.

Sanity Media Library

Media Library is Sanity's own digital asset management app, distinct from the plugin. It's a paid add-on for certain Enterprise plans, so check with Sanity sales before planning around it. The Sanity pricing guide gives an overview of the plans.

According to Sanity's documentation, Media Library lets you:

  • Store assets centrally for use across multiple projects and datasets in your organisation.
  • Describe assets with aspects, which are custom, schema-style metadata fields such as licence details or product references.
  • Organise assets into nested folders and collections.
  • Set assets to public or private, with signed, time-limited URLs for private assets.
  • Manage versions of an asset and update the documents that use it.
  • Handle video, with playback streamed through a dedicated video CDN.

It runs inside Sanity's Dashboard rather than in Studio itself.

Connect It to Studio

Media Library needs Studio v3.82.0 or later. Once it's enabled for your organisation, turn it on in your config. Sanity recommends token-based authentication, because some features don't work with cookie-based login:

// sanity.config.ts
import { defineConfig } from "sanity";
import { structureTool } from "sanity/structure";

export default defineConfig({
  projectId: "abc123",
  dataset: "production",
  mediaLibrary: {
    enabled: true,
    // Optional: pin to a specific library
    // libraryId: 'YOUR_MEDIA_LIBRARY_ID',
  },
  auth: {
    loginMethod: "token",
  },
  plugins: [structureTool()],
  schema: { types: [] },
});

To move editors entirely to Media Library, remove the default source, which is named sanity-default:

form: {
  image: {
    assetSources: (sources) => sources.filter((s) => s.name !== 'sanity-default'),
  },
  file: {
    assetSources: (sources) => sources.filter((s) => s.name !== 'sanity-default'),
  },
},

From Studio v4.2.0, you can also add selectable filters to an image field's Media Library picker using GROQ against the library's dataset:

defineField({
  name: "heroImage",
  type: "image",
  options: {
    mediaLibrary: {
      filters: [
        {
          name: "Wider than 2000px",
          query: "currentVersion->metadata.dimensions.width > 2000",
        },
      ],
    },
  },
});

How Rendering Works

Linking a Media Library asset to a document creates a normal asset document in your dataset, carrying a media reference back to the library. You keep rendering images exactly as before, with @sanity/image-url and the project's CDN. Sanity's docs say all requests for Media Library assets should go through your project datasets, and that bandwidth for those requests counts towards the project. See using Sanity's image URL builder for the rendering side.

If you're moving from the Media plugin, Sanity publishes a migration guide covering moving assets, re-linking them and updating references.

Which Should You Choose?

  • Small site, few editors: The default asset source is enough. Add sanity-plugin-media when finding images starts to take time.
  • Growing content team on one project: sanity-plugin-media gives you tags, folders, search, global alt text and bulk clean-up at no extra cost.
  • Heavy use of stock photography: Add the Unsplash source alongside whichever manager you use.
  • Existing DAM such as Cloudinary or Bynder: Use the matching plugin so assets stay in the system your organisation already trusts.
  • Many projects sharing one asset library, private assets or licensing workflows: That's what Media Library is for, if your organisation is on an eligible Enterprise plan.

FAQ: Sanity Media Library Plugins

sanity-plugin-media is an open source Studio plugin that manages assets in a single dataset with tags, folders and search. Media Library is a separate Sanity app, sold as an add-on for certain Enterprise plans, that manages assets across an organisation with aspects, private assets and versions.

Yes. It's an MIT-licensed plugin maintained in Sanity's official plugins repository. Assets you manage with it still count towards your project's normal asset storage and bandwidth.

On the asset document itself, in the altText field of sanity.imageAsset. That makes it global for every use of the image. Query it with asset->altText, and use a field on the image object for alt text that should vary by document.

Yes. The Unsplash asset source copies the selected photo into your dataset as a normal image asset and records where it came from on the asset document, so you render it like any other Sanity image.

Use a function for form.image.assetSources or form.file.assetSources in sanity.config.ts that filters out the source named sanity-default. A function replaces the list of sources, while a static array would append to it.

Sanity's docs list Studio v3.82.0 or later for using Media Library assets in Studio, and v4.2.0 or later for Media Library filters on image fields. Your organisation must also have Media Library enabled.


Conclusion

Sanity's default asset picker is deliberately minimal, and the plugin ecosystem fills the gaps. sanity-plugin-media is the natural first step for most teams, adding tags, folders, search and global asset fields like alt text without changing how you render images. Asset source plugins bring in Unsplash, Cloudinary and other services, and you control where each one appears with assetSources and per-field sources.

For organisations that need one library across many projects, with private assets and structured metadata, Media Library is Sanity's answer, provided you're on an eligible Enterprise plan. Whichever you choose, assets still reach your front end through your project's dataset and CDN, so your rendering code stays the same as your asset management grows.

Tags :
Share :

Related Posts

Building a Static Site With Astro and Sanity

Building a Static Site With Astro and Sanity

To build a static site with Astro and Sanity, keep Astro's default output: 'static', configure @sanity/astro with useCdn: false, and fetch

Dive Deeper
Common Sanity Mistakes and How to Fix Them

Common Sanity Mistakes and How to Fix Them

The most common Sanity mistakes are using the CDN where you need fresh data, fetching whole documents with ..., leaving slugs unvalidated, ship

Dive Deeper
How to Create a Custom Sanity Plugin

How to Create a Custom Sanity Plugin

To create a custom Sanity plugin, wrap a piece of Studio configuration in definePlugin from the sanity package and add it to the plugins ar

Dive Deeper