Skip to content

chore(deps): update dependency next-sanity to v12#1784

Open
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/major-12-app-dependencies
Open

chore(deps): update dependency next-sanity to v12#1784
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/major-12-app-dependencies

Conversation

@renovate
Copy link
Copy Markdown
Contributor

@renovate renovate Bot commented Jan 26, 2026

ℹ️ Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Change Age Confidence
next-sanity (source) 10.1.112.4.5 age confidence

Release Notes

sanity-io/next-sanity (next-sanity)

v12.4.5

Compare Source

Patch Changes
  • 9446c27 Thanks @​stipsan! - Fix a regression introduced in v12.4.0 (#​3430) that lead to live preview sometimes failing to refresh and show draft content automatically

12.4.4

Patch Changes

12.4.3

Patch Changes
TypeGen-aware Portable Text components

<PortableText> now infers the shape of every component handler from the value prop. When you pass a value typed by Sanity TypeGen, components.types, components.marks, components.block, components.list, and components.listItem all receive precise value props for the exact content the query returned.

Three new utility types ship with this feature:

  • InferComponents<T> - same inference as the inline components prop, for hoisting components out of JSX.
  • InferStrictComponents<T> - strict variant that requires a handler for every inferred custom type, mark, block style, and list style, and rejects handlers that aren't in the schema (and therefore not visible to TypeGen).
  • InferValue<T> - derives a Portable Text array value type from any TypeGen query result type, useful for re-usable wrapper components.
Schema

Every example below assumes the same sanity.config.ts:

// sanity.config.ts
"use client";
import {
  defineArrayMember,
  defineConfig,
  defineField,
  defineType,
} from "sanity";

export default defineConfig({
  name: "default",
  projectId: "abc123",
  dataset: "production",
  schema: {
    types: [
      defineType({
        name: "post",
        type: "document",
        fields: [
          defineField({ name: "title", type: "string" }),
          defineField({
            name: "content",
            type: "array",
            of: [
              defineArrayMember({ type: "block" }),
              defineArrayMember({
                type: "image",
                options: { hotspot: true },
                fields: [defineField({ name: "alt", type: "string" })],
              }),
            ],
          }),
        ],
      }),
    ],
  },
});
Before: hand-typing handlers

Previously, every handler had to be typed by hand to mirror the generated query shape:

// app/[slug]/page.tsx
import { createImageUrlBuilder } from "@&#8203;sanity/image-url";
import {
  createClient,
  defineQuery,
  defineLive,
  PortableText,
} from "next-sanity";
import { Image } from "next-sanity/image";
import { notFound } from "next/navigation";

const client = createClient({
  projectId: "abc123",
  dataset: "production",
  useCdn: true,
  apiVersion: "2026-05-04",
});
const builder = createImageUrlBuilder(client);
const { sanityFetch } = defineLive({ client });

export default async function Page({ params }: PageProps<"/[slug]">) {
  const { slug } = await params;
  const query = defineQuery(
    `*[_type == "post" && slug.current == $slug][0]{title,content}`
  );
  const { data } = await sanityFetch({ query, params: { slug } });

  if (!data) return notFound();

  return (
    <article>
      <h1>{data.title}</h1>
      <PortableText
        components={{
          types: {
            image: ({
              value,
            }: {
              value: {
                asset?: {
                  _ref: string;
                  _type: "reference";
                  _weak?: boolean;
                };
                hotspot?: {
                  _type: "sanity.imageHotspot";
                  x?: number;
                  y?: number;
                  height?: number;
                  width?: number;
                };
                crop?: {
                  _type: "sanity.imageCrop";
                  top?: number;
                  bottom?: number;
                  left?: number;
                  right?: number;
                };
                alt?: string;
                _type: "image";
                _key: string;
              };
            }) => (
              <Image
                src={builder.image(value).url()}
                alt={value.alt || ""}
                fill
                sizes="100vw"
                style={{ objectFit: "cover" }}
              />
            ),
          },
        }}
        value={data.content}
      />
    </article>
  );
}
After: automatic inference

Now the same handler is fully typed straight from data.content:

// app/[slug]/page.tsx
import { createImageUrlBuilder } from "@&#8203;sanity/image-url";
import {
  createClient,
  defineQuery,
  defineLive,
  PortableText,
} from "next-sanity";
import { Image } from "next-sanity/image";
import { notFound } from "next/navigation";

const client = createClient({
  projectId: "abc123",
  dataset: "production",
  useCdn: true,
  apiVersion: "2026-05-04",
});
const builder = createImageUrlBuilder(client);
const { sanityFetch } = defineLive({ client });

export default async function Page({ params }: PageProps<"/[slug]">) {
  const { slug } = await params;
  const query = defineQuery(
    `*[_type == "post" && slug.current == $slug][0]{title,content}`
  );
  const { data } = await sanityFetch({ query, params: { slug } });

  if (!data) return notFound();

  return (
    <article>
      <h1>{data.title}</h1>
      <PortableText
        components={{
          types: {
            // value is fully typed from the query result, no annotation needed
            image: ({ value }) => (
              <Image
                src={builder.image(value).url()}
                alt={value.alt || ""}
                fill
                sizes="100vw"
                style={{ objectFit: "cover" }}
              />
            ),
          },
        }}
        value={data.content}
      />
    </article>
  );
}
InferComponents: hoisting components without losing inference

Move the components map out of JSX and keep the same inferred handler types:

// app/[slug]/page.tsx
import { createImageUrlBuilder } from "@&#8203;sanity/image-url";
import {
  createClient,
  defineQuery,
  defineLive,
  PortableText,
  type InferComponents,
} from "next-sanity";
import { Image } from "next-sanity/image";
import { notFound } from "next/navigation";

const client = createClient({
  projectId: "abc123",
  dataset: "production",
  useCdn: true,
  apiVersion: "2026-05-04",
});
const builder = createImageUrlBuilder(client);
const { sanityFetch } = defineLive({ client });

export default async function Page({ params }: PageProps<"/[slug]">) {
  const { slug } = await params;
  const query = defineQuery(
    `*[_type == "post" && slug.current == $slug][0]{title,content}`
  );
  const { data } = await sanityFetch({ query, params: { slug } });

  if (!data) return notFound();

  const components = {
    types: {
      image: ({ value }) => (
        <Image
          src={builder.image(value).url()}
          alt={value.alt || ""}
          fill
          sizes="100vw"
          style={{ objectFit: "cover" }}
        />
      ),
    },
  } satisfies InferComponents<typeof data.content>;

  return (
    <article>
      <h1>{data.title}</h1>
      <PortableText components={components} value={data.content} />
    </article>
  );
}
InferStrictComponents + InferValue: a strict, re-usable wrapper

InferValue<SanityQueries[keyof SanityQueries]> collects every Portable Text item shape from every registered TypeGen query into an array value type, and InferStrictComponents requires a handler for each of them. Together they're perfect for a single CustomPortableText you reuse across the app:

// app/[slug]/page.tsx
import { createImageUrlBuilder } from "@&#8203;sanity/image-url";
import {
  createClient,
  defineQuery,
  defineLive,
  PortableText,
  type SanityQueries,
  type InferValue,
  type InferStrictComponents,
} from "next-sanity";
import { Image } from "next-sanity/image";
import { notFound } from "next/navigation";

const client = createClient({
  projectId: "abc123",
  dataset: "production",
  useCdn: true,
  apiVersion: "2026-05-04",
});
const builder = createImageUrlBuilder(client);
const { sanityFetch } = defineLive({ client });

function CustomPortableText({
  value,
}: {
  // Array value type for every Portable Text item shape across all registered queries.
  value: InferValue<SanityQueries[keyof SanityQueries]>;
}) {
  const components = {
    types: {
      image: ({ value }) => (
        <img src={builder.image(value).url()} alt={value.alt || ""} />
      ),
    },
  } satisfies InferStrictComponents<typeof value>;
  //   ^ TypeScript errors when the schema gains a custom type, mark, or list
  //     style without a matching handler defined here

  return <PortableText components={components} value={value} />;
}

export default async function Page({ params }: PageProps<"/[slug]">) {
  const { slug } = await params;
  const query = defineQuery(
    `*[_type == "post" && slug.current == $slug][0]{title,content}`
  );
  const { data } = await sanityFetch({ query, params: { slug } });

  if (!data) return notFound();

  return (
    <article>
      <h1>{data.title}</h1>
      {Array.isArray(data.content) && (
        <CustomPortableText value={data.content} />
      )}
    </article>
  );
}

12.4.2

Patch Changes

12.4.1

Patch Changes

12.4.0

Minor Changes
  • #​3430 aa519e0 Thanks @​stipsan! - Change <VisualEditing>'s default refresh behavior for document mutations to only call router.refresh(), and no longer call revalidatePath('/', 'layout') by default.

    Technically this is a breaking change for apps relying on the previous default root layout revalidation. However, because of the Next.js regression reported by Sanity to Vercel in vercel/next.js#93210, we feel strongly that the default behavior in <VisualEditing> on document mutations needs to avoid revalidatePath('/', 'layout'): calling it worsens the impact of the regression by causing many CACHE: REVALIDATED events, which can massively increase ISR Writes.

    The previous behavior can be restored by providing a custom refresh prop to <VisualEditing> that calls revalidatePath('/', 'layout'):

    import { draftMode } from "next/headers";
    import { refresh, revalidatePath } from "next/cache";
    import { VisualEditing } from "next-sanity/visual-editing";
    
    export default async function RootLayout({
      children,
    }: {
      children: React.ReactNode;
    }) {
      const { isEnabled: isDraftMode } = await draftMode();
      return (
        <html lang="en">
          <body>
            {children}
            {isDraftMode && (
              <VisualEditing
                refresh={async function refreshVisualEditing(payload) {
                  "use server";
                  switch (payload.source) {
                    // When clicking the refresh button manually in Presentation Tool we purge the cache
                    case "manual":
                      return revalidatePath("/", "layout");
                    // When a document is edited we just refresh
                    case "mutation":
                      return refresh();
                    default:
                      throw new Error("Unknown refresh source", {
                        cause: payload,
                      });
                  }
                }}
              />
            )}
          </body>
        </html>
      );
    }
  • #​3432 45b164b Thanks @​stipsan! - Change <SanityLive />'s default revalidateSyncTags behavior so draft mode revalidates affected Sanity tags with revalidateTag(tag, 'max'), instead of expiring them immediately with revalidateTag(tag, {expire: 0}).

    Technically this is a breaking change for apps relying on the previous immediate tag expiry behavior. However, because of the Next.js regression reported by Sanity to Vercel in vercel/next.js#93210, we feel strongly that the default behavior in <SanityLive /> needs to avoid revalidateTag(tag, {expire: 0}) in draft mode: calling it worsens the impact of the regression by causing many CACHE: REVALIDATED events, which can massively increase ISR Writes.

    The previous behavior can be restored by providing a custom revalidateSyncTags prop to <SanityLive />:

    import type { SyncTag } from "@&#8203;sanity/client";
    import { revalidateTag } from "next/cache";
    
    import { SanityLive } from "@&#8203;/sanity/live";
    
    async function revalidateSyncTags(tags: SyncTag[]): Promise<void> {
      "use server";
    
      revalidateTag("sanity:fetch-sync-tags", "max");
    
      for (const _tag of tags) {
        revalidateTag(`sanity:${_tag}`, { expire: 0 });
      }
    }
    
    export default function RootLayout({
      children,
    }: {
      children: React.ReactNode;
    }) {
      return (
        <html lang="en">
          <body>
            {children}
            <SanityLive revalidateSyncTags={revalidateSyncTags} />
          </body>
        </html>
      );
    }
  • #​3433 df0eb01 Thanks @​stipsan! - Disallow using defineLive when cacheComponents: true is enabled.

    Technically this is a breaking change for apps that currently combine defineLive with Next.js Cache Components. However, this configuration is not supported and can cause problems that are difficult to detect, so it is better to fail early until #​3109 lands.

Patch Changes
  • #​3430 aa519e0 Thanks @​stipsan! - Improve lazy loading of <SanityLive>, if not rendered it won't add <SanityLiveClientComponent /> to the bundle`

  • #​3430 aa519e0 Thanks @​stipsan! - Improve lazy loading of <VisualEditing>, if not rendered it won't increase the browser bundle

12.3.5

Patch Changes

12.3.4

Patch Changes

12.3.3

Patch Changes
  • #​3419 b2f026b Thanks @​copilot-swe-agent! - Removed the experimental SanityLiveStream export from defineLive. While this is technically a breaking change, it does not follow semver as it was an experimental, undocumented API marked as @alpha. We will return with a different implementation in the future, once we've found an approach that works well with Next.js v16 and cache components.

12.3.2

Patch Changes

12.3.1

Patch Changes

12.3.0

Minor Changes
  • #​3368 f2832eb Thanks @​adoprog! - feat(live): add waitFor option to <SanityLive> to defer events until a Sanity Function has processed them
Patch Changes

12.2.2

Patch Changes

12.2.1

Patch Changes

12.2.0

Minor Changes

[!WARNING]
This is a breaking change if you were using this implementation. Upgrade to next-sanity@cache-components if you want to continue testing the cache components implementation or wait for the stable release.

Patch Changes

12.1.6

Patch Changes

12.1.5

Patch Changes
  • #​3335 71e609a Thanks @​stipsan! - Stop using ['sanity'] as the default fallback when sanityFetch does not specify custom tags

12.1.4

Patch Changes

12.1.3

Patch Changes

12.1.2

Patch Changes

12.1.1

Patch Changes

12.1.0

Minor Changes
Patch Changes

12.0.17

Patch Changes

12.0.16

Patch Changes

12.0.15

Patch Changes

12.0.14

Patch Changes

12.0.13

Patch Changes

12.0.12

Patch Changes

12.0.11

Patch Changes

12.0.10

Patch Changes

12.0.9

Patch Changes

12.0.8

Patch Changes

12.0.7

Patch Changes

12.0.6

Patch Changes

12.0.5

Patch Changes

12.0.4

Patch Changes

12.0.3

Patch Changes

12.0.2 (2025-12-18)

Bug Fixes
  • stop shipping src folder to npm (ec9956d)

12.0.1 (2025-12-17)

Bug Fixes

12.0.0 (2025-12-16)

⚠ BREAKING CHANGES
Features
Bug Fixes
Miscellaneous Chores

11.6.12 (2025-12-16)

Bug Fixes

11.6.11 (2025-12-15)

Bug Fixes

11.6.10 (2025-11-26)

Bug Fixes

11.6.9 (2025-11-25)

Bug Fixes

11.6.8 (2025-11-19)

Bug Fixes

11.6.7 (2025-11-17)

Bug Fixes

11.6.6 (2025-11-11)

Bug Fixes

11.6.5 (2025-11-05)

Bug Fixes

11.6.4 (2025-11-03)

Bug Fixes

11.6.3 (2025-10-31)

Bug Fixes

11.6.2 (2025-10-24)

Bug Fixes
  • experimental/live: QueryParams cannot be a promise (171dc2f)

11.6.1 (2025-10-24)

Bug Fixes
  • experimental/live: QueryParams cannot be a promise (e307fdd)

11.6.0 (2025-10-24)

Features

11.5.7 (2025-10-23)

Bug Fixes
  • handle revalidateTag warning on v16 (2023512)

11.5.6 (2025-10-21)

Bug Fixes

11.5.5 (2025-10-16)

Bug Fixes

11.5.4 (2025-10-16)

Bug Fixes

11.5.3 (2025-10-16)

Bug Fixes

11.5.2 (2025-10-16)

Bug Fixes

11.5.1 (2025-10-15)

Bug Fixes

11.5.0 (2025-10-15)

Features

11.4.2 (2025-09-26)

Bug Fixes
  • deps: update sanity monorepo to ^4.10.1 (main) (#​2840) (91024f1)
  • experimental: ensure server-only import at the top (f1faca8)

11.4.1 (2025-09-25)

Bug Fixes
  • **expe

Note

PR body was truncated to here.


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • "before 3am on Monday"
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate using a curated preset maintained by Sanity. View repository job log here

@vercel
Copy link
Copy Markdown

vercel Bot commented Jan 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
preview-kit-next-app-router Error Error May 12, 2026 3:39pm
preview-kit-next-pages-router Error Error May 12, 2026 3:39pm
preview-kit-remix Ready Ready Preview, Comment May 12, 2026 3:39pm
preview-kit-test-studio Ready Ready Preview, Comment May 12, 2026 3:39pm

Request Review

@socket-security
Copy link
Copy Markdown

socket-security Bot commented Jan 29, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatednpm/​@​types/​react@​19.2.9 ⏵ 19.2.14100 +110079 +188100
Updatednpm/​isbot@​5.1.33 ⏵ 5.1.4010010010095 +2100
Updatednpm/​next-sanity@​10.1.1 ⏵ 12.4.59910010098 -2100

View full report

@renovate renovate Bot force-pushed the renovate/major-12-app-dependencies branch from a844c00 to 11d583d Compare February 17, 2026 18:39
@renovate renovate Bot force-pushed the renovate/major-12-app-dependencies branch from 11d583d to 56e97e8 Compare March 5, 2026 18:08
@renovate renovate Bot force-pushed the renovate/major-12-app-dependencies branch from 56e97e8 to e864d55 Compare March 6, 2026 15:20
@renovate renovate Bot force-pushed the renovate/major-12-app-dependencies branch from e864d55 to 755de5b Compare March 13, 2026 16:01
@renovate renovate Bot force-pushed the renovate/major-12-app-dependencies branch from 755de5b to a31fe6f Compare March 17, 2026 15:34
@socket-security
Copy link
Copy Markdown

socket-security Bot commented Mar 19, 2026

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm @vercel/stega is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: pnpm-lock.yamlnpm/next-sanity@12.4.5npm/@vercel/stega@1.1.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@vercel/stega@1.1.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants