diff --git a/docs/testing.md b/docs/testing.md
index 500016c6bff84fa..d24cd71f3249a9e 100644
--- a/docs/testing.md
+++ b/docs/testing.md
@@ -10,6 +10,7 @@ description: Learn how to set up Next.js with three commonly used testing tools
Next.js with Cypress
Next.js with Playwright
Next.js with Jest and React Testing Library
+ Next.js with Vitest
diff --git a/examples/with-vitest/.gitignore b/examples/with-vitest/.gitignore
new file mode 100644
index 000000000000000..1437c53f70bc211
--- /dev/null
+++ b/examples/with-vitest/.gitignore
@@ -0,0 +1,34 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# vercel
+.vercel
diff --git a/examples/with-vitest/README.md b/examples/with-vitest/README.md
new file mode 100644
index 000000000000000..5bd869b5c98a63f
--- /dev/null
+++ b/examples/with-vitest/README.md
@@ -0,0 +1,23 @@
+# Vitest
+
+This example shows how to use [Vitest](https://github.com/vitest-dev/vitest) with Next.js.
+
+## Deploy your own
+
+Deploy the example using [Vercel](https://vercel.com/) or preview live with [StackBlitz](https://stackblitz.com/github/vercel/next.js/tree/canary/examples/with-vitest)
+
+[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-vitest&project-name=with-vitest&repository-name=with-vitest)
+
+## How to use
+
+Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:
+
+```bash
+npx create-next-app --example with-vitest with-vitest-app
+# or
+yarn create next-app --example with-vitest with-vitest-app
+# or
+pnpm create next-app -- --example with-vitest with-vitest-app
+```
+
+Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).
diff --git a/examples/with-vitest/__tests__/Home.test.tsx b/examples/with-vitest/__tests__/Home.test.tsx
new file mode 100644
index 000000000000000..c6f8dc2303427a2
--- /dev/null
+++ b/examples/with-vitest/__tests__/Home.test.tsx
@@ -0,0 +1,15 @@
+import { expect, test } from 'vitest'
+import { render, screen, within } from '@testing-library/react'
+import Home from '../pages'
+
+test('home', () => {
+ render( )
+ const main = within(screen.getByRole('main'))
+ expect(
+ main.getByRole('heading', { level: 1, name: /welcome to next\.js!/i })
+ ).toBeDefined()
+
+ const footer = within(screen.getByRole('contentinfo'))
+ const link = within(footer.getByRole('link'))
+ expect(link.getByRole('img', { name: /vercel logo/i })).toBeDefined()
+})
diff --git a/examples/with-vitest/next-env.d.ts b/examples/with-vitest/next-env.d.ts
new file mode 100644
index 000000000000000..4f11a03dc6cc37f
--- /dev/null
+++ b/examples/with-vitest/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/examples/with-vitest/next.config.js b/examples/with-vitest/next.config.js
new file mode 100644
index 000000000000000..a843cbee09afaad
--- /dev/null
+++ b/examples/with-vitest/next.config.js
@@ -0,0 +1,6 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+ reactStrictMode: true,
+}
+
+module.exports = nextConfig
diff --git a/examples/with-vitest/package.json b/examples/with-vitest/package.json
new file mode 100644
index 000000000000000..973a91ffeed555a
--- /dev/null
+++ b/examples/with-vitest/package.json
@@ -0,0 +1,23 @@
+{
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "test": "vitest"
+ },
+ "dependencies": {
+ "next": "latest",
+ "react": "18.0.0",
+ "react-dom": "18.0.0"
+ },
+ "devDependencies": {
+ "@testing-library/react": "^12.1.4",
+ "@types/node": "17.0.23",
+ "@types/react": "17.0.43",
+ "@vitejs/plugin-react": "1.3.0",
+ "jsdom": "^19.0.0",
+ "typescript": "4.6.3",
+ "vitest": "0.8.4"
+ }
+}
diff --git a/examples/with-vitest/pages/_app.tsx b/examples/with-vitest/pages/_app.tsx
new file mode 100644
index 000000000000000..33da2fce548ca16
--- /dev/null
+++ b/examples/with-vitest/pages/_app.tsx
@@ -0,0 +1,6 @@
+import '../styles/globals.css'
+import type { AppProps } from 'next/app'
+
+export default function MyApp({ Component, pageProps }: AppProps) {
+ return
+}
diff --git a/examples/with-vitest/pages/index.tsx b/examples/with-vitest/pages/index.tsx
new file mode 100644
index 000000000000000..86b5b3b5bf3fdf0
--- /dev/null
+++ b/examples/with-vitest/pages/index.tsx
@@ -0,0 +1,72 @@
+import type { NextPage } from 'next'
+import Head from 'next/head'
+import Image from 'next/image'
+import styles from '../styles/Home.module.css'
+
+const Home: NextPage = () => {
+ return (
+
+
+
Create Next App
+
+
+
+
+
+
+
+
+ Get started by editing{' '}
+ pages/index.tsx
+
+
+
+
+
+
+
+ )
+}
+
+export default Home
diff --git a/examples/with-vitest/public/favicon.ico b/examples/with-vitest/public/favicon.ico
new file mode 100644
index 000000000000000..d14dbd1d8638ded
Binary files /dev/null and b/examples/with-vitest/public/favicon.ico differ
diff --git a/examples/with-vitest/public/vercel.svg b/examples/with-vitest/public/vercel.svg
new file mode 100644
index 000000000000000..fbf0e25a651c289
--- /dev/null
+++ b/examples/with-vitest/public/vercel.svg
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/examples/with-vitest/styles/Home.module.css b/examples/with-vitest/styles/Home.module.css
new file mode 100644
index 000000000000000..32a57d52f34c482
--- /dev/null
+++ b/examples/with-vitest/styles/Home.module.css
@@ -0,0 +1,116 @@
+.container {
+ padding: 0 2rem;
+}
+
+.main {
+ min-height: 100vh;
+ padding: 4rem 0;
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+}
+
+.footer {
+ display: flex;
+ flex: 1;
+ padding: 2rem 0;
+ border-top: 1px solid #eaeaea;
+ justify-content: center;
+ align-items: center;
+}
+
+.footer a {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-grow: 1;
+}
+
+.title a {
+ color: #0070f3;
+ text-decoration: none;
+}
+
+.title a:hover,
+.title a:focus,
+.title a:active {
+ text-decoration: underline;
+}
+
+.title {
+ margin: 0;
+ line-height: 1.15;
+ font-size: 4rem;
+}
+
+.title,
+.description {
+ text-align: center;
+}
+
+.description {
+ margin: 4rem 0;
+ line-height: 1.5;
+ font-size: 1.5rem;
+}
+
+.code {
+ background: #fafafa;
+ border-radius: 5px;
+ padding: 0.75rem;
+ font-size: 1.1rem;
+ font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
+ Bitstream Vera Sans Mono, Courier New, monospace;
+}
+
+.grid {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-wrap: wrap;
+ max-width: 800px;
+}
+
+.card {
+ margin: 1rem;
+ padding: 1.5rem;
+ text-align: left;
+ color: inherit;
+ text-decoration: none;
+ border: 1px solid #eaeaea;
+ border-radius: 10px;
+ transition: color 0.15s ease, border-color 0.15s ease;
+ max-width: 300px;
+}
+
+.card:hover,
+.card:focus,
+.card:active {
+ color: #0070f3;
+ border-color: #0070f3;
+}
+
+.card h2 {
+ margin: 0 0 1rem 0;
+ font-size: 1.5rem;
+}
+
+.card p {
+ margin: 0;
+ font-size: 1.25rem;
+ line-height: 1.5;
+}
+
+.logo {
+ height: 1em;
+ margin-left: 0.5rem;
+}
+
+@media (max-width: 600px) {
+ .grid {
+ width: 100%;
+ flex-direction: column;
+ }
+}
diff --git a/examples/with-vitest/styles/globals.css b/examples/with-vitest/styles/globals.css
new file mode 100644
index 000000000000000..e5e2dcc23baf192
--- /dev/null
+++ b/examples/with-vitest/styles/globals.css
@@ -0,0 +1,16 @@
+html,
+body {
+ padding: 0;
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+ Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+}
+
+a {
+ color: inherit;
+ text-decoration: none;
+}
+
+* {
+ box-sizing: border-box;
+}
diff --git a/examples/with-vitest/tsconfig.json b/examples/with-vitest/tsconfig.json
new file mode 100644
index 000000000000000..99710e857874ff8
--- /dev/null
+++ b/examples/with-vitest/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
+ "exclude": ["node_modules"]
+}
diff --git a/examples/with-vitest/vitest.config.ts b/examples/with-vitest/vitest.config.ts
new file mode 100644
index 000000000000000..e82ca6b60b1d660
--- /dev/null
+++ b/examples/with-vitest/vitest.config.ts
@@ -0,0 +1,12 @@
+///
+
+import { defineConfig } from 'vitest/config'
+import react from '@vitejs/plugin-react'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ test: {
+ environment: 'jsdom',
+ },
+})