Studio SDK integration, CLI asset uploads and token expiry, and presentation and Vision fixes
Published: August 18, 2026
This release provides the Sanity App SDK out of the box for custom Studio tools, a new CLI asset upload command, token expiry support for the CLI, and fixes numerous bugs including issues with pasting in Vision, Presentation route matching, document layout shifts, and preview loading errors.
Studio now supports zero-config SDK usage
Studio now provides the Sanity App SDK out of the box. If you build custom Studio functionality (tools, panes, custom inputs), you can call App SDK hooks from @sanity/sdk-react directly, without adding your own SanityApp or ResourceProvider:
import {useDocuments} from '@sanity/sdk-react'
function MyTool() {
// resolves project, dataset, and auth from the current Studio workspace automatically
const {data} = useDocuments({/* ... */})
return /* ... */
}Add @sanity/sdk-react to your Studio project's dependencies to import the hooks.
Limitations to be aware of:
- A single shared SDK instance is created per (primary) workspace at the Studio root; hooks reuse it rather than creating their own.
- SDK hooks used inside the Tasks addon dataset subtree resolve against the root workspace instance, not the addon dataset.
- Studios published before Aug 2022 that don't expose a reactive auth token fall back to localStorage/cookie token discovery.
- Because the Studio provides the SDK via
ResourceProviderrather thanSanityApp, the SDK's own login/error UI is not mounted. Authentication is handled by the Studio. Named multi-resource lookups (resourceName) are not registered; hooks resolve the current workspace by default.
Upload assets from the CLI
You can now upload image and file assets to a dataset with the Sanity CLI’s sanity assets upload command. Check the reference docs for specific options, or run the following:
npx sanity@latest assets upload --help
pnpm dlx sanity@latest assets upload --help
yarn dlx sanity@latest assets upload --help
bunx sanity@latest assets upload --help
sanity tokens now supports expiry options
The sanity tokens create command adds the ability to set expiry dates, just like you can in sanity.io/manage.
npx sanity@latest tokens create --expires-at '2027-01-01T12:00:00Z'
pnpm dlx sanity@latest tokens create --expires-at '2027-01-01T12:00:00Z'
yarn dlx sanity@latest tokens create --expires-at '2027-01-01T12:00:00Z'
bunx sanity@latest tokens create --expires-at '2027-01-01T12:00:00Z'
Use an ISO 8601 date or timestamp format. Expiration times are also now available from the sanity tokens list command.
🐛 Notable bugfixes and improvements
- Pin
@sanity/eslint-config-studioto^6in thesanity initstudio and SDK app templates, so scaffolded projects resolve against theeslint@^9they also pin instead of failing withERESOLVE. - The
deploycommand now shows schema extraction errors during studio deploy. - The
migrationscommand now preserves progress counts and transaction log URLs on failure. - The
devcommand will now announce the pre-claim Studio sign-in URL (#token=) only for locally unclaimed projects created with sanity.new. - The CLI will now keep table output within the terminal width. CLI tables now wrap long values instead of truncating content and preserve borders when Unicode width estimates differ.
- Synced Shopify metafields now show in the Shopify templates.
- Replace Sign out with Claim this project for unclaimed projects opened through
sanity newin development. - Automatically redirect users to Studio login after they claim a provisioned project.
- Fixes a bug where having the Vision tool open prevented pasting into other fields in the Studio, such as the global search field in the navbar.
- Presentation's
mainDocumentsroute matching is now backed by the web-standardURLPatternAPI instead ofpath-to-regexpv8. Route patterns written forpath-to-regexpv6, such as custom regexp params like/:prefix(.*)/course/:slugor/:locale(en|no|se)/blog/:slug, optional (:slug?) and repeated (:path*,:slug+) params, work again and the v8 wildcard syntax (/*prefix/course/:slug) also keeps working. In browsers without nativeURLPatternsupport a polyfill is loaded on demand. One caveat for configs written forpath-to-regexpv8: a{…}group without a modifier is required again (as it was in v6). If you relied on/books{/:id}matching/books, write/books{/:id}?instead. - When a document has no document actions, the Manage versions button in the document footer still appears if versions exist. The Publish/overflow action buttons stay hidden when there is nothing to show.
- Fixes a horizontal layout shift in the object editing dialog when switching between field group tabs: the dialog now reserves space for the scrollbar so content stays put. Only affected setups with always-visible scrollbars (e.g., Windows).
- Fixes an issue where using the “Copy field” action on a field nested inside an array item (for example in a page-builder array) and pasting it into the equivalent field of another document failed with the error "Source and target schema types are not compatible".
- Hide the unclaimed-project nudge after its claim period ends.
- Improve contrast and assistive technology behavior in the unclaimed-project Studio nudge.
- If a Presentation preview never finishes loading, the studio now shows a connection error with a retry option after 15 seconds instead of an endless loading spinner. The most common cause is a Next.js 16.2.x dev server previewed in Firefox, which enters an infinite reload loop. If you experience this issue, please upgrade to Next.js 16.3.0, or set
experimental: {reactDebugChannel: false}innext.config.