+ Hello (SPA mode)
+
+ This playground runs with ssr: false. The Nuxt DevTools dock
+ entry should still appear in Vite DevTools.
+
+
+
+
+
diff --git a/playgrounds/spa/nuxt.config.ts b/playgrounds/spa/nuxt.config.ts
new file mode 100644
index 0000000000..7b931371d3
--- /dev/null
+++ b/playgrounds/spa/nuxt.config.ts
@@ -0,0 +1,23 @@
+// https://nuxt.com/docs/api/configuration/nuxt-config
+const devtoolsModule = process.env.NUXT_DEVTOOLS_LOCAL ? '../../local' : '@nuxt/devtools'
+
+// Regression playground for the dock-missing bug. With `ssr: false` AND
+// `experimental.viteEnvironmentApi: true`, `@nuxt/kit`'s `addVitePlugin`
+// takes the `applyToEnvironment` wrapper branch (`config.environments` is
+// always populated). The wrapper plugin object lacks a `devtools` property,
+// so `@vitejs/devtools`'s `"devtools" in plugin` filter silently drops it
+// and the Nuxt DevTools dock entry never registers. This mirrors the Nuxt 5
+// vite-builder code path the bug was originally reported against.
+export default defineNuxtConfig({
+ modules: [
+ devtoolsModule,
+ ],
+
+ ssr: false,
+
+ experimental: {
+ viteEnvironmentApi: true,
+ },
+
+ compatibilityDate: '2024-09-19',
+})
diff --git a/playgrounds/spa/package.json b/playgrounds/spa/package.json
new file mode 100644
index 0000000000..159437a3cf
--- /dev/null
+++ b/playgrounds/spa/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "spa",
+ "version": "4.0.0-alpha.6",
+ "private": true,
+ "main": "nuxt.config.ts",
+ "files": [
+ "app.vue",
+ "components",
+ "nuxt.config.ts",
+ "pages",
+ "public"
+ ],
+ "scripts": {
+ "play:build": "nuxt build",
+ "play:dev": "nuxt dev",
+ "play:generate": "nuxt generate",
+ "play:preview": "nuxt preview"
+ },
+ "devDependencies": {
+ "@types/node": "catalog:types",
+ "nuxt": "catalog:buildtools"
+ }
+}
diff --git a/playgrounds/spa/public/empty.txt b/playgrounds/spa/public/empty.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/playgrounds/spa/tsconfig.json b/playgrounds/spa/tsconfig.json
new file mode 100644
index 0000000000..a746f2a70c
--- /dev/null
+++ b/playgrounds/spa/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ // https://nuxt.com/docs/guide/concepts/typescript
+ "extends": "./.nuxt/tsconfig.json"
+}
diff --git a/tests/e2e/playwright.config.ts b/tests/e2e/playwright.config.ts
index dc5ac827ce..f68c4ea289 100644
--- a/tests/e2e/playwright.config.ts
+++ b/tests/e2e/playwright.config.ts
@@ -5,7 +5,7 @@ import { matchesProjectFilter } from './shared/glob'
const REPO_ROOT = fileURLToPath(new URL('../..', import.meta.url))
-const PLAYGROUNDS = ['empty', 'tab-pinia', 'tab-seo'] as const
+const PLAYGROUNDS = ['empty', 'spa', 'tab-pinia', 'tab-seo'] as const
const MODES = ['dev', 'built'] as const
type Mode = typeof MODES[number]