@@ -4,11 +4,13 @@ import path from 'node:path'
4
4
5
5
import { type DatasetAclMode , type SanityProject } from '@sanity/client'
6
6
import { type Framework } from '@vercel/frameworks'
7
+ import { type detectFrameworkRecord } from '@vercel/fs-detectors'
7
8
import dotenv from 'dotenv'
8
9
import execa , { type CommonOptions } from 'execa'
9
10
import { deburr , noop } from 'lodash'
10
11
import pFilter from 'p-filter'
11
12
import resolveFrom from 'resolve-from'
13
+ import semver from 'semver'
12
14
import { evaluate , patch } from 'silver-fleece'
13
15
import which from 'which'
14
16
@@ -55,6 +57,7 @@ import {
55
57
promptForNextTemplate ,
56
58
promptForStudioPath ,
57
59
} from './prompts/nextjs'
60
+ import { readPackageJson } from './readPackageJson'
58
61
import { reconfigureV2Project } from './reconfigureV2Project'
59
62
import templates from './templates'
60
63
import {
@@ -110,7 +113,9 @@ export interface ProjectOrganization {
110
113
// eslint-disable-next-line max-statements, complexity
111
114
export default async function initSanity (
112
115
args : CliCommandArguments < InitFlags > ,
113
- context : CliCommandContext & { detectedFramework : Framework | null } ,
116
+ context : CliCommandContext & {
117
+ detectedFramework : Awaited < ReturnType < typeof detectFrameworkRecord > >
118
+ } ,
114
119
) : Promise < void > {
115
120
const {
116
121
output,
@@ -128,6 +133,8 @@ export default async function initSanity(
128
133
const cliFlags = args . extOptions
129
134
const unattended = cliFlags . y || cliFlags . yes
130
135
const print = unattended ? noop : output . print
136
+ const warn = ( msg : string ) => output . warn ( chalk . yellow . bgBlack ( msg ) )
137
+
131
138
const intendedPlan = cliFlags [ 'project-plan' ]
132
139
const intendedCoupon = cliFlags . coupon
133
140
const reconfigure = cliFlags . reconfigure
@@ -298,7 +305,8 @@ export default async function initSanity(
298
305
}
299
306
300
307
let initNext = false
301
- if ( detectedFramework ?. slug === 'nextjs' ) {
308
+ const isNextJs = detectedFramework ?. slug === 'nextjs'
309
+ if ( isNextJs ) {
302
310
initNext = await prompt . single ( {
303
311
type : 'confirm' ,
304
312
message :
@@ -327,6 +335,26 @@ export default async function initSanity(
327
335
// Ensure we are using the output path provided by user
328
336
outputPath = answers . outputPath
329
337
338
+ if ( isNextJs ) {
339
+ const packageJson = readPackageJson ( `${ outputPath } /package.json` )
340
+ const reactVersion = packageJson ?. dependencies ?. react
341
+
342
+ if ( reactVersion ) {
343
+ const isUsingReact19 = semver . coerce ( reactVersion ) ?. major === 19
344
+ const isUsingNextJs15 = semver . coerce ( detectedFramework ?. detectedVersion ) ?. major === 15
345
+
346
+ if ( isUsingNextJs15 && isUsingReact19 ) {
347
+ warn ( '╭────────────────────────────────────────────────────────────╮' )
348
+ warn ( '│ │' )
349
+ warn ( '│ It looks like you are using Next.js 15 and React 19 │' )
350
+ warn ( '│ Please read our compatibility guide. │' )
351
+ warn ( '│ https://www.sanity.io/help/react-19 │' )
352
+ warn ( '│ │' )
353
+ warn ( '╰────────────────────────────────────────────────────────────╯' )
354
+ }
355
+ }
356
+ }
357
+
330
358
if ( initNext ) {
331
359
const useTypeScript = unattended ? true : await promptForTypeScript ( prompt )
332
360
trace . log ( { step : 'useTypeScript' , selectedOption : useTypeScript ? 'yes' : 'no' } )
0 commit comments