Conversation
Contributor
📦 Bundle Stats —
|
| Metric | Value | vs main (3848089) |
|---|---|---|
| Internal (raw) | 2.2 KB | -450 B, -16.5% |
| Internal (gzip) | 838 B | -218 B, -20.6% |
| Bundled (raw) | 11.16 MB | +1.1 KB, +0.0% |
| Bundled (gzip) | 2.10 MB | +230 B, +0.0% |
| Import time | 791ms | +5ms, +0.6% |
bin:sanity
| Metric | Value | vs main (3848089) |
|---|---|---|
| Internal (raw) | 782 B | - |
| Internal (gzip) | 423 B | - |
| Bundled (raw) | 9.87 MB | - |
| Bundled (gzip) | 1.78 MB | - |
| Import time | 2.05s | -3ms, -0.1% |
🗺️ View treemap · Artifacts
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
📦 Bundle Stats — @sanity/cli-core
Compared against main (38480893)
| Metric | Value | vs main (3848089) |
|---|---|---|
| Internal (raw) | 105.5 KB | - |
| Internal (gzip) | 25.8 KB | - |
| Bundled (raw) | 21.72 MB | - |
| Bundled (gzip) | 3.46 MB | - |
| Import time | 701ms | +3ms, +0.4% |
🗺️ View treemap · Artifacts
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
📦 Bundle Stats — create-sanity
Compared against main (38480893)
| Metric | Value | vs main (3848089) |
|---|---|---|
| Internal (raw) | 908 B | - |
| Internal (gzip) | 483 B | - |
| Bundled (raw) | 931 B | - |
| Bundled (gzip) | 491 B | - |
| Import time | ❌ ChildProcess denied: node | - |
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
Contributor
Preview this PR with pkg.pr.newRun the Sanity CLInpx https://pkg.pr.new/sanity-io/cli/@sanity/cli@71d7eac <command>...Or upgrade project dependencies📦
|
Contributor
Coverage Delta
Comparing 15 changed files against main @ Overall Coverage
|
2f17943 to
1171cf3
Compare
unstable_defineMediaLibrary and the configs declaration familyunstable_defineMediaLibrary
6ae0e06 to
ed8da3c
Compare
08a446d to
63435cb
Compare
63435cb to
ad9ff83
Compare
a418e8f to
6591862
Compare
ad9ff83 to
d59fddb
Compare
1 task
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 19b6020. Configure here.
gu-stav
commented
Jul 3, 2026
Member
Author
There was a problem hiding this comment.
Mostly renamed from interfaceSetId.ts, because an installation config isn't an interface but fits into the same model to calculate HMR changes too.
…aration family Media Library needs per-org custom fields, and in Brett's model those are installation configs — a versioned snapshot on an org's app installation, not interfaces registered with the application service. An installation has one active config, so an app declares at most one (rejected otherwise). unstable_defineApp grows generic primitives: an isSingleton flag and a configs list — a discriminated union of installation configs, with media-library (an object carrying a fields array) the only member today. unstable_defineMediaLibrary is sugar: isSingleton, fixed name/title, and all fields collected into that single media-library config. Configs ride the existing federation build and dev plumbing: the fields compile into one self-accepting HMR module exposed as ./configs/media-library, and the config shows up on the dev-server registry (interface_type: media-library) so the workbench shell sees it over the existing websocket channel. Deploy validates and logs the installation-config payload only — Brett's endpoint isn't wired yet.
…ations A config-only singleton isn't an app, so a media-library dev server no longer registers as a local application. Its installation config travels on an installationConfigs channel next to the applications in the HMR payload.
… moduleName Tag the config by `type` with `config` as the payload, and send the app's `unstable_defineApp` name as `moduleName` plus its origin as `remoteURL`, so the workbench loads the config module without reconstructing the remote name or URL from host and port.
…config ready The dev-server registry carries `installationConfigs` (an array — an app may expose more than one), and a singleton is flagged with `isSingleton` rather than a `media-library` dev-server type. The wire routes config-only singletons to the installationConfigs channel by that flag.
moduleName is only read when loading a config's live values, so it lives on the installationConfigs entries rather than as a top-level registry field that every studio/app carried but never used.
… flag A dev server is a local application unless it's config-only — an installation config with no interfaces. A config that also exposes interfaces is both a local app and an installation config. Drop the `isSingleton` registry field: routing is by what a server exposes, not whether it's a singleton.
… config generic Derive the dev-manifest-watcher extract return from ManifestPatch instead of re-listing its fields. Keep the installation-config wire projection payload- agnostic (spread whatever remains after the discriminator and transport), since `fields` is the media-library payload and other config types will differ.
…pt from the catalog Pinning `sanity: workbench` pulled a second copy of the Studio dependency tree (the portable-text editor and its plugins) into the lockfile. Use `catalog:` for `sanity` and `typescript`, like the rest of the workspace, so the fixture shares the existing versions.
`exposesSetId` used a fixed token for the installation config, so editing `fields` in `sanity.cli.ts` (add or rename) during dev kept the same expose-set id — the watcher patched the wire metadata but skipped the rebuild, leaving the build-baked config module stale. Key the id on each field, like interfaces, so a field change takes the rebuild path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

unstable_defineMediaLibrarydeclares the Sanity Media Library as a workbench app — a singleton whose customfieldsbecome an installation config.Design decisions
defineFieldvalue can't serialize, so only its metadata rides the wire (and deploys); the live value loads from the app's federation module. The workbench merges the two halves.appType.fieldsis the media-library payload; the shape is a union, so other config types can be added without reworking the pipeline.installationConfigsstream, separate from local applications. A dev server is a local app unless it's config-only (a config with no interfaces); one with interfaces too is both.Workbench half: sanity-io/workbench#267.
Note
Medium Risk
Touches workbench build/dev/deploy and federation expose semantics; deploy persistence is intentionally stubbed, so behavior depends on the paired workbench change.
Overview
Introduces
unstable_defineMediaLibraryas sugar overunstable_defineApp, which now accepts optionalinstallationConfigand internalisSingleton. Media library apps are fixed singletons (media-library) whose customfieldsbecome a discriminatedmedia-libraryinstallation config.Build & federation: Installation configs generate a federation module (
./configs/installation_config) that aggregates field metadata and livedefineFieldimports; build and devexposesnow includeinstallationConfigalongside views and services.Dev: Registry entries carry
installationConfigsseparately from interfaces; the workbench HMR payload splitsapplicationsvsinstallationConfigs(config-only servers skip the apps list). Interface-set tracking is generalized toexposesSetIdso adding/renaming config fields triggers remote rebuilds while title/public edits do not.Deploy:
assertDeployabletreats installation config as deployable content; deploy validates and logs the installation-config payload but does not persist it yet.@sanity/clire-exports the new API; afixtures/media-libraryexample and tests cover schemas, artifacts, and routing.Reviewed by Cursor Bugbot for commit 71d7eac. Bugbot is set up for automated code reviews on this repo. Configure here.