diff --git a/.github/workflows/docs-screenshots.yml b/.github/workflows/docs-screenshots.yml
new file mode 100644
index 0000000000..ad15360720
--- /dev/null
+++ b/.github/workflows/docs-screenshots.yml
@@ -0,0 +1,56 @@
+name: docs-screenshots
+
+# Regenerates the screenshots in `docs/images/` (`pnpm docs:screenshots`) and
+# opens a pull request when they changed. Run it from the Actions tab after a
+# UI change; one runner keeps the rendering consistent across runs.
+on:
+ workflow_dispatch:
+
+permissions: {}
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ screenshots:
+ if: github.repository == 'nuxt/devtools'
+ runs-on: ubuntu-latest
+ timeout-minutes: 15
+ permissions:
+ contents: write
+ pull-requests: write
+ steps:
+ - uses: actions/checkout@v7
+ with:
+ persist-credentials: false
+ - uses: pnpm/action-setup@v6
+ - uses: actions/setup-node@v7
+ with:
+ node-version: lts/*
+ cache: pnpm
+ - run: npm install -g corepack@latest
+ - run: corepack enable
+ - run: pnpm install
+ - run: pnpm build
+ - run: pnpm exec playwright install --with-deps chromium
+ - run: pnpm docs:screenshots
+ - name: Open a pull request
+ env:
+ GH_TOKEN: ${{ github.token }}
+ BASE: ${{ github.ref_name }}
+ BRANCH: docs/screenshots-${{ github.run_id }}
+ run: |
+ if [ -z "$(git status --porcelain -- docs/images)" ]; then
+ echo "Screenshots are up to date."
+ exit 0
+ fi
+ git config user.name 'github-actions[bot]'
+ git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
+ git switch -c "$BRANCH"
+ git add docs/images
+ git commit -m 'docs: update screenshots'
+ git push "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" "$BRANCH"
+ gh pr create --base "$BASE" --head "$BRANCH" \
+ --title 'docs: update screenshots' \
+ --body "Regenerated by \`pnpm docs:screenshots\` in the [docs-screenshots workflow](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID})."
diff --git a/docs/1.features.md b/docs/1.features.md
index 90c9942480..e069ac6eda 100644
--- a/docs/1.features.md
+++ b/docs/1.features.md
@@ -53,10 +53,14 @@ Appears while the current page holds an error, and shows it with its stack trace
Shows the state and data payloads of your page: keyed state from `useState()` and the data fetched with `useAsyncData()` and `useFetch()`, which you can re-fetch.
+
+
### Runtime Configs
Shows your App Config and runtime config. App Config and public runtime config can be edited live; private runtime config is read-only, as it is never exposed to the client.
+
+
### Plugins
Shows the plugins of your app, with their mode (client or server) and initialization time.
@@ -65,6 +69,8 @@ Shows the plugins of your app, with their mode (client or server) and initializa
Records when auto-imported composables run and when the route changes, to help you understand the order in which things happen. It is opt-in: until it is enabled, the tab offers to enable it for you, which updates your `nuxt.config` and restarts Nuxt.
+
+
```ts [nuxt.config.ts]
export default defineNuxtConfig({
devtools: {
@@ -95,14 +101,20 @@ The Open Graph panel, powered by [`@devframes/plugin-og`](https://npmx.dev/packa
Shows all the [Nitro](https://nitro.build) routes of your project, with a playground to send requests to your endpoints and inspect their responses.
+
+
### Server Tasks
Appears when Nitro's `experimental.tasks` is enabled and your project defines [tasks](https://nitro.build/guide/tasks). Pass task payloads, run them, and see their results.
+
+
### Storage
Shows the [Nitro storage](https://nitro.build/guide/storage) mounts of your project. You can create, edit, and delete their items.
+
+
## Modules
Tabs contributed by the Nuxt modules you install (for example `@nuxt/fonts`, `@nuxt/scripts` or `nuxt-og-image`) appear in this section. See the [Module Authors Guide](/modules/devtools/module-authors) to add your own.
diff --git a/docs/8.contributing.md b/docs/8.contributing.md
index bfcac39bb6..1b276c0958 100644
--- a/docs/8.contributing.md
+++ b/docs/8.contributing.md
@@ -78,4 +78,14 @@ On the module side, the source TypeScript files are used directly, so you don't
The documentation lives in the [`docs/`](https://github.com/nuxt/devtools/tree/main/docs) directory and is published on [nuxt.com/modules/devtools](/modules/devtools). Keep images next to the pages in `docs/images/` and link them with a relative path, such as ``.
+The DevTools screenshots are generated from the [`docs` playground](https://github.com/nuxt/devtools/tree/main/playgrounds/docs), a small shop with pages, components, server routes, a task and a storage mount. After a UI change, regenerate them with:
+
+```sh
+pnpm build
+pnpm exec playwright install chromium
+pnpm docs:screenshots
+```
+
+Each screenshot is a step in [`tests/docs-screenshots/screenshots.spec.ts`](https://github.com/nuxt/devtools/blob/main/tests/docs-screenshots/screenshots.spec.ts): add one there to document a new tab. The `docs-screenshots` workflow, run from the Actions tab, does the same on CI and opens a pull request with the updated images.
+
To preview your changes, run the [nuxt.com](https://github.com/nuxt/nuxt.com) dev server with `NUXT_DEVTOOLS_PATH` set to your local clone of this repo. Pull requests changing `docs/` can also be previewed on nuxt.com once a maintainer adds the `preview:enabled` label.
diff --git a/docs/images/components.webp b/docs/images/components.webp
index 19eeb4f559..7b11edb883 100644
Binary files a/docs/images/components.webp and b/docs/images/components.webp differ
diff --git a/docs/images/hooks.webp b/docs/images/hooks.webp
index 31201e7a2c..d5c64e0705 100644
Binary files a/docs/images/hooks.webp and b/docs/images/hooks.webp differ
diff --git a/docs/images/imports.webp b/docs/images/imports.webp
index b4ddfe6e66..f4c4d68dc6 100644
Binary files a/docs/images/imports.webp and b/docs/images/imports.webp differ
diff --git a/docs/images/modules.webp b/docs/images/modules.webp
index ad5948a1de..9653f69024 100644
Binary files a/docs/images/modules.webp and b/docs/images/modules.webp differ
diff --git a/docs/images/overview.webp b/docs/images/overview.webp
index 595569cccd..46c78ab91a 100644
Binary files a/docs/images/overview.webp and b/docs/images/overview.webp differ
diff --git a/docs/images/pages.webp b/docs/images/pages.webp
index 5ab10887bb..1f032ca844 100644
Binary files a/docs/images/pages.webp and b/docs/images/pages.webp differ
diff --git a/docs/images/payload.webp b/docs/images/payload.webp
new file mode 100644
index 0000000000..a4d3ef0dd5
Binary files /dev/null and b/docs/images/payload.webp differ
diff --git a/docs/images/runtime-configs.webp b/docs/images/runtime-configs.webp
new file mode 100644
index 0000000000..b9f80a37f7
Binary files /dev/null and b/docs/images/runtime-configs.webp differ
diff --git a/docs/images/server-routes.webp b/docs/images/server-routes.webp
new file mode 100644
index 0000000000..a0ee854fe4
Binary files /dev/null and b/docs/images/server-routes.webp differ
diff --git a/docs/images/server-tasks.webp b/docs/images/server-tasks.webp
new file mode 100644
index 0000000000..e88fdf45ff
Binary files /dev/null and b/docs/images/server-tasks.webp differ
diff --git a/docs/images/storage.webp b/docs/images/storage.webp
new file mode 100644
index 0000000000..867ec4ca05
Binary files /dev/null and b/docs/images/storage.webp differ
diff --git a/docs/images/timeline.webp b/docs/images/timeline.webp
new file mode 100644
index 0000000000..c3c2a2afc9
Binary files /dev/null and b/docs/images/timeline.webp differ
diff --git a/knip.jsonc b/knip.jsonc
index 2aabd1947d..ced8214ddc 100644
--- a/knip.jsonc
+++ b/knip.jsonc
@@ -9,7 +9,7 @@
"local.ts",
"scripts/*.{js,mjs,ts}",
"taze.config.ts",
- "tests/e2e/**/*.ts"
+ "tests/{e2e,docs-screenshots}/**/*.ts"
],
"project": [
"*.{js,mjs,ts}",
diff --git a/package.json b/package.json
index c3c430fc0d..f6b2041f04 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"test:e2e:prebuild": "pnpm -C playgrounds/empty exec nuxt build && pnpm -C playgrounds/spa exec nuxt build",
"test:e2e:ui": "playwright test --config tests/e2e/playwright.config.ts --ui",
"test:e2e:ecosystem": "playwright test --config playgrounds-ecosystem/tests/playwright.config.ts",
+ "docs:screenshots": "playwright test --config tests/docs-screenshots/playwright.config.ts",
"typecheck": "vue-tsc --noEmit",
"postinstall": "simple-git-hooks && skills experimental_sync -y -r",
"dev:prepare": "pnpm -r --filter=\"./packages/*\" run dev:prepare"
diff --git a/playgrounds/docs/app/app.config.ts b/playgrounds/docs/app/app.config.ts
new file mode 100644
index 0000000000..644f7ba444
--- /dev/null
+++ b/playgrounds/docs/app/app.config.ts
@@ -0,0 +1,6 @@
+export default defineAppConfig({
+ theme: {
+ primary: 'green',
+ },
+ announcement: 'Free shipping on orders over €50',
+})
diff --git a/playgrounds/docs/app/app.vue b/playgrounds/docs/app/app.vue
new file mode 100644
index 0000000000..f8eacfa737
--- /dev/null
+++ b/playgrounds/docs/app/app.vue
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/playgrounds/docs/app/assets/main.css b/playgrounds/docs/app/assets/main.css
new file mode 100644
index 0000000000..5e5d40761f
--- /dev/null
+++ b/playgrounds/docs/app/assets/main.css
@@ -0,0 +1,9 @@
+html {
+ background: #0b0b0b;
+ color: #e5e5e5;
+ font-family: ui-sans-serif, system-ui, sans-serif;
+}
+
+body {
+ margin: 0;
+}
diff --git a/playgrounds/docs/app/components/AppHeader.vue b/playgrounds/docs/app/components/AppHeader.vue
new file mode 100644
index 0000000000..e60f3021ff
--- /dev/null
+++ b/playgrounds/docs/app/components/AppHeader.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+ {{ siteName }}
+
+
+ {{ announcement }}
+
+
+
diff --git a/playgrounds/docs/app/components/CartButton.vue b/playgrounds/docs/app/components/CartButton.vue
new file mode 100644
index 0000000000..ac6c40d50b
--- /dev/null
+++ b/playgrounds/docs/app/components/CartButton.vue
@@ -0,0 +1,7 @@
+
+
+
+ Cart ({{ count }})
+
diff --git a/playgrounds/docs/app/components/PriceTag.vue b/playgrounds/docs/app/components/PriceTag.vue
new file mode 100644
index 0000000000..d93770a931
--- /dev/null
+++ b/playgrounds/docs/app/components/PriceTag.vue
@@ -0,0 +1,9 @@
+
+
+
+ {{ formatted }}
+
diff --git a/playgrounds/docs/app/components/ProductCard.vue b/playgrounds/docs/app/components/ProductCard.vue
new file mode 100644
index 0000000000..eb799130b1
--- /dev/null
+++ b/playgrounds/docs/app/components/ProductCard.vue
@@ -0,0 +1,24 @@
+
+
+
+
+
+ {{ product.name }}
+
+