一键导入
plugin-transfer
Guides agents through migrating an existing plugin into this monorepo with the copy-plugin generator workflow.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Guides agents through migrating an existing plugin into this monorepo with the copy-plugin generator workflow.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Anti-patterns and best practices for building Sanity Studio plugins in this monorepo. Use when writing, reviewing, or refactoring plugin code under plugins/ — especially for styling/CSS, component performance, and runtime cost. Triggers on vanilla-extract, raw <style> tags, styled-components, theming, inline styles, or questions about how plugins should be structured here.
Vite build tool configuration, plugin API, SSR, and Vite 8 Rolldown migration. Use when working with Vite projects, vite.config.ts, Vite plugins, or building libraries/SSR apps with Vite.
Explains the dev/test-studio Script Runner tool. Use when adding, editing, running, or documenting scripts in dev/test-studio/src/script-runner, or when the user mentions the Scripts tool, Studio runner scripts, script variables, or browser-side Sanity Studio scripts.
Turborepo monorepo build system guidance. Triggers on: turbo.json, task pipelines, dependsOn, caching, remote cache, the "turbo" CLI, --filter, --affected, CI optimization, environment variables, internal packages, monorepo structure/best practices, and boundaries. Use when user: configures tasks/workflows/pipelines, creates packages, sets up monorepo, shares code between apps, runs changed/affected packages, debugs cache, or has apps/packages directories.
Detect and update legacy GROQ patterns where language is read from _key for sanity-plugin-internationalized-array when users mention v4 to v5 migration, or @sanity/document-internationalization from v5 to v6. GROQ query updates, localized arrays, or patterns like `_key == "en"` and `_key == $language`.
| name | plugin-transfer |
| description | Guides agents through migrating an existing plugin into this monorepo with the copy-plugin generator workflow. |
Use this skill when migrating an existing plugin repository into sanity-io/plugins.
Always start with:
pnpm generate "copy plugin"
This is the canonical transfer flow and scaffolds monorepo-compatible files and test-studio wiring.
Do not keep migration TODOs in the repo. If the generator creates README.todo.md, delete it after moving its contents into the transfer PR description. Maintainers can update PR checklists directly on GitHub without a code change.
Keep and maintain these monorepo config files in the transferred plugin:
package.jsontsdown.config.tstsconfig.jsonvitest.config.tsDo not copy standalone-repo-only setup such as custom root CI/build/lint/test configs that are already handled by this monorepo.
The original README.md is preserved, but old standalone-repo content is almost always stale in the monorepo. Remove or rewrite the following before opening the PR:
## Develop & test (typically references @sanity/plugin-kit) and ### Release new version (references the original repo's GitHub Actions / semantic-release). The monorepo handles building, testing, and releasing centrally, so these instructions are wrong here.v2 - legacy to disambiguate a legacy line—and usually omit it entirely.Keep the substance that is still accurate: intro/description, screenshots, acknowledgements, install, usage, configuration, and license sections.
README.md in the new plugin workspace, but clean it up (see Clean Up the Transferred README).LICENSE from the original repository when it credits authors beyond Sanity.io alone (the copy-plugin generator deletes it during cleanup). If kept, update the copyright year(s) to the current year.dev/test-studio/src/<plugin-example>/index.tsx.dev/test-studio/sanity.config.ts..github/CODEOWNERS during transfer unless explicitly requested.README.md plugins table with the transferred plugin.Run these commands in order. All must pass or CI will fail:
# 1. Format code
pnpm format
# 2. Check for unused exports, dependencies, and catalog entries
pnpm knip
# 3. Run linters (includes TypeScript type checking)
pnpm lint
# 4. Build all packages
pnpm build
# 5. Run tests
pnpm test run
The copy-plugin generator adds a workspace entry to knip.jsonc. After transfer, fix any knip issues in the plugin:
Catalog warnings for dev/* workspaces (e.g. @sanity/vision used only by dev/test-studio) are expected—the root knip.jsonc sets "catalog": "warn" for those.
Transferred plugins may carry legacy patterns that fail monorepo lint rules. Fix what you can; for remaining issues in legacy src/ or test/ code, add targeted .oxlintrc.json overrides or ignorePatterns rather than disabling rules repo-wide.
Common legacy fixes:
createRequire / require() with ESM import (add "resolveJsonModule": true to the plugin tsconfig.json for JSON imports).import.meta.url with fileURLToPath instead of __dirname in tests.eslint-disable comments that oxlint reports as unused.sanity peer variants break type-aware lintType-aware lint can fail (sometimes intermittently, especially on cold installs) with errors like Type 'import(".../.pnpm/sanity@X_<hashA>/...").D' is not assignable to type 'import(".../.pnpm/sanity@X_<hashB>/...").D' in dev/test-studio/src/** examples. This happens when the transferred plugin resolves sanity to a different pnpm peer-variant than the other plugins, creating an extra duplicate copy of sanity's type definitions.
To keep the plugin on the shared sanity variant, declare these in the plugin devDependencies:
"@types/node": "catalog:""styled-components": "catalog:" (when the plugin depends on @sanity/ui, which peers on styled-components; without the declaration pnpm auto-installs the peer and bypasses the workspace @sanity/styled-components override)Verify alignment by checking that the plugin importer's sanity version string in pnpm-lock.yaml matches other plugins (e.g. plugins/@sanity/sfcc).
Do not migrate styling during a transfer. When the plugin already uses
styled-components, leave it in place for the initial port — the goal is a faithful, low-risk move.styled-componentsis still migrated to vanilla-extract (the styling target for every plugin), but in a separate follow-up PR, done with care to preserve visual fidelity and avoid regressions. Thestyled-components: catalog:alignment above applies until then. See thesanity-plugin-best-practicesstyling reference (Migrating off styled-components).
Vitest runs against built dist/ output (pretest builds packages automatically). Fix path resolution and module import issues in legacy test files. The plugin's own test/ suite (if present) runs via the root vitest config when included in the plugin workspace.
Every transferred plugin needs a major changeset. Compare the transferred plugin's package.json (peer dependencies, engines, exports, and build config) against the last published version on npm. Do not copy a template blindly—only list breaking changes that actually apply.
Because the transfer PR is opened by someone else (often the 🤖 bot), the generated release would otherwise thank the wrong person. Add an author: directive so the changelog credits the people who actually built the plugin. Multiple author: lines are supported, so list everyone who worked on the plugin being ported — not just the latest author — so they all get their thanks in the release notes.
@ (e.g. author: @stipsan).author: line on its own line, before the summary text. The lines are stripped from the rendered changelog.package.json author/contributors, and the README acknowledgements.---
'package-name': major
---
author: @stipsan
author: @rexxars
Port PACKAGE-NAME to the Sanity plugins monorepo
This produces a release line thanking each contributor:
Thanks @stipsan, @rexxars! - Port PACKAGE-NAME to the Sanity plugins monorepo
See AGENTS.md → Crediting Original Authors for the full rationale.
Use this format (add the author: lines from Credit every contributor above the summary):
---
'package-name': major
---
author: @stipsan
author: @rexxars
Port PACKAGE-NAME to the Sanity plugins monorepo
This major release includes several breaking changes as part of the migration to the monorepo:
- **React Compiler enabled**: ...
- **ESM-only**: CommonJS support has been removed. The package now ships only ESM
- **React 19.2+ required**: ...
- **Sanity Studio v5+ required**: ...
- **Node.js 20.19+ required**: ...
Include additional bullets only when they apply to the plugin—for example:
Example for sanity-naive-html-serializer:
---
'sanity-naive-html-serializer': major
---
author: @stipsan
author: @rexxars
Port sanity-naive-html-serializer to the Sanity plugins monorepo
This major release includes several breaking changes as part of the migration to the monorepo:
- **React Compiler enabled**: The package is now built with React Compiler targeting React 19
- **ESM-only**: CommonJS support has been removed. The package now ships only ESM
- **React 19.2+ required**: Minimum React version is now 19.2 (previously ^18.3 || ^19)
- **react-dom 19.2+ required**: `react-dom` is now a required peer dependency
- **Sanity Studio v5+ required**: Minimum Sanity version is now v5 (Sanity v3 and v4 are no longer supported)
- **Node.js 20.19+ required**: Minimum Node.js version is now 20.19 (previously >=18)
Put all pending transfer work in the PR description as unchecked checkboxes. Do not create README.todo.md or similar todo files in the plugin workspace—the maintainer should be able to check items off on GitHub without opening a PR to edit repo files.
Include these sections in every transfer PR:
npm trust github <package-name> --file=release.yml --repository=sanity-io/pluginspackage.json dependencies/peerDependencies/exports verified against original repoLICENSE restored with updated copyright year when the original credits authors beyond Sanity.io alonepnpm dev)pnpm format, pnpm knip, pnpm lint, pnpm build, pnpm test run all passAgents cannot complete these steps themselves. Ask the maintainer to handle them:
<link to readme>) and replace it with: # [This plugin has moved](<new location>)<plugin-name><repo link>/settingsExample for sanity-naive-html-serializer:
# [This plugin has moved](https://github.com/sanity-io/plugins/tree/main/plugins/sanity-naive-html-serializer)naive-html-serializerstyled-components plugin on styled-components for the initial port; defer any vanilla-extract migration to a follow-up PR (see the styling note above).pnpm build and pnpm dev.pnpm dev to manually verify the test-studio example after the automated checks pass.