Skip to content

Latest commit

 

History

History
425 lines (278 loc) · 15 KB

File metadata and controls

425 lines (278 loc) · 15 KB

Contributing to Sanity Plugins

Thank you for your interest in contributing to the Sanity Plugins monorepo! This guide will help you get set up and explain our workflows.

For AI Agents: See AGENTS.md for agent-specific instructions and quick reference commands.

Table of Contents

Development Setup

Prerequisites

  • Node.js (latest LTS)
  • pnpm v10 or later — the exact version is managed via packageManager in root package.json

Initial Setup

# Enable corepack to automatically use the correct pnpm version
corepack enable

# Install all dependencies
pnpm install

Running the Test Studio

The test studio located at dev/test-studio is a Sanity Studio instance that includes all plugins from this monorepo. It's the primary way to develop and test plugins locally.

# Start the test studio in development mode
pnpm dev

This starts the Sanity Studio dev server at http://localhost:3333. The studio is pre-configured with all plugins and includes example schemas to test plugin functionality.

Note: The test studio requires Sanity user authentication in the browser. When you access the studio, you'll need to log in with your Sanity account. Simply accessing the URL isn't enough—the studio connects to Sanity APIs and requires authenticated access to the configured project.

The studio is deployed in two places:

Adding Your Plugin to the Test Studio

  1. Add your plugin as a dependency in dev/test-studio/package.json:
{
  "dependencies": {
    "your-plugin-name": "workspace:*"
  }
}
  1. Import and configure your plugin in dev/test-studio/sanity.config.ts

  2. If your plugin requires schema types, add them to the appropriate schema file in dev/test-studio/src/

Code Quality

Formatting

We use oxfmt for code formatting:

# Format all files
pnpm format

Linting

We use oxlint for all linting (including React Compiler rules via the react-hooks-js plugin):

# Run the linter
pnpm lint

Type Checking

Type checking is performed by oxlint when running the lint command.

Testing

The monorepo uses Vitest v4 for testing.

# Run all tests (non-watch mode)
pnpm test run

# Run tests in watch mode (default vitest behavior)
pnpm test

# Update snapshots
pnpm test -u

Tests are co-located with source code in the src/ directory using .test.ts or .spec.ts extensions. Each plugin includes a package exports test to verify all exports are valid. Tests run from the root and require packages to be built first.

When creating a new plugin with pnpm generate, test files and configuration are automatically created. The root vitest.config.ts uses glob patterns to automatically discover all plugins, so no manual test configuration is needed when adding new plugins.

Test Timeouts

When tests need custom timeouts, use the options object syntax as the second argument:

// Correct
test('my test', {timeout: 30_000}, async () => {
  // ...
})

// Wrong (deprecated)
test('my test', async () => {}, 30000)

Running All Checks

Before submitting a PR, make sure all checks pass:

pnpm format
pnpm lint
pnpm build
pnpm test

And attach a changeset:

pnpm changeset add

Adding a New Plugin

Plugin Ownership Model

All new official Studio plugins should be added to this monorepo.

The plugins monorepo is the canonical home for all Studio plugins, whether built by the Studio App Team or any other team at Sanity.

Being in this monorepo does not mean the Studio team owns the plugin. The monorepo is a collaborative space. The Studio team owns the repository, tooling, and cross-cutting maintenance work, while the creating team owns the plugin itself.

You build it, you own it — The team or individual who builds a plugin is responsible for bugs, new features, and user support. This must be explicit from day one.

Ownership Principles

  • Official plugin home: New official Studio plugins should be created in this monorepo instead of standalone repositories
  • You build it, you own it: The team that creates the plugin is responsible for plugin-specific bugs, features, issue triage, and community support
  • Studio team role: The Studio team maintains monorepo infrastructure, CI/release automation, and compatibility updates needed for Studio majors
  • Owner is required: Every new plugin must add a dedicated owner entry in .github/CODEOWNERS (prefer a GitHub team, not an individual) before merge

Responsibilities

Responsibility Studio team Plugin owner team
Monorepo tooling and CI
Release automation and publishing workflow
Studio major compatibility updates
PR review for monorepo standards and consistency
PR review for plugin domain correctness
Plugin-specific bug fixes
Plugin feature development
Issue triage and response for the plugin
Community support for plugin behavior and usage

New Plugin Checklist (Ownership + Release)

