@@ -227,7 +227,8 @@ async function run(): Promise<void> {
227
227
* If the user does not provide the necessary flags, prompt them for their
228
228
* preferences, unless `--yes` option was specified, or when running in CI.
229
229
*/
230
- const skipPrompt = ciInfo . isCI || opts . yes
230
+ let skipPrompt = ciInfo . isCI || opts . yes
231
+ let useRecommendedDefaults = false
231
232
232
233
if ( ! example ) {
233
234
const defaults : typeof preferences = {
@@ -244,8 +245,124 @@ async function run(): Promise<void> {
244
245
disableGit : false ,
245
246
reactCompiler : false ,
246
247
}
247
- const getPrefOrDefault = ( field : string ) =>
248
- preferences [ field ] ?? defaults [ field ]
248
+
249
+ type DisplayConfigItem = {
250
+ key : keyof typeof defaults
251
+ values ? : Record < string , string>
252
+ }
253
+
254
+ const displayConfig : DisplayConfigItem [ ] = [
255
+ {
256
+ key : 'typescript' ,
257
+ values : { true : 'TypeScript' , false : 'JavaScript' } ,
258
+ } ,
259
+ { key : 'linter' , values : { eslint : 'ESLint' , biome : 'Biome' } } ,
260
+ { key : 'reactCompiler' , values : { true : 'React Compiler' } } ,
261
+ { key : 'tailwind' , values : { true : 'Tailwind CSS' } } ,
262
+ { key : 'srcDir' , values : { true : 'src/ dir' } } ,
263
+ { key : 'app' , values : { true : 'App Router' , false : 'Pages Router' } } ,
264
+ { key : 'turbopack' , values : { true : 'Turbopack' } } ,
265
+ ]
266
+
267
+ // Helper to format settings for display based on displayConfig
268
+ const formatSettingsDescription = (
269
+ settings : Record < string , boolean | string >
270
+ ) => {
271
+ const descriptions : string [ ] = [ ]
272
+
273
+ for ( const config of displayConfig ) {
274
+ const value = settings [ config . key ]
275
+
276
+ if ( config . values ) {
277
+ // Look up the display label for this value
278
+ const label = config . values [ String ( value ) ]
279
+ if ( label ) {
280
+ descriptions . push ( label )
281
+ }
282
+ }
283
+ }
284
+
285
+ return descriptions . join ( ', ' )
286
+ }
287
+
288
+ // Check if we have saved preferences
289
+ const hasSavedPreferences = Object . keys ( preferences ) . length > 0
290
+
291
+ // Check if user provided any configuration flags
292
+ // If they did, skip the "recommended defaults" prompt and go straight to
293
+ // individual prompts for any missing options
294
+ const hasProvidedOptions = process . argv . some ( ( arg ) => arg . startsWith ( '--' ) )
295
+
296
+ // Only show the "recommended defaults" prompt if:
297
+ // - Not in CI and not using --yes flag
298
+ // - User hasn't provided any custom options
299
+ if ( ! skipPrompt && ! hasProvidedOptions ) {
300
+ const choices : Array < {
301
+ title : string
302
+ value : string
303
+ description ?: string
304
+ } > = [
305
+ {
306
+ title : 'Yes, use recommended defaults' ,
307
+ value : 'recommended' ,
308
+ description : formatSettingsDescription ( defaults ) ,
309
+ } ,
310
+ {
311
+ title : 'No, customize settings' ,
312
+ value : 'customize' ,
313
+ description : 'Choose your own preferences' ,
314
+ } ,
315
+ ]
316
+
317
+ // Add "reuse previous settings" option if we have saved preferences
318
+ if ( hasSavedPreferences ) {
319
+ const prefDescription = formatSettingsDescription ( preferences )
320
+ choices . splice ( 1 , 0 , {
321
+ title : 'No, reuse previous settings' ,
322
+ value : 'reuse' ,
323
+ description : prefDescription ,
324
+ } )
325
+ }
326
+
327
+ const { setupChoice } = await prompts (
328
+ {
329
+ type : 'select' ,
330
+ name : 'setupChoice' ,
331
+ message : 'Would you like to use the recommended Next.js defaults?' ,
332
+ choices,
333
+ initial : 0 ,
334
+ } ,
335
+ {
336
+ onCancel : ( ) => {
337
+ console . error ( 'Exiting.' )
338
+ process . exit ( 1 )
339
+ } ,
340
+ }
341
+ )
342
+
343
+ if ( setupChoice === 'recommended' ) {
344
+ useRecommendedDefaults = true
345
+ skipPrompt = true
346
+ } else if ( setupChoice === 'reuse' ) {
347
+ skipPrompt = true
348
+ }
349
+ }
350
+
351
+ // If using recommended defaults, populate preferences with defaults
352
+ // This ensures they are saved for reuse next time
353
+ if ( useRecommendedDefaults ) {
354
+ Object . assign ( preferences , defaults )
355
+ }
356
+
357
+ const getPrefOrDefault = ( field : string ) => {
358
+ // If using recommended defaults, always use hardcoded defaults
359
+ if ( useRecommendedDefaults ) {
360
+ return defaults [ field ]
361
+ }
362
+
363
+ // If not using the recommended template, we prefer saved preferences, otherwise defaults.
364
+ return preferences [ field ] ?? defaults [ field ]
365
+ }
249
366
250
367
if ( ! opts . typescript && ! opts . javascript ) {
251
368
if ( skipPrompt ) {
0 commit comments