How AI is powering better personalization in e-commerce [with Vercel]. Sign up now

Vimeo Field

Retrieve Vimeo video data via the API with an access token and store it in Sanity.

By Marco Land

Install command

npm i sanity-plugin-vimeo-field

Sanity Plugin Vimeo Field

npm version npm downloads license CI

Syncs your Vimeo video library into Sanity as first-class documents and provides a reference field with a visual picker.

Sanity Vimeo Field Plugin

Installation

npm install sanity-plugin-vimeo-field
# or
pnpm add sanity-plugin-vimeo-field

Requires Sanity Studio v5 and React 18+.

Setup

1. Register the plugin

// sanity.config.ts
import {defineConfig} from 'sanity'
import {vimeoField} from 'sanity-plugin-vimeo-field'

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

2. Add a Vimeo field to a document

Use the vimeo type in any document's fields array. All standard field options (hidden, readOnly, group, validation, etc.) work as expected.

// schemas/movie.ts
import {defineField, defineType} from 'sanity'

export default defineType({
  name: 'movie',
  title: 'Movie',
  type: 'document',
  fields: [
    defineField({
      type: 'vimeo',
      name: 'trailer',
      title: 'Trailer',
    }),

    // With standard field options
    defineField({
      type: 'vimeo',
      name: 'behindTheScenes',
      title: 'Behind the Scenes',
      hidden: ({document}) => !document?.title,
      readOnly: true,
      group: 'media',
    }),
  ],
})

3. Vimeo access token

The first time you use the field, you will be prompted to enter your Vimeo API access token. The token is stored securely in the Sanity dataset using @sanity/studio-secrets.

To create a token, go to developer.vimeo.com/apps, select your app (or create one), and generate a personal access token with the following scopes:

  • Public — access public videos
  • Private — access private and unlisted videos
  • Video Files — access direct video file links (progressive/HLS/DASH)

The Video Files scope requires a Vimeo Pro plan or above. Without it the play field will be empty.

How it works

Videos are stored as hidden vimeoVideo documents in your dataset. The vimeo type is an object that contains a reference to these documents.

Vimeo Library tool

Sanity Vimeo Field Plugin

The plugin adds a Vimeo Library tool to the Studio sidebar. It provides a searchable, browsable grid of all synced videos with inline video playback. From here you can:

  • Search videos by name or Vimeo ID.
  • Sync from Vimeo to fetch your full Vimeo library and upsert documents.
  • Configure Access Token to update your Vimeo API credentials.

Vimeo field

Sanity Vimeo Field Plugin

When using the vimeo type in a document:

  • Select Video opens a picker dialog showing all synced videos.
  • Sync from Vimeo (in the picker) fetches your full Vimeo library and upserts documents.
  • Refresh (on the populated field) re-syncs just the selected video from the Vimeo API.

The vimeoVideo document

Each synced video is stored as a document with this shape:

FieldTypeDescription
vimeoIdstringNumeric Vimeo video ID
namestringVideo title
durationnumberDuration in seconds
widthnumberVideo width in pixels
heightnumberVideo height in pixels
privacystringPrivacy setting — anybody, nobody, unlisted, etc.
lastSynceddatetimeWhen this document was last synced
picturesobjectThumbnail sizes (array of {width, height, link})
filesarrayVideo file downloads — {quality, type, width, height, link, size}
playobjectPlayback links — progressive[], dash, hls

Documents use the ID format vimeoVideo-{vimeoId} and have liveEdit: true (no draft/publish workflow).

Note: The files and play fields require a Vimeo account with API access to direct video file links (Pro plan or above). On free/basic accounts these fields will be empty.

Important: The play links (progressive/HLS/DASH) are short-lived and will expire after a few hours. They are not suitable for use in production frontends. Use the files field instead — it contains persistent direct MP4 download URLs that do not expire.

Querying in the frontend

The field stores a reference inside an object, so you need to dereference the nested asset field in your GROQ query:

*[_type == "movie"][0] {
  title,
  trailer {
    asset-> {
      vimeoId,
      name,
      duration,
      width,
      height,
      privacy,
      "thumbnail": pictures.sizes[0].link,
      "mp4": files[quality == "hd"][0].link,
      files
    }
  }
}

TypeScript type

Import the VimeoVideo type for use in your frontend code:

import type {VimeoVideo} from 'sanity-plugin-vimeo-field'

Migrating from v2.x.x–3.1.0

Note: In versions 2.x.x–3.1.0 the plugin was exported as vimeoFieldPlugin and the field type was named vimeoField. Both have been renamed in the current version.

vimeoFieldPlugin renamed to vimeoField

The plugin export has been renamed. Update your config:

- import {vimeoFieldPlugin} from 'sanity-plugin-vimeo-field'
+ import {vimeoField} from 'sanity-plugin-vimeo-field'

  export default defineConfig({
-   plugins: [vimeoFieldPlugin()],
+   plugins: [vimeoField()],
  })

vimeoField type renamed to vimeo

The field type name has been shortened. Update your schemas:

  defineField({
-   type: 'vimeoField',
+   type: 'vimeo',
    name: 'trailer',
    title: 'Trailer',
  })

vimeoFieldType renamed to vimeoSchemaType

If you import the raw schema type definition, update the import:

- import {vimeoFieldType} from 'sanity-plugin-vimeo-field'
+ import {vimeoSchemaType} from 'sanity-plugin-vimeo-field'

No data migration is needed — only code references change.

License

MIT © Marco Land

Develop & test

This plugin uses @sanity/plugin-kit with default configuration for build & watch scripts.

# Install dependencies
pnpm install

# Build the plugin
pnpm build

# Watch for changes during development
pnpm watch

# Link into a Sanity Studio for live development
pnpm link-watch

# Lint
pnpm lint

See Testing a plugin in Sanity Studio on how to run this plugin with hotreload in the studio.