For any new plugin PR, make sure all of the following are included:

  1. Plugin scaffold/code in plugins/...
  2. A .changeset/*.md file for release automation
  3. A CODEOWNERS rule that assigns the plugin path to the owning team
  4. Clear ownership details in the plugin README.md (owning team and support expectations)
  5. An entry in the root README.md ## Current Plugins table

Without an explicit owner, new plugins should not be merged.

1. Set Up Trusted Publishing

Trusted publishing configuration depends on whether the package is brand new (never published to npm) or already exists on npm.

For Brand New Packages (Not Yet on npm)

If you're creating a package that has never been published to npm before:

  1. Go to the repository's Actions tab on GitHub
  2. Find the "Setup a new npm package with Trusted Publishing" workflow
  3. Click "Run workflow"
  4. Enter the package name (e.g., @sanity/my-new-plugin or sanity-plugin-my-feature)
  5. Click "Run workflow" — the workflow will create the package on npm

Then, configure trusted publishing by running locally (requires npm >= 11.10.0):

npm trust github <package-name> --file=release.yml --repository=sanity-io/plugins

This sets up OIDC-based trusted publishing so the release workflow can publish packages without storing npm tokens.

For Existing Packages (Already on npm)

⚠️ Do NOT use the "Setup a new npm package with Trusted Publishing" workflow for existing packages! That workflow is only for brand new packages that don't have an npm settings page yet.

For packages that are already published to npm, configure trusted publishing using the npm CLI (requires npm >= 11.10.0):

npm trust github <package-name> --file=release.yml --repository=sanity-io/plugins
Alternative: Configure via npm website

If you don't have npm >= 11.10.0, you can configure trusted publishing manually:

  1. Go to your package's access settings page: https://www.npmjs.com/package/YOUR-PACKAGE-NAME/access
  2. Under "Publishing access", click "Add a trusted publisher" and select "GitHub Actions"
  3. Fill in the fields exactly as shown:
Setting Value
Owner sanity-io
Repository plugins
Workflow release.yml
Environment name (leave empty)
  1. Click "Add trusted publisher"

2. Init the plugin workspace

Run the generator and follow the prompts:

pnpm generate "new plugin"

You can now iterate on the plugin with hot reloading in the test studio:

pnpm dev

Before opening your PR, add the new package to the root README.md ## Current Plugins table so the monorepo plugin list stays current.

3. Create the Initial Release Changeset

The trusted publishing workflow publishes an initial 0.0.1 placeholder version. To publish the real first version, create a changeset:

pnpm changeset add

When prompted:

  • Select your new package
  • Choose major for the version bump (to release 1.0.0)
  • Enter Initial release as the summary

Commit the changeset file with your PR.

Migrate an existing plugin to this monorepo

1. Set Up Trusted Publishing

Since the plugin is already published to npm, configure trusted publishing using the npm CLI (requires npm >= 11.10.0):

npm trust github <package-name> --file=release.yml --repository=sanity-io/plugins

See For Existing Packages above for alternative manual instructions.

2. Init the plugin workspace

Follow the prompts in the generator:

pnpm generate "copy plugin"

The generator will:

  • Fetch metadata from the published npm package
  • Copy over version, description, and keywords
  • Copy over dependencies, automatically filtering out:
    • @sanity/incompatible-plugin (test package)
    • styled-components (should always be a peer dependency)
    • sanity (should always be a peer/dev dependency)
  • Detect if the plugin uses styled-components based on devDependencies and peerDependencies

Note: You'll need to manually review and copy over any relevant peerDependencies and devDependencies as needed.

3. Manually port over files

Refer to the generated README.md file in the plugin workspace for how to complete the last manual steps.

You can run pnpm dev to quickly see how the plugin works in the test studio as you migrate code.

4. Create a new major release

When moving a plugin to this monorepo the conventions enforced on the repo typically warrant a new major version:

  • enabling React Compiler
  • Dropping CJS
  • Requiring Sanity Studio v5 as the baseline
pnpm changeset add

When prompted:

  • Select your new package
  • Choose major for the version bump
  • Enter a summary of the changes that are breaking, and other changes that might affect runtime in order to pass linting and strict type checks.

Commit the changeset file with your PR.

5. Update the original repository

After the plugin has been successfully migrated and published from the monorepo, update the original repository to inform users about the move:

  1. Update the README in the original repository to include a notice at the top:

    > **Note:** This repository has been moved to the [sanity-io/plugins](https://github.com/sanity-io/plugins) monorepo.
    >
    > All future development, issues, and releases will be managed there.
    >
    > - New location: `plugins/PLUGIN-NAME` (e.g., `plugins/@sanity/document-internationalization`)
    > - npm package: The package name remains the same
    > - Issues: Please open new issues in the [monorepo](https://github.com/sanity-io/plugins/issues)
  2. Migrate existing issues to the monorepo:

    • Review all open issues in the original repository
    • Add a label matching the plugin name to each issue for organization (example: an issue that was once in the @sanity/color-input repo will have a tag color-input in this repo)
    • Move the issues to the monorepo's issue tracker
    • Update issue references as needed
  3. Archive the repository: Archive the original repository on GitHub to prevent new issues and PRs while keeping the history accessible.

See this example PR for reference.

Publishing Packages

This monorepo uses Changesets for version management and publishing.

Preview Packages in a PR (pkg-pr-new)

You can publish preview versions of changed plugin packages directly from a PR using pkg.pr.new.

How it is triggered

The preview workflow runs on PR events only when the PR has the trigger: preview label.

  1. Open your PR
  2. Add the trigger: preview label
  3. Wait for the Publish workflow (.github/workflows/pkg-pr-new.yml) to finish

What gets preview-published

The workflow detects changed packages from .changeset/*.md files in your PR diff and publishes only matching plugin packages.

  • It ignores .changeset/README.md
  • It supports package names that map to:
    • @sanity/* -> plugins/@sanity/*
    • sanity-plugin-* -> plugins/sanity-plugin-*

If no valid changesets are found, no packages are published.

How to use the preview

After the workflow runs, it posts (or updates) a PR comment titled "Preview this PR with pkg.pr.new" that includes install commands for each published package (for both pnpm and npm).

Use the provided command in another project to test the preview package version, for example:

pnpm install <pkg.pr.new url from the PR comment>

Creating a Changeset

When you make changes that should be released:

pnpm changeset add

Follow the prompts to:

  1. Select the packages that have changed
  2. Choose the version bump type (patch/minor/major)
  3. Write a summary of the changes

This creates a changeset file in .changeset/ that should be committed with your PR.

Release Process

  1. Merge PRs that include changeset files to main
  2. The release workflow automatically creates a "Version Packages" PR that bumps versions and updates changelogs
  3. When the "Version Packages" PR is merged, packages are automatically published to npm with provenance

Commit Guidelines

  • Write clear, descriptive commit messages
  • Reference relevant issues when applicable
  • Keep commits focused on a single change

Questions?

If you have questions or need help, please: