Repository: vercel/next.js
Pull request: [create-next-app] Generate route types after setup

## Run `next typegen` after project creation in create-next-app

### What?
This PR adds automatic type generation after a Next.js project is created with create-next-app.

### Why?
Running `next typegen` immediately after project creation ensures that route type definitions are available right away, improving the developer experience by providing proper TypeScript support from the start.

### How?
- Added a new helper function `runTypegen()` that executes the local Next.js binary with the `typegen` command
- Integrated this function into both the main app creation flow and the template installation process
- Implemented error handling to ensure that typegen failures don't interrupt the app creation process

Changed files:
filename: packages/create-next-app/create-app.ts
patch: @@ -17,6 +17,7 @@ import { install } from './helpers/install'
 import { isFolderEmpty } from './helpers/is-folder-empty'
 import { getOnline } from './helpers/is-online'
 import { isWriteable } from './helpers/is-writeable'
+import { runTypegen } from './helpers/typegen'
 
 import type { TemplateMode, TemplateType } from './templates'
 import { getTemplateFile, installTemplate } from './templates'
@@ -222,6 +223,14 @@ export async function createApp({
 
       await install(packageManager, isOnline)
       console.log()
+      try {
+        console.log()
+        await runTypegen(packageManager)
+        console.log()
+      } catch (err) {
+        // Best effort: do not fail app creation if typegen fails
+        console.error('Error running typegen:', err)
+      }
     }
   } else {
     /**

filename: packages/create-next-app/helpers/typegen.ts
patch: @@ -0,0 +1,56 @@
+/* eslint-disable import/no-extraneous-dependencies */
+import spawn from 'cross-spawn'
+import type { PackageManager } from './get-pkg-manager'
+
+/**
+ * Runs `next typegen` using the package manager to execute the locally installed Next.js binary.
+ * Assumes the current working directory is the project root where Next is installed.
+ */
+export async function runTypegen(
+  packageManager: PackageManager
+): Promise<void> {
+  return new Promise((resolve, reject) => {
+    // Determine the command and arguments based on the package manager
+    let command: string
+    let args: string[]
+
+    switch (packageManager) {
+      case 'npm':
+        command = 'npm'
+        args = ['exec', 'next', '--', 'typegen']
+        break
+      case 'yarn':
+        command = 'yarn'
+        args = ['exec', 'next', '--', 'typegen']
+        break
+      case 'pnpm':
+        command = 'pnpm'
+        args = ['exec', 'next', '--', 'typegen']
+        break
+      case 'bun':
+        command = 'bun'
+        // Bun only has `bun x` which is not the same thing.
+        // We need to hope Bun never implements their own `bun next`.
+        args = ['next', 'typegen']
+        break
+      default:
+        packageManager satisfies never
+        throw new Error(`Unsupported package manager: ${packageManager}`)
+    }
+
+    const child = spawn(command, args, {
+      stdio: 'inherit',
+      env: {
+        ...process.env,
+      },
+    })
+
+    child.on('close', (code) => {
+      if (code !== 0) {
+        reject(new Error(`next typegen exited with code ${code}`))
+        return
+      }
+      resolve()
+    })
+  })
+}

filename: packages/create-next-app/templates/index.ts
patch: @@ -1,4 +1,5 @@
 import { install } from "../helpers/install";
+import { runTypegen } from "../helpers/typegen";
 import { copy } from "../helpers/copy";
 
 import { async as glob } from "fast-glob";
@@ -302,6 +303,14 @@ export const installTemplate = async ({
   console.log();
 
   await install(packageManager, isOnline);
+  try {
+    console.log();
+    await runTypegen(packageManager);
+    console.log();
+  } catch (err) {
+    console.error("Error running typegen:", err);
+    // Best effort: do not fail app creation if typegen fails
+  }
 };
 
 export * from "./types";