sanity-plugin-air
v0.1.0-alpha.1
Published
Integrate Air to your Sanity Studio.
Readme
sanity-plugin-air
Integrate Air into your Sanity Studio.
Architecture
This plugin uses an iframe architecture
┌─────────────────────────────────────────────────────────┐
│ Sanity Studio │
│ ┌───────────────────────────────────────────────────┐ │
│ │ sanity-plugin-air (this package) │ │
│ │ - Installed in Sanity Studio │ │
│ │ - Renders an iframe │ │
│ │ - Communicates via postMessage │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ <iframe src="sanity-plugin"> │ │ │
│ │ │ ┌─────────────────────────────────────────┐│ │ │
│ │ │ │ @apps/sanity-plugin (Next.js) ││ │ │
│ │ │ │ - Full React app with auth, Tailwind ││ │ │
│ │ │ │ - Uses parent.postMessage() to ││ │ │
│ │ │ │ communicate with this plugin ││ │ │
│ │ │ └─────────────────────────────────────────┘│ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘Features
- Studio Tool: Browse your Air workspace from within Sanity Studio
- Custom Field Type: Use
air.assetfields to reference Air assets in your schemas
Getting Started (Link-Watch only)
Prerequisites
- Node.js >= 18
- A Sanity Studio project (v3) to test the plugin
- Access to this monorepo
One-path setup (3 terminals)
Terminal 1: Plugin watch + link
cd plugins/sanity
yarn install # first time
yarn link-watch # builds, watches, and pushes updates via yalcTerminal 2: Next.js iframe app
cd apps/sanity-plugin
yarn install # first time
yarn dev # runs at http://localhost:3005Terminal 3: Your Sanity Studio
# once per project
yalc add sanity-plugin-air --link
yarn dev # start Studiosanity.config.ts:
import { airPlugin } from 'sanity-plugin-air'
export default defineConfig({
// ...
plugins: [
airPlugin({ workspaceId: 'a valid workspace id' }),
],
})You should now see:
- An "Air" tool in the Studio navigation
Iteration loop
- Edit
plugins/sanity/src/* yarn link-watchrebuilds and pushes automatically- Refresh Studio to see changes
Configuration
airPlugin({
appUrl: 'https://sanity-plugin.air.inc', // URL of the Air app (defaults to localhost:3005)
});Scripts
| Script | Description |
|--------|-------------|
| yarn build | Build the plugin using current .env.local |
| yarn build:dev | Build for local development (localhost:3005) |
| yarn build:qa | Build for QA environment |
| yarn build:prod | Build for production (sanity-plugin.air.inc) |
| yarn dev | Watch mode - rebuilds on file changes |
| yarn link-watch | Watch + push to yalc for live development |
| yarn lint | Run Biome linter |
Environment Configuration
The plugin uses .env.local to configure the Air app URL at build time:
| File | Purpose |
|------|---------|
| .env.local | Active configuration (used by build) |
| .env.local.bak | Development config (localhost:3005) |
| .env.local.qa.bak | QA environment config |
| .env.local.prod.bak | Production config (sanity-plugin.air.inc) |
The build:dev, build:qa, and build:prod scripts automatically copy the appropriate .bak file to .env.local before building.
Important: When publishing to npm, use yarn build:prod to ensure the production URL is baked into the bundle.
Troubleshooting
Plugin not showing in Sanity Studio
- Verify the plugin is installed:
yarn why sanity-plugin-air - Check
sanity.config.tsincludesairPlugin()in the plugins array - Restart Sanity Studio
Iframe shows blank/error
- Ensure
apps/sanity-pluginis running (yarn dev) - Check
appUrlin plugin config matches the running app URL - Check browser console for CORS or other errors
Changes not reflecting
- Ensure
yarn link-watchis running without errors - Hard refresh Sanity Studio (Cmd+Shift+R)
Development Guide
Release Tags (Required)
All exported functions, types, and components must have a JSDoc release tag. The build will fail without them.
/** @public */
export function myPublicFunction() { ... }
/** @public */
export type MyPublicType = { ... }
/** @internal */
export function _internalHelper() { ... }Available tags:
@public- Stable API, part of the public contract@beta- May change in minor versions@internal- Not for external use, prefix with underscore
The pkg-utils build --strict command enforces these tags at build time. If you forget a tag, you'll see an error like:
error: ae-missing-release-tag: "myFunction" is exported but missing a release tagLinting
This package uses Biome for linting and formatting:
yarn lint # Check for issues
yarn biome:check:write # Auto-fix issuesPackage Structure
plugins/sanity/
├── src/
│ ├── index.ts # Main exports (all need @public tags)
│ ├── plugin.tsx # Plugin definition
│ ├── components/ # React components
│ ├── schema/ # Sanity schema definitions
│ ├── types/ # TypeScript types
│ └── utils/ # Utility functions
├── scripts/ # Build scripts (excluded from linting)
├── package.config.ts # pkg-utils configuration
└── biome.json # Linter configurationRelated
apps/sanity-plugin- The Next.js app that runs inside the iframepackages/sanity/constants- Shared constants and types (@air/sanity-constants)plugins/figma- Similar architecture for Figma plugin
License
BSD-3-Clause
