diff --git a/capture/output/nuxt-dev-plain-restart.svg b/capture/output/nuxt-dev-plain-restart.svg
index e0531066f..02de54c16 100644
--- a/capture/output/nuxt-dev-plain-restart.svg
+++ b/capture/output/nuxt-dev-plain-restart.svg
@@ -16,25 +16,27 @@ svg{--bg:#ffffff;--fg:#24292f;--chrome:#f6f8fa;--dot:#d0d7de}
nuxt dev (plain output, restart on config change)
-
-⠙ Starting Nuxt... 0ms
-│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose⠸ Setting up modules 92ms
-│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)⠴ Preparing app 187ms
-│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)⠧ Preparing app 367ms
-│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)⠏ Generating types 447ms
-│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)⠙ Bundling app 537ms
-│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)✔ Vite client built in 23ms✔ Vite server built in 9ms⠸ Building server 638ms
-│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)✔ Vite client built in 23ms✔ Vite server built in 9ms⠼ Building server 719ms
-│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)✔ Vite client built in 23ms✔ Vite server built in 9ms⠴ Building server 804ms
-│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)✔ Vite client built in 23ms✔ Vite server built in 9ms⠦ Building server 888ms
-│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)✔ Vite client built in 23ms✔ Vite server built in 9ms⠧ Building server 969ms
-│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)✔ Vite client built in 23ms✔ Vite server built in 9ms⠇ Building server 1.05s
-│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)✔ Vite client built in 23ms✔ Vite server built in 9ms✔ Nuxt Nitro server built in 539ms nitro│◆ Ready in 1.23s│config 92ms · modules 95ms · app 204ms · types 145ms · bundle 102ms · server 591mspressh + enterto see available shortcutsℹ Vite server warmed up in 5msℹ Vite client warmed up in 14ms
-│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)✔ Vite client built in 23ms✔ Vite server built in 9ms✔ Nuxt Nitro server built in 539ms nitro│◆ Ready in 1.23s│config 92ms · modules 95ms · app 204ms · types 145ms · bundle 102ms · server 591mspressh + enterto see available shortcutsℹ Vite server warmed up in 5msℹ Vite client warmed up in 14msℹ nuxt.config.ts changed. Reloading Nuxt...
-│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)✔ Vite client built in 23ms✔ Vite server built in 9ms✔ Nuxt Nitro server built in 539ms nitro│◆ Ready in 1.23s│config 92ms · modules 95ms · app 204ms · types 145ms · bundle 102ms · server 591mspressh + enterto see available shortcutsℹ Vite server warmed up in 5msℹ Vite client warmed up in 14msℹ nuxt.config.ts changed. Reloading Nuxt...ℹ Re-optimizing dependencies because vite config has changed✔ Vite client built in 16ms✔ Vite server built in 12ms
-●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)✔ Vite client built in 23ms✔ Vite server built in 9ms✔ Nuxt Nitro server built in 539ms nitro│◆ Ready in 1.23s│config 92ms · modules 95ms · app 204ms · types 145ms · bundle 102ms · server 591mspressh + enterto see available shortcutsℹ Vite server warmed up in 5msℹ Vite client warmed up in 14msℹ nuxt.config.ts changed. Reloading Nuxt...ℹ Re-optimizing dependencies because vite config has changed✔ Vite client built in 16ms✔ Vite server built in 12ms✔ Nuxt Nitro server built in 408ms nitroℹ Vite server warmed up in 2msℹ Vite client warmed up in 4ms
-➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)✔ Vite client built in 23ms✔ Vite server built in 9ms✔ Nuxt Nitro server built in 539ms nitro│◆ Ready in 1.23s│config 92ms · modules 95ms · app 204ms · types 145ms · bundle 102ms · server 591mspressh + enterto see available shortcutsℹ Vite server warmed up in 5msℹ Vite client warmed up in 14msℹ nuxt.config.ts changed. Reloading Nuxt...ℹ Re-optimizing dependencies because vite config has changed✔ Vite client built in 16ms✔ Vite server built in 12ms✔ Nuxt Nitro server built in 408ms nitroℹ Vite server warmed up in 2msℹ Vite client warmed up in 4msℹ nuxt.config.ts changed. Reloading Nuxt... ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)
-✔ Vite client built in 23ms✔ Vite server built in 9ms✔ Nuxt Nitro server built in 539ms nitro│◆ Ready in 1.23s│config 92ms · modules 95ms · app 204ms · types 145ms · bundle 102ms · server 591mspressh + enterto see available shortcutsℹ Vite server warmed up in 5msℹ Vite client warmed up in 14msℹ nuxt.config.ts changed. Reloading Nuxt...ℹ Re-optimizing dependencies because vite config has changed✔ Vite client built in 16ms✔ Vite server built in 12ms✔ Nuxt Nitro server built in 408ms nitroℹ Vite server warmed up in 2msℹ Vite client warmed up in 4msℹ nuxt.config.ts changed. Reloading Nuxt... ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)ℹ Re-optimizing dependencies because vite config has changed (x2)✔ Vite client built in 10ms✔ Vite server built in 8ms
-✔ Nuxt Nitro server built in 539ms nitro│◆ Ready in 1.23s│config 92ms · modules 95ms · app 204ms · types 145ms · bundle 102ms · server 591mspressh + enterto see available shortcutsℹ Vite server warmed up in 5msℹ Vite client warmed up in 14msℹ nuxt.config.ts changed. Reloading Nuxt...ℹ Re-optimizing dependencies because vite config has changed✔ Vite client built in 16ms✔ Vite server built in 12ms✔ Nuxt Nitro server built in 408ms nitroℹ Vite server warmed up in 2msℹ Vite client warmed up in 4msℹ nuxt.config.ts changed. Reloading Nuxt... ➜ DevTools: press Shift + Alt + D in the browser (v3.4.1)ℹ Re-optimizing dependencies because vite config has changed (x2)✔ Vite client built in 10ms✔ Vite server built in 8ms✔ Nuxt Nitro server built in 343ms nitroℹ Vite server warmed up in 2msℹ Vite client warmed up in 2ms
+
+⠙ Starting Nuxt... 0ms
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose⠸ Setting up modules 117ms
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)⠴ Preparing app 244ms
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)⠦ Preparing app 374ms
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)⠇ Generating types 500ms
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)⠏ Generating types 543ms
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)⠙ Bundling app 701ms
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)✔ Vite client built in 31ms✔ Vite server built in 11ms⠸ Building server 829ms
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)✔ Vite client built in 31ms✔ Vite server built in 11ms⠴ Building server 951ms
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)✔ Vite client built in 31ms✔ Vite server built in 11ms⠦ Building server 1.05s
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)✔ Vite client built in 31ms✔ Vite server built in 11ms⠧ Building server 1.13s
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)✔ Vite client built in 31ms✔ Vite server built in 11ms⠇ Building server 1.22s
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)✔ Vite client built in 31ms✔ Vite server built in 11ms⠏ Building server 1.3s
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)✔ Vite client built in 31ms✔ Vite server built in 11ms⠋ Building server 1.38s
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)✔ Vite client built in 31ms✔ Vite server built in 11ms✔ Nuxt Nitro server built in 736ms nitro│◆ Ready in 1.65s│config 117ms · modules 126ms · app 257ms · types 199ms · bundle 130ms · server 820mspressh + enterto see available shortcutsℹ Vite server warmed up in 20msℹ Vite client warmed up in 36ms
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)✔ Vite client built in 31ms✔ Vite server built in 11ms✔ Nuxt Nitro server built in 736ms nitro│◆ Ready in 1.65s│config 117ms · modules 126ms · app 257ms · types 199ms · bundle 130ms · server 820mspressh + enterto see available shortcutsℹ Vite server warmed up in 20msℹ Vite client warmed up in 36msℹ nuxt.config.ts changed. Reloading Nuxt...
+│●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)✔ Vite client built in 31ms✔ Vite server built in 11ms✔ Nuxt Nitro server built in 736ms nitro│◆ Ready in 1.65s│config 117ms · modules 126ms · app 257ms · types 199ms · bundle 130ms · server 820mspressh + enterto see available shortcutsℹ Vite server warmed up in 20msℹ Vite client warmed up in 36msℹ nuxt.config.ts changed. Reloading Nuxt...ℹ Re-optimizing dependencies because vite config has changed✔ Vite client built in 14ms✔ Vite server built in 14ms
+●Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.2.2 and Vue 3.5.41)➜Local: http://localhost:3000/➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)✔ Vite client built in 31ms✔ Vite server built in 11ms✔ Nuxt Nitro server built in 736ms nitro│◆ Ready in 1.65s│config 117ms · modules 126ms · app 257ms · types 199ms · bundle 130ms · server 820mspressh + enterto see available shortcutsℹ Vite server warmed up in 20msℹ Vite client warmed up in 36msℹ nuxt.config.ts changed. Reloading Nuxt...ℹ Re-optimizing dependencies because vite config has changed✔ Vite client built in 14ms✔ Vite server built in 14ms✔ Nuxt Nitro server built in 534ms nitroℹ Vite server warmed up in 2msℹ Vite client warmed up in 6ms
+➜Network: use --host to expose ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)✔ Vite client built in 31ms✔ Vite server built in 11ms✔ Nuxt Nitro server built in 736ms nitro│◆ Ready in 1.65s│config 117ms · modules 126ms · app 257ms · types 199ms · bundle 130ms · server 820mspressh + enterto see available shortcutsℹ Vite server warmed up in 20msℹ Vite client warmed up in 36msℹ nuxt.config.ts changed. Reloading Nuxt...ℹ Re-optimizing dependencies because vite config has changed✔ Vite client built in 14ms✔ Vite server built in 14ms✔ Nuxt Nitro server built in 534ms nitroℹ Vite server warmed up in 2msℹ Vite client warmed up in 6msℹ nuxt.config.ts changed. Reloading Nuxt... ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)
+✔ Vite client built in 31ms✔ Vite server built in 11ms✔ Nuxt Nitro server built in 736ms nitro│◆ Ready in 1.65s│config 117ms · modules 126ms · app 257ms · types 199ms · bundle 130ms · server 820mspressh + enterto see available shortcutsℹ Vite server warmed up in 20msℹ Vite client warmed up in 36msℹ nuxt.config.ts changed. Reloading Nuxt...ℹ Re-optimizing dependencies because vite config has changed✔ Vite client built in 14ms✔ Vite server built in 14ms✔ Nuxt Nitro server built in 534ms nitroℹ Vite server warmed up in 2msℹ Vite client warmed up in 6msℹ nuxt.config.ts changed. Reloading Nuxt... ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)ℹ Re-optimizing dependencies because vite config has changed (x2)✔ Vite client built in 13ms✔ Vite server built in 10ms
+✔ Nuxt Nitro server built in 736ms nitro│◆ Ready in 1.65s│config 117ms · modules 126ms · app 257ms · types 199ms · bundle 130ms · server 820mspressh + enterto see available shortcutsℹ Vite server warmed up in 20msℹ Vite client warmed up in 36msℹ nuxt.config.ts changed. Reloading Nuxt...ℹ Re-optimizing dependencies because vite config has changed✔ Vite client built in 14ms✔ Vite server built in 14ms✔ Nuxt Nitro server built in 534ms nitroℹ Vite server warmed up in 2msℹ Vite client warmed up in 6msℹ nuxt.config.ts changed. Reloading Nuxt... ➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)ℹ Re-optimizing dependencies because vite config has changed (x2)✔ Vite client built in 13ms✔ Vite server built in 10ms✔ Nuxt Nitro server built in 466ms nitroℹ Vite server warmed up in 2msℹ Vite client warmed up in 3ms
diff --git a/capture/output/nuxt-init.svg b/capture/output/nuxt-init.svg
index dbdbe37c9..8e85c132b 100644
--- a/capture/output/nuxt-init.svg
+++ b/capture/output/nuxt-init.svg
@@ -16,15 +16,14 @@ svg{--bg:#ffffff;--fg:#24292f;--chrome:#f6f8fa;--dot:#d0d7de}
npm create nuxt
- .d$b. i$$A$$L .d$b .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`
- .d$b. i$$A$$L .d$b .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`┌Welcome to Nuxt!│
- .d$b. i$$A$$L .d$b .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`┌Welcome to Nuxt!│◐ Loading available templates
- .d$b. i$$A$$L .d$b .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`┌Welcome to Nuxt!│◇ Templates loaded│◆ Which template would you like to use?│○content · Starter for a content-driven website.│●minimal · Minimal starter with a single app.vue. (recommended)│○module · Starter to create your first Nuxt module.│○ui · Starter with Nuxt UI.│○v5-nightly · Minimal setup for Nuxt 5 Nightly│↑/↓ to navigate • Enter: confirm└
- .d$b. i$$A$$L .d$b .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`┌Welcome to Nuxt!│◇ Templates loaded│◇ Which template would you like to use?│minimal · Minimal starter with a single app.vue.│◇ Creating project in my-app│
- .d$b. i$$A$$L .d$b .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`┌Welcome to Nuxt!│◇ Templates loaded│◇ Which template would you like to use?│minimal · Minimal starter with a single app.vue.│◇ Creating project in my-app│◒ Downloading minimal template
- .d$b. i$$A$$L .d$b .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`┌Welcome to Nuxt!│◇ Templates loaded│◇ Which template would you like to use?│minimal · Minimal starter with a single app.vue.│◇ Creating project in my-app│
- .d$b. i$$A$$L .d$b .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`┌Welcome to Nuxt!│◇ Templates loaded│◇ Which template would you like to use?│minimal · Minimal starter with a single app.vue.│◇ Creating project in my-app│◓ Downloading minimal template
- .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`┌Welcome to Nuxt!│◇ Templates loaded│◇ Which template would you like to use?│minimal · Minimal starter with a single app.vue.│◇ Creating project in my-app│◇ Downloaded minimal template│● Skipping install dependencies step.│◆ Would you like to browse and install modules?│○Yes/● No└
-│◇ Creating project in my-app│◇ Downloaded minimal template│● Skipping install dependencies step.│◇ Would you like to browse and install modules?│No│◇ Created your project from the minimal template│● to scaffold this project again without prompts:│npm create nuxt@latest my-app -- --template=minimal --packageManager=npm --no-gitInit \│ --no-modules --no-install││ Next steps:│ › cd my-app│ › npm install│ › npm run dev│└ ✨ Happy building!
+ .d$b. i$$A$$L .d$b .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`
+ .d$b. i$$A$$L .d$b .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`┌Welcome to Nuxt!│
+ .d$b. i$$A$$L .d$b .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`┌Welcome to Nuxt!│
+ .d$b. i$$A$$L .d$b .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`┌Welcome to Nuxt!│◓ Loading available templates
+ .d$b. i$$A$$L .d$b .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`┌Welcome to Nuxt!│◇ Templates loaded│◆ Which template would you like to use?│○content · Starter for a content-driven website.│●minimal · Minimal starter with a single app.vue. (recommended)│○module · Starter to create your first Nuxt module.│○ui · Starter with Nuxt UI.│○v5-nightly · Minimal setup for Nuxt 5 Nightly│↑/↓ to navigate • Enter: confirm└
+ .d$b. i$$A$$L .d$b .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`┌Welcome to Nuxt!│◇ Templates loaded│◇ Which template would you like to use?│minimal · Minimal starter with a single app.vue.│◇ Creating project in my-app│
+ .d$b. i$$A$$L .d$b .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`┌Welcome to Nuxt!│◇ Templates loaded│◇ Which template would you like to use?│minimal · Minimal starter with a single app.vue.│◇ Creating project in my-app│◒ Downloading minimal template
+ .$$F` `$$L.$$A$$. j$$' `4$$:` `$$. j$$' .4$: `$$. j$$` .$$: `4$L :$$:____.d$$: _____.:$$: `4$$$$$$$$P` .i$$$$$$$$P`┌Welcome to Nuxt!│◇ Templates loaded│◇ Which template would you like to use?│minimal · Minimal starter with a single app.vue.│◇ Creating project in my-app│◇ Downloaded minimal template│● Skipping install dependencies step.│◆ Would you like to browse and install modules?│○Yes/● No└
+│◇ Creating project in my-app│◇ Downloaded minimal template│● Skipping install dependencies step.│◇ Would you like to browse and install modules?│No│◇ Created your project from the minimal template│● to scaffold this project again without prompts:│npm create nuxt@latest my-app -- --template=minimal --packageManager=npm --no-gitInit \│ --no-modules --no-install││ Next steps:│ › cd my-app│ › npm install│ › npm run dev│└ ✨ Happy building!
diff --git a/packages/nuxt-cli/src/commands/build.ts b/packages/nuxt-cli/src/commands/build.ts
index c3b9dfcc9..e23c96b29 100644
--- a/packages/nuxt-cli/src/commands/build.ts
+++ b/packages/nuxt-cli/src/commands/build.ts
@@ -6,8 +6,9 @@ import { defineCommand } from 'citty'
import { relative } from 'pathe'
import { resolveDotenvFileNames } from '../utils/args'
import { showBanner } from '../utils/banner'
-
+import { BuildProgress } from '../utils/build-progress'
import { overrideEnv } from '../utils/env'
+
import { ActionableError } from '../utils/errors'
import { formatDuration } from '../utils/formatting'
import { clearBuildDir } from '../utils/fs'
@@ -15,9 +16,13 @@ import { loadKit } from '../utils/kit'
import { acquireLock, acquireOutputLock, formatLockError } from '../utils/lockfile'
import { intro, logger, outro } from '../utils/logger'
import { resolveRootDir } from '../utils/paths'
+import { createPhaseReporter, formatPhaseBreakdown } from '../utils/phase-reporter'
import { startCpuProfile, stopCpuProfile } from '../utils/profile'
import { dotEnvArgs, envNameArgs, extendsArgs, logLevelArgs, profileArgs, rootDirArgs } from './_shared'
+/** How often a phase repeats itself where there is no animated line. */
+const HEARTBEAT_INTERVAL = 5000
+
export default defineCommand({
meta: {
name: 'build',
@@ -55,9 +60,27 @@ export default defineCommand({
}
const releaseLocks: Array<() => void> = []
+ const progress = new BuildProgress()
+ let stopReporting = () => {}
try {
intro(styleText('cyan', 'Building Nuxt for production...'))
+ // The phase line owns a row of the terminal, which a silent build has no
+ // business drawing on. Subscribed after the intro so the first phase is
+ // reported below it rather than above.
+ if (ctx.args.logLevel !== 'silent') {
+ const reporter = createPhaseReporter({ heartbeat: HEARTBEAT_INTERVAL })
+ let unsubscribe: (() => void) | undefined
+ // Assigned before subscribing, because subscribing reports the phase in
+ // flight straight away: a first write that fails, on a pipe that has
+ // already been closed, must still leave the terminal recoverable.
+ stopReporting = () => {
+ unsubscribe?.()
+ reporter.stop()
+ }
+ unsubscribe = progress.onUpdate(reporter.update)
+ }
+
const kit = await loadKit(cwd)
const nuxt = await kit.loadNuxt({
cwd,
@@ -85,6 +108,8 @@ export default defineCommand({
},
})
+ progress.attachNuxt(nuxt)
+
showBanner(nuxt)
await nuxt.ready()
@@ -115,6 +140,14 @@ export default defineCommand({
await kit.buildNuxt(nuxt)
+ stopReporting()
+ progress.finish()
+
+ const breakdown = formatPhaseBreakdown(progress.timings)
+ if (breakdown) {
+ logger.message(styleText('dim', breakdown))
+ }
+
if (ctx.args.prerender) {
if (!nuxt.options.ssr) {
logger.warn(`HTML content not prerendered because ${styleText('cyan', 'ssr: false')} was set.`)
@@ -129,6 +162,7 @@ export default defineCommand({
}
}
finally {
+ stopReporting()
for (const release of releaseLocks.reverse()) {
release()
}
diff --git a/packages/nuxt-cli/src/dev/index.ts b/packages/nuxt-cli/src/dev/index.ts
index d95660cce..d40de4e73 100644
--- a/packages/nuxt-cli/src/dev/index.ts
+++ b/packages/nuxt-cli/src/dev/index.ts
@@ -1,7 +1,7 @@
/* eslint-disable perfectionist/sort-imports -- `./force-tty` must be evaluated before anything that loads `std-env` or `consola` */
import type { NuxtConfig } from '@nuxt/schema'
import type { DevListenOverrides, Listener, ListenURL } from './listen'
-import type { DevProgressSnapshot } from './progress'
+import type { ProgressSnapshot } from '../utils/progress-snapshot'
import type { DevRestartReason } from './reason'
import type { ServerLogEvent } from './log-channel'
import type { DevRequestEvent, DevRoutes, NuxtDevContext, NuxtDevIPCMessage, NuxtParentIPCMessage } from './utils'
@@ -21,7 +21,7 @@ import { debug } from '../utils/logger'
import { startCpuProfile, stopCpuProfile } from '../utils/profile.ts'
import { openInspector } from './inspect'
import { currentRequest, isServingRequest } from './serving-state'
-import { createStartupReporter } from './startup-log'
+import { createPhaseReporter } from '../utils/phase-reporter'
import { NuxtDevServer } from './utils'
const start = Date.now()
@@ -93,7 +93,7 @@ interface InitializeOptions {
* Called with every startup progress snapshot, from before the first load
* begins, so a UI can narrate startup as it happens rather than after.
*/
- onProgress?: (snapshot: DevProgressSnapshot) => void
+ onProgress?: (snapshot: ProgressSnapshot) => void
/**
* Called as soon as a socket is bound, milliseconds into startup, and again
* with `confirmed` once the resolved config has agreed with the address.
@@ -357,7 +357,7 @@ export async function initialize(devContext: NuxtDevContext, ctx: InitializeOpti
// itself, so the transient reporter line would only fight it for the screen.
const reporter = devContext.args.logLevel === 'silent' || ipc.enabled || ctx.captureUIEvents
? undefined
- : createStartupReporter()
+ : createPhaseReporter()
const unsubscribeProgress = reporter && devServer.progress.onUpdate(reporter.update)
const stopReporting = () => {
unsubscribeProgress?.()
diff --git a/packages/nuxt-cli/src/dev/loading-client.ts b/packages/nuxt-cli/src/dev/loading-client.ts
index f207cdc15..157d80e23 100644
--- a/packages/nuxt-cli/src/dev/loading-client.ts
+++ b/packages/nuxt-cli/src/dev/loading-client.ts
@@ -1,4 +1,4 @@
-import type { DevProgressSnapshot } from './progress'
+import type { ProgressSnapshot } from '../utils/progress-snapshot'
/**
* The scripts inlined into the dev server's loading and error pages.
@@ -36,7 +36,7 @@ export function progressClient(options: ProgressClientOptions): void {
caption.textContent = label ? `${label} \u00B7 ${seconds}` : seconds
}
- function apply(snapshot: DevProgressSnapshot): void {
+ function apply(snapshot: ProgressSnapshot): void {
start = Date.now() - snapshot.elapsed
// The message, not the phase id: it carries whatever detail the server has,
// such as the module currently being set up, and this page is what the user
@@ -53,7 +53,7 @@ export function progressClient(options: ProgressClientOptions): void {
paint()
}
- function read(event: Event): DevProgressSnapshot | undefined {
+ function read(event: Event): ProgressSnapshot | undefined {
try {
return JSON.parse((event as MessageEvent).data)
}
diff --git a/packages/nuxt-cli/src/dev/loading-page.ts b/packages/nuxt-cli/src/dev/loading-page.ts
index 2c57d49d0..5baa0118f 100644
--- a/packages/nuxt-cli/src/dev/loading-page.ts
+++ b/packages/nuxt-cli/src/dev/loading-page.ts
@@ -1,4 +1,4 @@
-import type { DevProgressSnapshot } from './progress'
+import type { ProgressSnapshot } from '../utils/progress-snapshot'
import { inlineScript, progressClient, recoveryClient } from './loading-client'
import { PROGRESS_PATH } from './progress'
@@ -16,7 +16,7 @@ const MAX_POLL_INTERVAL_MS = 1000
const STYLES = `.nuxt-loader-bar{right:auto!important;width:var(${PROGRESS_PROPERTY},4%);transition:width .3s ease}
#${CAPTION_ID}{position:fixed;left:0;right:0;bottom:14px;text-align:center;font:12px/1.5 ui-sans-serif,system-ui,-apple-system,sans-serif;opacity:.55;font-variant-numeric:tabular-nums}`
-function progressTags(snapshot: DevProgressSnapshot): string {
+function progressTags(snapshot: ProgressSnapshot): string {
return `${inlineScript(progressClient, {
progressPath: PROGRESS_PATH,
captionId: CAPTION_ID,
@@ -35,7 +35,7 @@ function progressTags(snapshot: DevProgressSnapshot): string {
* adds is a determinate bar, a phase caption, the build error inline, and a
* reload driven by the server rather than by a poll interval.
*/
-export function withProgress(html: string, snapshot: DevProgressSnapshot): string {
+export function withProgress(html: string, snapshot: ProgressSnapshot): string {
const tags = progressTags(snapshot)
const index = html.lastIndexOf('