├── CODEOWNERS
├── .npmrc
├── .nuxtrc
├── shared
├── tsconfig.json
├── README.md
├── assets
│ └── main.css
├── nuxt.config.ts
├── package.json
└── components
│ ├── Logo.vue
│ └── NuxtExample.vue
├── examples
├── ui
│ ├── sass
│ │ ├── tsconfig.json
│ │ ├── assets
│ │ │ └── styles
│ │ │ │ └── _colors.sass
│ │ ├── public
│ │ │ └── favicon.ico
│ │ ├── pages
│ │ │ └── index.vue
│ │ ├── app.vue
│ │ ├── nuxt.config.ts
│ │ └── package.json
│ ├── daisyui
│ │ ├── tsconfig.json
│ │ ├── tailwind.config.js
│ │ ├── public
│ │ │ └── favicon.ico
│ │ ├── nuxt.config.ts
│ │ ├── package.json
│ │ └── app.vue
│ ├── vuetify
│ │ ├── tsconfig.json
│ │ ├── public
│ │ │ └── favicon.ico
│ │ ├── nuxt.config.ts
│ │ ├── plugins
│ │ │ └── vuetify.ts
│ │ ├── package.json
│ │ └── app.vue
│ └── tailwindcss
│ │ ├── tsconfig.json
│ │ ├── tailwind.config.js
│ │ ├── public
│ │ ├── favicon.ico
│ │ └── mountains.jpg
│ │ ├── components
│ │ └── TButton.vue
│ │ ├── nuxt.config.ts
│ │ ├── package.json
│ │ ├── pages
│ │ ├── about.vue
│ │ └── index.vue
│ │ └── app.vue
├── advanced
│ ├── config-extends
│ │ ├── base
│ │ │ ├── server
│ │ │ │ └── api
│ │ │ │ │ └── base.ts
│ │ │ ├── utils
│ │ │ │ └── bar.ts
│ │ │ ├── components
│ │ │ │ ├── FancyButton.vue
│ │ │ │ └── BaseButton.vue
│ │ │ ├── composables
│ │ │ │ └── foo.ts
│ │ │ ├── middleware
│ │ │ │ └── foo.ts
│ │ │ ├── pages
│ │ │ │ └── foo.vue
│ │ │ ├── plugins
│ │ │ │ └── my-plugin.ts
│ │ │ ├── app.config.ts
│ │ │ └── nuxt.config.ts
│ │ ├── server
│ │ │ ├── api
│ │ │ │ └── hello.ts
│ │ │ └── tsconfig.json
│ │ ├── tsconfig.json
│ │ ├── ui
│ │ │ ├── nuxt.config.ts
│ │ │ └── components
│ │ │ │ └── Button.vue
│ │ ├── app.config.ts
│ │ ├── package.json
│ │ ├── nuxt.config.ts
│ │ ├── components
│ │ │ └── FancyButton.vue
│ │ └── pages
│ │ │ └── index.vue
│ ├── jsx
│ │ ├── tsconfig.json
│ │ ├── nuxt.config.ts
│ │ ├── components
│ │ │ └── MyComponent.tsx
│ │ ├── package.json
│ │ └── app.vue
│ ├── locale
│ │ ├── tsconfig.json
│ │ ├── nuxt.config.ts
│ │ ├── package.json
│ │ ├── app.vue
│ │ └── composables
│ │ │ └── locale.ts
│ ├── teleport
│ │ ├── tsconfig.json
│ │ ├── nuxt.config.ts
│ │ ├── package.json
│ │ ├── components
│ │ │ └── MyModal.vue
│ │ └── app.vue
│ ├── testing
│ │ ├── tsconfig.json
│ │ ├── nuxt.config.ts
│ │ ├── app.vue
│ │ ├── package.json
│ │ └── tests
│ │ │ └── basic.test.ts
│ ├── use-cookie
│ │ ├── tsconfig.json
│ │ ├── nuxt.config.ts
│ │ ├── package.json
│ │ └── app.vue
│ ├── error-handling
│ │ ├── tsconfig.json
│ │ ├── server
│ │ │ ├── tsconfig.json
│ │ │ └── middleware
│ │ │ │ └── error.ts
│ │ ├── pages
│ │ │ ├── index.vue
│ │ │ └── other.vue
│ │ ├── nuxt.config.ts
│ │ ├── middleware
│ │ │ └── error.global.ts
│ │ ├── components
│ │ │ ├── ThrowError.vue
│ │ │ └── FaultyComponent.vue
│ │ ├── package.json
│ │ ├── plugins
│ │ │ └── error.ts
│ │ ├── error.vue
│ │ └── app.vue
│ ├── module-extend-pages
│ │ ├── tsconfig.json
│ │ ├── layouts
│ │ │ └── default.vue
│ │ ├── pages
│ │ │ └── index.vue
│ │ ├── nuxt.config.ts
│ │ ├── modules
│ │ │ └── pages
│ │ │ │ ├── pages
│ │ │ │ └── test.vue
│ │ │ │ └── index.ts
│ │ └── package.json
│ └── use-custom-fetch-composable
│ │ ├── tsconfig.json
│ │ ├── nuxt.config.ts
│ │ ├── composables
│ │ └── useCustomFetch.ts
│ │ ├── package.json
│ │ ├── app.vue
│ │ └── plugins
│ │ └── customFetch.ts
├── auth
│ └── local
│ │ ├── .npmrc
│ │ ├── .env.example
│ │ ├── server
│ │ ├── tsconfig.json
│ │ └── api
│ │ │ └── secret.ts
│ │ ├── .gitignore
│ │ ├── tsconfig.json
│ │ ├── auth
│ │ ├── server
│ │ │ ├── api
│ │ │ │ └── auth
│ │ │ │ │ ├── session.get.ts
│ │ │ │ │ ├── logout.post.ts
│ │ │ │ │ ├── register.post.ts
│ │ │ │ │ └── login.post.ts
│ │ │ └── utils
│ │ │ │ ├── session.ts
│ │ │ │ └── db.ts
│ │ ├── nuxt.config.ts
│ │ ├── composables
│ │ │ └── auth.ts
│ │ └── plugins
│ │ │ └── 0.auth.ts
│ │ ├── pages
│ │ ├── index.vue
│ │ ├── secret.vue
│ │ ├── profile.vue
│ │ └── login.vue
│ │ ├── package.json
│ │ ├── nuxt.config.ts
│ │ ├── app.vue
│ │ └── README.md
├── hello-world
│ ├── tsconfig.json
│ ├── public
│ │ └── favicon.ico
│ ├── app.vue
│ └── package.json
├── experimental
│ └── wasm
│ │ ├── tsconfig.json
│ │ ├── server
│ │ ├── tsconfig.json
│ │ ├── wasm
│ │ │ ├── sum.wasm
│ │ │ └── sum.wat
│ │ └── api
│ │ │ └── sum.ts
│ │ ├── nuxt.config.ts
│ │ ├── package.json
│ │ └── app.vue
├── features
│ ├── README.md
│ ├── layouts
│ │ ├── tsconfig.json
│ │ ├── pages
│ │ │ ├── index.vue
│ │ │ ├── custom.vue
│ │ │ ├── other.vue
│ │ │ └── dynamic.vue
│ │ ├── middleware
│ │ │ └── other.ts
│ │ ├── nuxt.config.ts
│ │ ├── package.json
│ │ ├── layouts
│ │ │ ├── other.vue
│ │ │ ├── default.vue
│ │ │ └── custom.vue
│ │ └── app.vue
│ ├── auto-imports
│ │ ├── tsconfig.json
│ │ ├── utils
│ │ │ └── string.ts
│ │ ├── composables
│ │ │ └── hello.ts
│ │ ├── nuxt.config.ts
│ │ ├── components
│ │ │ └── CustomInput.vue
│ │ ├── package.json
│ │ └── app.vue
│ ├── data-fetching
│ │ ├── tsconfig.json
│ │ ├── server
│ │ │ ├── tsconfig.json
│ │ │ └── api
│ │ │ │ └── hello.ts
│ │ ├── nuxt.config.ts
│ │ ├── pages
│ │ │ ├── index.vue
│ │ │ ├── component.vue
│ │ │ └── external.vue
│ │ ├── package.json
│ │ ├── app.vue
│ │ └── components
│ │ │ └── TheQuote.vue
│ ├── meta-tags
│ │ ├── tsconfig.json
│ │ ├── nuxt.config.ts
│ │ ├── app.vue
│ │ ├── package.json
│ │ └── pages
│ │ │ ├── about.vue
│ │ │ └── index.vue
│ └── state-management
│ │ ├── tsconfig.json
│ │ ├── nuxt.config.ts
│ │ ├── package.json
│ │ └── app.vue
└── routing
│ ├── pages
│ ├── tsconfig.json
│ ├── pages
│ │ ├── about.vue
│ │ ├── index.vue
│ │ ├── parent
│ │ │ ├── b.vue
│ │ │ ├── index.vue
│ │ │ ├── reload-[id].vue
│ │ │ └── static-[id].vue
│ │ ├── catchall
│ │ │ └── [...id].vue
│ │ └── parent.vue
│ ├── nuxt.config.ts
│ ├── package.json
│ └── app.vue
│ ├── middleware
│ ├── tsconfig.json
│ ├── pages
│ │ ├── index.vue
│ │ ├── redirect.vue
│ │ ├── secret.vue
│ │ └── forbidden.vue
│ ├── middleware
│ │ ├── always-run.global.ts
│ │ └── redirect-me.ts
│ ├── nuxt.config.ts
│ ├── package.json
│ ├── plugins
│ │ └── add.ts
│ └── app.vue
│ └── universal-router
│ ├── tsconfig.json
│ ├── middleware
│ └── always-run.global.ts
│ ├── nuxt.config.ts
│ ├── package.json
│ ├── app.vue
│ └── plugins
│ └── add.ts
├── .vercelignore
├── .docs
├── .navigation.yml
├── 7.experimental
│ └── wasm.md
├── 4.advanced
│ ├── testing.md
│ ├── module-extend-pages.md
│ ├── use-cookie.md
│ ├── error-handling.md
│ ├── jsx.md
│ ├── locale.md
│ ├── use-custom-fetch-composable.md
│ ├── config-extends.md
│ └── teleport.md
├── 2.routing
│ ├── universal-router.md
│ ├── pages.md
│ └── middleware.md
├── 0.hello-world.md
└── 1.features
│ ├── 4.meta-tags.md
│ ├── 5.layouts.md
│ ├── 2.data-fetching.md
│ ├── 3.state-management.md
│ └── 1.auto-imports.md
├── .e2e
├── tsconfig.json
├── __snapshots__
│ └── ui
│ │ ├── sass.spec.ts
│ │ └── Matches-snapshot-visual-1.png
│ │ ├── daisyui.spec.ts
│ │ └── Matches-snapshot-visual-1.png
│ │ ├── vuetify.spec.ts
│ │ └── Matches-snapshot-visual-1.png
│ │ └── tailwindcss.spec.ts
│ │ └── Matches-snapshot-visual-1.png
├── augments.d.ts
├── tests
│ ├── ui
│ │ ├── sass.spec.ts
│ │ ├── daisyui.spec.ts
│ │ ├── vuetify.spec.ts
│ │ └── tailwindcss.spec.ts
│ ├── hello-world.spec.ts
│ ├── experimental
│ │ └── wasm.spec.ts
│ ├── advanced
│ │ ├── jsx.spec.ts
│ │ ├── module-extend-pages.spec.ts
│ │ ├── locale.spec.ts
│ │ ├── config-extends.spec.ts
│ │ ├── use-cookie.spec.ts
│ │ └── error-handling.spec.ts
│ ├── features
│ │ ├── auto-imports.spec.ts
│ │ ├── state-management.spec.ts
│ │ ├── data-fetching.spec.ts
│ │ └── meta-tags.spec.ts
│ └── routing
│ │ ├── universal-router.spec.ts
│ │ ├── middleware.spec.ts
│ │ └── pages.spec.ts
├── package.json
├── playwright.config.ts
├── utils
│ └── index.ts
└── README.md
├── .editorconfig
├── pnpm-workspace.yaml
├── eslint.config.mjs
├── .github
└── workflows
│ ├── provenance.yml
│ ├── playwright.yml
│ └── ci.yml
├── turbo.json
├── renovate.json
├── .scripts
├── typecheck.mjs
└── build.mjs
├── package.json
├── .gitignore
├── LICENSE
├── patches
└── @nuxtjs__tailwindcss.patch
└── README.md
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @danielroe
2 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | shell-emulator=true
2 |
--------------------------------------------------------------------------------
/.nuxtrc:
--------------------------------------------------------------------------------
1 | nitro.preset=vercel
2 | sourcemap=false
3 |
--------------------------------------------------------------------------------
/shared/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/ui/sass/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/.vercelignore:
--------------------------------------------------------------------------------
1 | **/node_modules
2 | **/.nuxt
3 | **/.output
4 | **/.turbo
5 | **/dist
6 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/base/server/api/base.ts:
--------------------------------------------------------------------------------
1 | export default () => 'base'
2 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/base/utils/bar.ts:
--------------------------------------------------------------------------------
1 | export const getBar = () => 'bar'
2 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/server/api/hello.ts:
--------------------------------------------------------------------------------
1 | export default () => 'hello'
2 |
--------------------------------------------------------------------------------
/examples/advanced/jsx/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/auth/local/.npmrc:
--------------------------------------------------------------------------------
1 | shamefully-hoist=true
2 | strict-peer-dependencies=false
3 |
--------------------------------------------------------------------------------
/examples/hello-world/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/ui/daisyui/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/ui/sass/assets/styles/_colors.sass:
--------------------------------------------------------------------------------
1 | $primary: #00DC82
2 | $secondary: #16A79E
--------------------------------------------------------------------------------
/examples/ui/vuetify/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/advanced/locale/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/advanced/teleport/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/advanced/testing/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/experimental/wasm/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/features/README.md:
--------------------------------------------------------------------------------
1 | # Nuxt Examples
2 |
3 | 👉 https://nuxt.com/docs/examples
4 |
--------------------------------------------------------------------------------
/examples/features/layouts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/routing/pages/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/ui/tailwindcss/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/advanced/use-cookie/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/auth/local/.env.example:
--------------------------------------------------------------------------------
1 | NUXT_AUTH_PASSWORD=secretsecretsecretsecretsecretsecretsecret
2 |
--------------------------------------------------------------------------------
/examples/features/auto-imports/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/features/data-fetching/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/features/meta-tags/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/routing/middleware/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/ui/tailwindcss/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | darkMode: 'class',
3 | }
4 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/advanced/error-handling/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/auth/local/server/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../.nuxt/tsconfig.server.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/features/state-management/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json",
3 | }
4 |
--------------------------------------------------------------------------------
/examples/routing/universal-router/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/advanced/module-extend-pages/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/experimental/wasm/server/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../.nuxt/tsconfig.server.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/experimental/wasm/server/wasm/sum.wasm:
--------------------------------------------------------------------------------
1 | asm ` sum
2 | j name
--------------------------------------------------------------------------------
/examples/routing/pages/pages/about.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | About
4 |
5 |
6 |
--------------------------------------------------------------------------------
/examples/routing/pages/pages/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Home
4 |
5 |
6 |
--------------------------------------------------------------------------------
/examples/ui/daisyui/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [require('daisyui')],
3 | }
4 |
--------------------------------------------------------------------------------
/examples/features/auto-imports/utils/string.ts:
--------------------------------------------------------------------------------
1 | export const upperCase = (str: string) => str.toUpperCase()
2 |
--------------------------------------------------------------------------------
/examples/features/data-fetching/server/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../.nuxt/tsconfig.server.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/routing/middleware/pages/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Home
4 |
5 |
6 |
--------------------------------------------------------------------------------
/shared/README.md:
--------------------------------------------------------------------------------
1 | # @nuxt/examples-ui
2 |
3 | Shared UI for Nuxt examples on https://nuxt.com/docs/examples
4 |
--------------------------------------------------------------------------------
/.docs/.navigation.yml:
--------------------------------------------------------------------------------
1 | title: Examples
2 | titleTemplate: '%s · Nuxt Examples'
3 | icon: i-lucide-app-window-mac
4 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/server/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../.nuxt/tsconfig.server.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/advanced/error-handling/server/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../.nuxt/tsconfig.server.json"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/features/layouts/pages/index.vue:
--------------------------------------------------------------------------------
1 |
2 | Welcome to Layouts example
3 |
4 |
--------------------------------------------------------------------------------
/examples/routing/pages/pages/parent/b.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Parent/b
4 |
5 |
6 |
--------------------------------------------------------------------------------
/examples/routing/pages/pages/parent/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Parent/index
4 |
5 |
6 |
--------------------------------------------------------------------------------
/examples/ui/sass/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nuxt/examples/HEAD/examples/ui/sass/public/favicon.ico
--------------------------------------------------------------------------------
/examples/hello-world/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nuxt/examples/HEAD/examples/hello-world/public/favicon.ico
--------------------------------------------------------------------------------
/examples/ui/daisyui/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nuxt/examples/HEAD/examples/ui/daisyui/public/favicon.ico
--------------------------------------------------------------------------------
/examples/ui/vuetify/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nuxt/examples/HEAD/examples/ui/vuetify/public/favicon.ico
--------------------------------------------------------------------------------
/examples/advanced/error-handling/pages/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Home
4 |
5 |
6 |
--------------------------------------------------------------------------------
/examples/ui/tailwindcss/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nuxt/examples/HEAD/examples/ui/tailwindcss/public/favicon.ico
--------------------------------------------------------------------------------
/examples/advanced/error-handling/pages/other.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Other Page
4 |
5 |
6 |
--------------------------------------------------------------------------------
/examples/features/layouts/middleware/other.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtRouteMiddleware(() => {
2 | setPageLayout('other')
3 | })
4 |
--------------------------------------------------------------------------------
/examples/ui/tailwindcss/public/mountains.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nuxt/examples/HEAD/examples/ui/tailwindcss/public/mountains.jpg
--------------------------------------------------------------------------------
/.e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "paths": {
5 | "@/*": ["./*"]
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/examples/auth/local/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.log*
3 | .nuxt
4 | .nitro
5 | .cache
6 | .output
7 | .env
8 | dist
9 | .data
10 |
--------------------------------------------------------------------------------
/examples/auth/local/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | // https://nuxt.com/docs/guide/concepts/typescript
3 | "extends": "./.nuxt/tsconfig.json"
4 | }
5 |
--------------------------------------------------------------------------------
/examples/routing/pages/pages/catchall/[...id].vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | test-{{ $route.params.id }}
4 |
5 |
6 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/base/components/FancyButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/examples/features/auto-imports/composables/hello.ts:
--------------------------------------------------------------------------------
1 | export function sayHello(message = 'World') {
2 | alert(`Hello ${upperCase(message)}!`)
3 | }
4 |
--------------------------------------------------------------------------------
/examples/features/data-fetching/server/api/hello.ts:
--------------------------------------------------------------------------------
1 | export default defineEventHandler(() => {
2 | return {
3 | hello: 'world',
4 | }
5 | })
6 |
--------------------------------------------------------------------------------
/shared/assets/main.css:
--------------------------------------------------------------------------------
1 | @import "tailwindcss";
2 | @import "@nuxt/ui";
3 | @source "../components/Logo.vue";
4 | @source "../components/NuxtExample.vue";
5 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/base/composables/foo.ts:
--------------------------------------------------------------------------------
1 | import { useState } from '#imports'
2 |
3 | export const useFoo = () => useState('foo', () => 'foo')
4 |
--------------------------------------------------------------------------------
/examples/routing/middleware/middleware/always-run.global.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtRouteMiddleware(() => {
2 | console.log('running global middleware')
3 | })
4 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/base/middleware/foo.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtRouteMiddleware(() => {
2 | console.log('Hello from extended middleware !')
3 | })
4 |
--------------------------------------------------------------------------------
/examples/advanced/use-custom-fetch-composable/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | // https://nuxt.com/docs/guide/concepts/typescript
3 | "extends": "./.nuxt/tsconfig.json"
4 | }
5 |
--------------------------------------------------------------------------------
/examples/routing/universal-router/middleware/always-run.global.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtRouteMiddleware(() => {
2 | console.log('running global middleware')
3 | })
4 |
--------------------------------------------------------------------------------
/.e2e/__snapshots__/ui/sass.spec.ts/Matches-snapshot-visual-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nuxt/examples/HEAD/.e2e/__snapshots__/ui/sass.spec.ts/Matches-snapshot-visual-1.png
--------------------------------------------------------------------------------
/.e2e/__snapshots__/ui/daisyui.spec.ts/Matches-snapshot-visual-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nuxt/examples/HEAD/.e2e/__snapshots__/ui/daisyui.spec.ts/Matches-snapshot-visual-1.png
--------------------------------------------------------------------------------
/.e2e/__snapshots__/ui/vuetify.spec.ts/Matches-snapshot-visual-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nuxt/examples/HEAD/.e2e/__snapshots__/ui/vuetify.spec.ts/Matches-snapshot-visual-1.png
--------------------------------------------------------------------------------
/examples/advanced/jsx/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | })
8 |
--------------------------------------------------------------------------------
/examples/advanced/locale/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | })
8 |
--------------------------------------------------------------------------------
/examples/routing/pages/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | })
8 |
--------------------------------------------------------------------------------
/examples/routing/pages/pages/parent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Parent
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/examples/advanced/teleport/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | })
8 |
--------------------------------------------------------------------------------
/examples/advanced/testing/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | })
8 |
--------------------------------------------------------------------------------
/examples/advanced/use-cookie/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | })
8 |
--------------------------------------------------------------------------------
/examples/features/layouts/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | })
8 |
--------------------------------------------------------------------------------
/examples/features/meta-tags/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | })
8 |
--------------------------------------------------------------------------------
/examples/routing/middleware/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | })
8 |
--------------------------------------------------------------------------------
/.e2e/__snapshots__/ui/tailwindcss.spec.ts/Matches-snapshot-visual-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nuxt/examples/HEAD/.e2e/__snapshots__/ui/tailwindcss.spec.ts/Matches-snapshot-visual-1.png
--------------------------------------------------------------------------------
/examples/advanced/error-handling/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | })
8 |
--------------------------------------------------------------------------------
/examples/auth/local/auth/server/api/auth/session.get.ts:
--------------------------------------------------------------------------------
1 | export default eventHandler(async (event) => {
2 | const session = await useAuthSession(event)
3 | return session.data
4 | })
5 |
--------------------------------------------------------------------------------
/examples/features/auto-imports/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | })
8 |
--------------------------------------------------------------------------------
/examples/features/data-fetching/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | })
8 |
--------------------------------------------------------------------------------
/examples/features/state-management/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | })
8 |
--------------------------------------------------------------------------------
/examples/routing/universal-router/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | })
8 |
--------------------------------------------------------------------------------
/.e2e/augments.d.ts:
--------------------------------------------------------------------------------
1 | import type { useNuxtApp } from 'nuxt/app'
2 |
3 | declare global {
4 | interface Window {
5 | useNuxtApp?: typeof useNuxtApp
6 | }
7 | }
8 |
9 | export {}
10 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/base/components/BaseButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/examples/advanced/testing/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello Nuxt!
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/ui/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | components: [
3 | { path: './components', prefix: 'UI' },
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | })
8 |
--------------------------------------------------------------------------------
/examples/advanced/error-handling/middleware/error.global.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtRouteMiddleware((to) => {
2 | if ('middleware' in to.query) {
3 | return showError('error in middleware')
4 | }
5 | })
6 |
--------------------------------------------------------------------------------
/examples/advanced/error-handling/server/middleware/error.ts:
--------------------------------------------------------------------------------
1 | export default defineEventHandler((event) => {
2 | if ('api' in getQuery(event)) {
3 | throw new Error('Server middleware error')
4 | }
5 | })
6 |
--------------------------------------------------------------------------------
/examples/advanced/error-handling/components/ThrowError.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Should never see this
7 |
8 |
--------------------------------------------------------------------------------
/examples/advanced/module-extend-pages/layouts/default.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/app.config.ts:
--------------------------------------------------------------------------------
1 | export default defineAppConfig({
2 | foo: 'user',
3 | bar: 'user',
4 | baz: 'base',
5 | array: [
6 | 'user',
7 | 'user',
8 | 'user',
9 | ],
10 | })
11 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/base/pages/foo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello from extended page !
4 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/base/plugins/my-plugin.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtPlugin((/* nuxtApp */) => {
2 | return {
3 | provide: {
4 | myPlugin: () => 'String generated from my auto-imported plugin!',
5 | },
6 | }
7 | })
8 |
--------------------------------------------------------------------------------
/examples/advanced/module-extend-pages/pages/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Go to
4 |
8 | Test Page
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/auth/local/server/api/secret.ts:
--------------------------------------------------------------------------------
1 | export default eventHandler(async (event) => {
2 | const auth = await requireAuthSession(event)
3 | return {
4 | message: `You are accessing secret api with email: ${auth.data.email}`,
5 | }
6 | })
7 |
--------------------------------------------------------------------------------
/examples/routing/middleware/pages/redirect.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | You should never see this page
4 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_size = 2
5 | indent_style = space
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
--------------------------------------------------------------------------------
/examples/auth/local/auth/server/api/auth/logout.post.ts:
--------------------------------------------------------------------------------
1 | export default eventHandler(async (event) => {
2 | const session = await useAuthSession(event)
3 | await session.clear()
4 | return {
5 | message: 'Successfully logged out!',
6 | }
7 | })
8 |
--------------------------------------------------------------------------------
/examples/features/layouts/pages/custom.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 | Custom layout defined with definePageMeta
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/advanced/module-extend-pages/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 | modules: [
6 | '~/modules/pages/index',
7 | ],
8 |
9 | compatibilityDate: '2024-04-03',
10 | })
11 |
--------------------------------------------------------------------------------
/examples/features/layouts/pages/other.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 | The layout is set within middleware/other.ts.
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/routing/middleware/pages/secret.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | You've landed on a page that wasn't in the menu!
4 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/.docs/7.experimental/wasm.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: 'WASM'
4 | description: 'This example demonstrates the server-side support of WebAssembly in Nuxt.'
5 | ---
6 |
7 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/experimental/wasm" file="app.vue"}
8 |
--------------------------------------------------------------------------------
/examples/advanced/use-custom-fetch-composable/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | runtimeConfig: {
7 | baseURL: '',
8 | },
9 |
10 | compatibilityDate: '2024-04-03',
11 | })
12 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - shared
3 | - examples/**
4 | - .e2e
5 | - '!**/.vercel/**'
6 | ignoredBuiltDependencies:
7 | - esbuild
8 | - vue-demi
9 | patchedDependencies:
10 | '@nuxtjs/tailwindcss': patches/@nuxtjs__tailwindcss.patch
11 |
12 |
--------------------------------------------------------------------------------
/examples/experimental/wasm/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | nitro: {
8 | experimental: {
9 | wasm: true,
10 | },
11 | },
12 | })
13 |
--------------------------------------------------------------------------------
/examples/routing/pages/pages/parent/reload-[id].vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Child reloaded: {{ reloads }}
4 |
5 |
6 |
7 |
13 |
--------------------------------------------------------------------------------
/examples/ui/vuetify/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | css: [
3 | 'vuetify/lib/styles/main.sass',
4 | '@mdi/font/css/materialdesignicons.min.css',
5 | ],
6 | build: {
7 | transpile: ['vuetify'],
8 | },
9 |
10 | compatibilityDate: '2024-04-03',
11 | })
12 |
--------------------------------------------------------------------------------
/.docs/4.advanced/testing.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: Testing
4 | description: 'This example shows how to test your Nuxt application.'
5 | ---
6 |
7 | :read-more{to="/docs/getting-started/testing"}
8 |
9 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/advanced/testing" file="app.vue"}
10 |
--------------------------------------------------------------------------------
/examples/experimental/wasm/server/wasm/sum.wat:
--------------------------------------------------------------------------------
1 | ;; https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format
2 | ;; https://webassembly.github.io/wabt/demo/wat2wasm/
3 | (module
4 | (func (export "sum") (param i32 i32) (result i32)
5 | local.get 0
6 | local.get 1
7 | i32.add))
8 |
--------------------------------------------------------------------------------
/examples/features/auto-imports/components/CustomInput.vue:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/features/meta-tags/app.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/examples/ui/sass/pages/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Welcome to Nuxt + SASS
4 |
A simple example on how to use SAAS with a colors.sass file.
5 |
6 |
7 |
8 |
14 |
--------------------------------------------------------------------------------
/.docs/2.routing/universal-router.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: 'Universal Router'
4 | description: 'This example demonstrates Nuxt universal routing utilities without depending on `pages/` and `vue-router`.'
5 | ---
6 |
7 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/routing/universal-router" file="app.vue"}
8 |
--------------------------------------------------------------------------------
/examples/ui/sass/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Nuxt with SASS
5 |
6 |
7 |
8 |
9 |
10 |
16 |
--------------------------------------------------------------------------------
/examples/advanced/jsx/components/MyComponent.tsx:
--------------------------------------------------------------------------------
1 | export default defineComponent({
2 | props: {
3 | message: String,
4 | },
5 | // @ts-expect-error investigate why `props` is not typed
6 | render(props) {
7 | return (
8 |
9 | { props.message }
10 |
11 | )
12 | },
13 | })
14 |
--------------------------------------------------------------------------------
/examples/advanced/module-extend-pages/modules/pages/pages/test.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Go to
5 |
9 | Homepage
10 |
11 |
12 |
Test page added by module
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.docs/0.hello-world.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: Hello World
4 | description: 'A minimal Nuxt application only requires the `app.vue` and `nuxt.config.js` files.'
5 | ---
6 |
7 | :read-more{to="/docs/getting-started/introduction"}
8 |
9 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/hello-world" file="app.vue"}
10 |
--------------------------------------------------------------------------------
/.docs/2.routing/pages.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: 'Pages'
4 | description: 'This example shows how to use the pages/ directory to create application routes.'
5 | ---
6 |
7 | :read-more{to="/docs/guide/directory-structure/pages"}
8 |
9 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/routing/pages" file="app.vue"}
10 |
--------------------------------------------------------------------------------
/examples/advanced/jsx/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jsx",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/routing/pages/pages/parent/static-[id].vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Child reloaded: {{ reloads }}
4 |
5 |
6 |
7 |
16 |
--------------------------------------------------------------------------------
/examples/routing/middleware/pages/forbidden.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Forbidden
4 |
5 |
6 |
7 |
16 |
--------------------------------------------------------------------------------
/examples/routing/pages/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pages",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/advanced/locale/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "locale",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/advanced/teleport/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "teleport",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/auth/local/pages/index.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 | Welcome to the example of Nuxt with Local Authentication.
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/experimental/wasm/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wasm",
3 | "private": true,
4 | "devDependencies": {
5 | "@nuxt/examples-ui": "latest",
6 | "nuxt": "^3.16.2",
7 | "vue": "3.5.13"
8 | },
9 | "scripts": {
10 | "dev": "nuxi dev",
11 | "build": "nuxi build",
12 | "start": "nuxi preview"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/features/data-fetching/pages/index.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 | Result of :
12 |
13 |
{{ data }}
14 |
15 |
16 |
--------------------------------------------------------------------------------
/examples/features/layouts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "layouts",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/shared/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | import { createResolver } from 'nuxt/kit'
2 |
3 | const resolver = createResolver(import.meta.url)
4 |
5 | export default defineNuxtConfig({
6 | modules: [
7 | '@nuxt/ui',
8 | ],
9 |
10 | css: [
11 | resolver.resolve('./assets/main.css'),
12 | ],
13 |
14 | compatibilityDate: '2024-04-03',
15 | })
16 |
--------------------------------------------------------------------------------
/examples/advanced/use-cookie/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "use-cookie",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/routing/middleware/middleware/redirect-me.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtRouteMiddleware((to) => {
2 | const { $config } = useNuxtApp()
3 | if ($config) {
4 | console.log('Accessed runtime config within middleware.')
5 | }
6 | console.log('Heading to', to.path, 'but I think we should go somewhere else...')
7 | return '/secret'
8 | })
9 |
--------------------------------------------------------------------------------
/examples/routing/middleware/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "middleware",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/.docs/1.features/4.meta-tags.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: Meta Tags
4 | description: 'This example shows how to use the Nuxt helpers and composables for SEO and meta management.'
5 | ---
6 |
7 | :read-more{to="/docs/getting-started/seo-meta"}
8 |
9 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/features/meta-tags/" file="app.vue"}
10 |
--------------------------------------------------------------------------------
/examples/features/auto-imports/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "auto-imports",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/features/data-fetching/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "data-fetching",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/features/meta-tags/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "meta-tags",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "node .output/server"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "config-extends",
3 | "private": true,
4 | "scripts": {
5 | "dev": "nuxi dev",
6 | "build": "nuxi build",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/advanced/error-handling/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "error-handling",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/hello-world/app.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 | Hello Nuxt {{ version }}!
8 |
9 |
10 |
11 |
18 |
--------------------------------------------------------------------------------
/examples/routing/universal-router/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "universal-router",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | './ui',
5 | './base',
6 | ],
7 | runtimeConfig: {
8 | public: {
9 | theme: {
10 | primaryColor: 'user_primary',
11 | },
12 | },
13 | },
14 |
15 | compatibilityDate: '2024-04-03',
16 | })
17 |
--------------------------------------------------------------------------------
/examples/advanced/use-custom-fetch-composable/composables/useCustomFetch.ts:
--------------------------------------------------------------------------------
1 | import type { UseFetchOptions } from 'nuxt/app'
2 |
3 | export function useCustomFetch(
4 | url: string | (() => string),
5 | options: UseFetchOptions = {},
6 | ) {
7 | return useFetch(url, {
8 | ...options,
9 | $fetch: useNuxtApp().$customFetch,
10 | })
11 | }
12 |
--------------------------------------------------------------------------------
/examples/auth/local/auth/server/api/auth/register.post.ts:
--------------------------------------------------------------------------------
1 | export default eventHandler(async (event) => {
2 | const { email, password } = await readBody(event)
3 | await createUser({
4 | email,
5 | name: email.split('@')[0],
6 | password: await hash(password),
7 | })
8 | return {
9 | message: 'Successfully registered!',
10 | }
11 | })
12 |
--------------------------------------------------------------------------------
/examples/features/state-management/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "state-management",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/routing/middleware/plugins/add.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtPlugin(() => {
2 | addRouteMiddleware('global-test', () => {
3 | console.log('this global middleware was added in a plugin')
4 | }, { global: true })
5 |
6 | addRouteMiddleware('named-test', () => {
7 | console.log('this named middleware was added in a plugin')
8 | })
9 | })
10 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/base/app.config.ts:
--------------------------------------------------------------------------------
1 | export default defineAppConfig({
2 | bar: 'base',
3 | baz: 'base',
4 | array: () => [
5 | 'base',
6 | 'base',
7 | 'base',
8 | ],
9 | arrayNested: {
10 | nested: {
11 | array: [
12 | 'base',
13 | 'base',
14 | 'base',
15 | ],
16 | },
17 | },
18 | })
19 |
--------------------------------------------------------------------------------
/examples/advanced/module-extend-pages/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "module-extend-pages",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/.e2e/tests/ui/sass.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('sass'))
5 | test.beforeEach(async ({ page }) => {
6 | await page.goto('/')
7 | })
8 |
9 | test('Matches snapshot @visual', async ({ page }) => {
10 | await expect(page).toHaveScreenshot()
11 | })
12 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/ui/components/Button.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/examples/auth/local/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "local-auth",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "uncrypto": "^0.1.3",
13 | "vue": "3.5.13"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/.docs/4.advanced/module-extend-pages.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: 'Module Extend Pages'
4 | description: 'This example defines a new `test` page using `extendPages` within a module.'
5 | ---
6 |
7 | :read-more{to="/docs/guide/going-further/modules"}
8 |
9 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/advanced/module-extend-pages" file="pages/index.vue"}
10 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/base/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | imports: {
3 | dirs: ['utils'],
4 | },
5 | runtimeConfig: {
6 | public: {
7 | theme: {
8 | primaryColor: 'base_primary',
9 | secondaryColor: 'base_secondary',
10 | },
11 | },
12 | },
13 |
14 | compatibilityDate: '2024-04-03',
15 | })
16 |
--------------------------------------------------------------------------------
/examples/hello-world/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hello-world",
3 | "private": true,
4 | "scripts": {
5 | "dev": "nuxi dev",
6 | "build": "nuxi build",
7 | "generate": "nuxi generate",
8 | "start": "nuxi preview"
9 | },
10 | "devDependencies": {
11 | "@nuxt/examples-ui": "latest",
12 | "nuxt": "^3.16.2",
13 | "vue": "3.5.13"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/.docs/4.advanced/use-cookie.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: 'useCookie'
4 | description: 'This example shows how to use the useCookie API to persist small amounts of data that both client and server can use.'
5 | ---
6 |
7 | :read-more{to="/docs/api/composables/use-cookie"}
8 |
9 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/advanced/use-cookie" file="app.vue"}
10 |
--------------------------------------------------------------------------------
/.e2e/tests/ui/daisyui.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('daisyui'))
5 | test.beforeEach(async ({ page }) => {
6 | await page.goto('/')
7 | })
8 |
9 | test('Matches snapshot @visual', async ({ page }) => {
10 | await expect(page).toHaveScreenshot()
11 | })
12 |
--------------------------------------------------------------------------------
/.e2e/tests/ui/vuetify.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('vuetify'))
5 | test.beforeEach(async ({ page }) => {
6 | await page.goto('/')
7 | })
8 |
9 | test('Matches snapshot @visual', async ({ page }) => {
10 | await expect(page).toHaveScreenshot()
11 | })
12 |
--------------------------------------------------------------------------------
/examples/advanced/use-custom-fetch-composable/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "use-custom-fetch-composable",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/examples-ui": "latest",
11 | "nuxt": "^3.16.2",
12 | "vue": "3.5.13"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/ui/daisyui/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | modules: [
3 | '@nuxtjs/tailwindcss',
4 | '@nuxtjs/color-mode',
5 | ],
6 |
7 | colorMode: {
8 | preference: 'system', // default theme
9 | dataValue: 'theme', // activate data-theme in tag
10 | classSuffix: '',
11 | },
12 |
13 | compatibilityDate: '2024-04-03',
14 | })
15 |
--------------------------------------------------------------------------------
/examples/ui/sass/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | extends: [
3 | '@nuxt/examples-ui',
4 | ],
5 |
6 | compatibilityDate: '2024-04-03',
7 | vite: {
8 | css: {
9 | preprocessorOptions: {
10 | sass: {
11 | additionalData: '@use "@/assets/styles/_colors.sass" as *\n',
12 | },
13 | },
14 | },
15 | },
16 | })
17 |
--------------------------------------------------------------------------------
/.docs/1.features/5.layouts.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: Layouts
4 | description: 'This example shows how to define default and custom layouts.'
5 | ---
6 |
7 | :read-more{to="/docs/getting-started/views#layouts"}
8 | :read-more{to="/docs/guide/directory-structure/layouts"}
9 |
10 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/features/layouts" file="pages/index.vue"}
11 |
--------------------------------------------------------------------------------
/.docs/4.advanced/error-handling.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: 'Error Handling'
4 | description: 'This example shows how to handle errors in different contexts: pages, plugins, components and middleware.'
5 | ---
6 |
7 | :read-more{to="/docs/getting-started/error-handling"}
8 |
9 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/advanced/error-handling" file="app.vue"}
10 |
--------------------------------------------------------------------------------
/.e2e/tests/ui/tailwindcss.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('tailwindcss'))
5 | test.beforeEach(async ({ page }) => {
6 | await page.goto('/')
7 | })
8 |
9 | test('Matches snapshot @visual', async ({ page }) => {
10 | await expect(page).toHaveScreenshot()
11 | })
12 |
--------------------------------------------------------------------------------
/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | import { createConfigForNuxt } from '@nuxt/eslint-config/flat'
2 |
3 | export default createConfigForNuxt({
4 | features: {
5 | tooling: true,
6 | stylistic: true,
7 | },
8 | }, {
9 | rules: {
10 | 'vue/multi-word-component-names': 'off',
11 | '@typescript-eslint/ban-types': 'off',
12 | '@typescript-eslint/no-unused-vars': 'warn',
13 | },
14 | })
15 |
--------------------------------------------------------------------------------
/examples/ui/tailwindcss/components/TButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Button
4 |
5 |
6 |
7 |
18 |
--------------------------------------------------------------------------------
/examples/ui/vuetify/plugins/vuetify.ts:
--------------------------------------------------------------------------------
1 | import { createVuetify } from 'vuetify'
2 | import * as components from 'vuetify/components'
3 | import * as directives from 'vuetify/directives'
4 |
5 | export default defineNuxtPlugin((nuxtApp) => {
6 | const vuetify = createVuetify({
7 | ssr: true,
8 | components,
9 | directives,
10 | })
11 |
12 | nuxtApp.vueApp.use(vuetify)
13 | })
14 |
--------------------------------------------------------------------------------
/.docs/2.routing/middleware.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: 'Middleware'
4 | description: 'This example shows how to add route middleware with the middleware/ directory or with a plugin, and how to use them globally or per page.'
5 | ---
6 |
7 | :read-more{to="/docs/guide/directory-structure/middleware"}
8 |
9 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/routing/middleware" file="app.vue"}
10 |
--------------------------------------------------------------------------------
/.docs/4.advanced/jsx.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: 'JSX / TSX'
4 | description: 'This example shows how to use JSX syntax with typescript in Nuxt pages and components.'
5 | ---
6 |
7 | :read-more{icon="i-simple-icons-vuedotjs" to="https://vuejs.org/guide/extras/render-function.html#jsx-tsx" target="_blank"}
8 |
9 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/advanced/jsx" file="app.vue"}
10 |
--------------------------------------------------------------------------------
/.e2e/tests/hello-world.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('hello-world'))
5 | test.beforeEach(async ({ page }) => {
6 | await page.goto('/')
7 | })
8 |
9 | test('"Hello Nuxt 3!" is visible', async ({ page }) => {
10 | await expect(page.getByText('Hello Nuxt 3!')).toBeVisible()
11 | })
12 |
--------------------------------------------------------------------------------
/examples/features/meta-tags/pages/about.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
About page
11 |
This is the about page using useSeoMeta() composable
12 |
13 | Back home
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/examples/auth/local/pages/secret.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 | Secret Page!
16 |
17 | API Response: {{ secretData }}
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/examples/ui/tailwindcss/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | modules: [
3 | '@nuxtjs/tailwindcss',
4 | '@nuxtjs/color-mode',
5 | ],
6 | colorMode: {
7 | classSuffix: '',
8 | },
9 |
10 | compatibilityDate: '2024-04-03',
11 | // https://tailwindcss.nuxtjs.org
12 | tailwindcss: {
13 | // Expose tailwind config with #tailwind-config
14 | exposeConfig: true,
15 | },
16 | })
17 |
--------------------------------------------------------------------------------
/.docs/1.features/2.data-fetching.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: Data Fetching
4 | description: 'This example demonstrates data fetching with Nuxt using built-in composables and API routes.'
5 | ---
6 |
7 | :read-more{to="/docs/getting-started/data-fetching"}
8 | :read-more{to="/docs/guide/directory-structure/server"}
9 |
10 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/features/data-fetching" file="app.vue"}
11 |
--------------------------------------------------------------------------------
/examples/ui/sass/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sass",
3 | "version": "1.0.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "nuxt dev",
7 | "build": "nuxt build",
8 | "start": "nuxt start",
9 | "generate": "nuxt generate"
10 | },
11 | "devDependencies": {
12 | "@nuxt/examples-ui": "latest",
13 | "nuxt": "^3.16.2",
14 | "sass-embedded": "^1.89.2",
15 | "vue": "3.5.13"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/advanced/testing/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "testing",
3 | "private": true,
4 | "scripts": {
5 | "build": "nuxi build",
6 | "dev": "nuxi dev",
7 | "start": "nuxi preview",
8 | "test": "vitest run"
9 | },
10 | "devDependencies": {
11 | "@nuxt/examples-ui": "latest",
12 | "@nuxt/test-utils": "^3.17.2",
13 | "nuxt": "^3.16.2",
14 | "vitest": "3.1.2",
15 | "vue": "3.5.13"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/experimental/wasm/server/api/sum.ts:
--------------------------------------------------------------------------------
1 | import { defineEventHandler, defineLazyEventHandler } from 'h3'
2 |
3 | export default defineLazyEventHandler(async () => {
4 | // @ts-expect-error TODO: https://github.com/nuxt/nuxt/issues/14131
5 | const { sum } = await import('~/server/wasm/sum.wasm')
6 |
7 | return defineEventHandler((event) => {
8 | const { a = 0, b = 0 } = getQuery(event)
9 | return { sum: sum(a, b) }
10 | })
11 | })
12 |
--------------------------------------------------------------------------------
/examples/ui/vuetify/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vuetify",
3 | "version": "1.0.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "nuxt dev",
7 | "build": "nuxt build",
8 | "start": "nuxt start",
9 | "generate": "nuxt generate"
10 | },
11 | "devDependencies": {
12 | "@mdi/font": "^7.4.47",
13 | "nuxt": "^3.16.2",
14 | "sass-embedded": "^1.89.2",
15 | "vue": "3.5.13",
16 | "vuetify": "^3.3.23"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/.docs/1.features/3.state-management.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: State Management
4 | description: 'This example shows how to use the `useState` composable to create a reactive and SSR-friendly shared state across components.'
5 | ---
6 |
7 | :read-more{to="/docs/getting-started/state-management"}
8 | :read-more{to="/docs/api/composables/use-state"}
9 |
10 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/features/state-management" file="app.vue"}
11 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/components/FancyButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
17 |
--------------------------------------------------------------------------------
/.e2e/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "e2e",
3 | "scripts": {
4 | "test": "playwright test --grep-invert @visual",
5 | "test:all": "playwright test",
6 | "test:visual": "playwright test --grep @visual",
7 | "test:visual:update-snapshots": "playwright test --grep @visual --update-snapshots",
8 | "codegen": "playwright codegen",
9 | "ui": "playwright test --ui"
10 | },
11 | "devDependencies": {
12 | "@playwright/test": "1.53.2"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/features/layouts/layouts/other.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
23 |
--------------------------------------------------------------------------------
/examples/advanced/module-extend-pages/modules/pages/index.ts:
--------------------------------------------------------------------------------
1 | import { createResolver, defineNuxtModule, extendPages } from 'nuxt/kit'
2 |
3 | export default defineNuxtModule({
4 | setup() {
5 | const resolver = createResolver(import.meta.url)
6 | extendPages((pages) => {
7 | // Add /test page
8 | pages.push({
9 | name: 'Test',
10 | path: '/test',
11 | file: resolver.resolve('./pages/test.vue'),
12 | })
13 | })
14 | },
15 | })
16 |
--------------------------------------------------------------------------------
/examples/ui/tailwindcss/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tailwindcss",
3 | "version": "1.0.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "nuxt dev",
7 | "build": "nuxt build",
8 | "start": "nuxt start",
9 | "generate": "nuxt generate"
10 | },
11 | "devDependencies": {
12 | "@nuxtjs/color-mode": "^3.5.2",
13 | "@nuxtjs/tailwindcss": "^6.13.2",
14 | "nuxt": "^3.16.2",
15 | "tailwindcss": "3.4.17",
16 | "vue": "3.5.13"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/.docs/4.advanced/locale.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: 'Locale'
4 | description: "This example shows how to define a locale composable to handle the application's locale, both server and client side."
5 | ---
6 |
7 | ::callout{icon="i-ph-info-duotone"}
8 | You can right-click to "View Page Source" and see that Nuxt renders the correct date in SSR based on the visitor's locale.
9 | ::
10 |
11 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/advanced/locale" file="app.vue"}
12 |
--------------------------------------------------------------------------------
/examples/features/layouts/layouts/default.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
23 |
--------------------------------------------------------------------------------
/examples/ui/daisyui/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "daisyui",
3 | "version": "1.0.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "nuxt dev",
7 | "build": "nuxt build",
8 | "start": "nuxt start",
9 | "generate": "nuxt generate"
10 | },
11 | "devDependencies": {
12 | "@nuxtjs/color-mode": "^3.5.2",
13 | "@nuxtjs/tailwindcss": "^6.13.2",
14 | "daisyui": "^4.12.24",
15 | "nuxt": "^3.16.2",
16 | "tailwindcss": "3.4.17",
17 | "vue": "3.5.13"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/.docs/4.advanced/use-custom-fetch-composable.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: 'Use Custom Fetch Composable'
4 | description: 'This example shows a convenient wrapper for the useFetch composable from nuxt. It allows you to customize the fetch request with default values and user authentication token.'
5 | ---
6 |
7 | :read-more{to="/docs/guide/recipes/custom-usefetch"}
8 |
9 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/advanced/use-custom-fetch-composable" file="composables/useCustomFetch.ts"}
10 |
--------------------------------------------------------------------------------
/.e2e/tests/experimental/wasm.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('wasm'))
5 | test.beforeEach(async ({ page }) => {
6 | await page.goto('/')
7 | })
8 |
9 | test('Sum is correctly calculated', async ({ page }) => {
10 | await expect(page.getByText('a = 100')).toBeVisible()
11 | await expect(page.getByText('b = 250')).toBeVisible()
12 | await expect(page.getByText('100 + 250 = 350')).toBeVisible()
13 | })
14 |
--------------------------------------------------------------------------------
/examples/features/auto-imports/app.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 | Demo with auto imports
12 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.docs/4.advanced/config-extends.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: 'Layers'
4 | description: 'This example shows how to use the extends key in `nuxt.config.ts`.'
5 | ---
6 |
7 | This example shows how to use the `extends` key in `nuxt.config.ts` to use the `base/` directory as a base Nuxt application, and use its components, composables or config and override them if necessary.
8 |
9 | :read-more{to="/docs/getting-started/layers"}
10 |
11 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/advanced/config-extends" file="nuxt.config.ts"}
12 |
--------------------------------------------------------------------------------
/examples/features/data-fetching/app.vue:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/.github/workflows/provenance.yml:
--------------------------------------------------------------------------------
1 | name: ci
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - main
10 | permissions:
11 | contents: read
12 | jobs:
13 | check-provenance:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v4
17 | with:
18 | fetch-depth: 0
19 | - name: Check provenance downgrades
20 | uses: danielroe/provenance-action@a5a718233ca12eff67651fcf29a030bbbd5b3ca1 # v0.1.0
21 | with:
22 | fail-on-provenance-change: true
23 |
--------------------------------------------------------------------------------
/examples/features/data-fetching/pages/component.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
Example of data fetching inside a component:
8 |
9 |
10 | Previous
11 | -
12 | Next
13 |
14 |
15 |
16 |
20 | Back to Home
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/examples/ui/tailwindcss/pages/about.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 | About page
9 |
10 |
11 |
12 | Home page
13 |
14 |
15 |
16 | Tailwind colors:
17 |
18 |
{{ JSON.stringify(theme.colors, null, 2) }}
19 |
20 |
21 |
--------------------------------------------------------------------------------
/examples/advanced/use-custom-fetch-composable/app.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
10 |
11 | - Nuxt custom fetch:
12 |
13 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.e2e/tests/advanced/jsx.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('jsx'))
5 | test.beforeEach(async ({ page }) => {
6 | await page.goto('/')
7 | })
8 |
9 | test('Inline components load', async ({ page }) => {
10 | await expect(page.getByText('Nuxt 3')).toBeVisible()
11 | })
12 |
13 | test('JSX component from "component" folder loads', async ({ page }) => {
14 | await expect(
15 | page.getByText('This is an external JSX component'),
16 | ).toBeVisible()
17 | })
18 |
--------------------------------------------------------------------------------
/examples/ui/vuetify/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | mdi-home
4 |
5 | This is a title
6 | This is a subtitle
7 | This is content
8 |
9 |
10 | Hello Sass Changes
11 |
12 |
13 |
14 |
15 |
19 |
--------------------------------------------------------------------------------
/examples/routing/middleware/app.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
16 |
17 |
18 |
19 | Current route: {{ route.path }}
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/examples/features/state-management/app.vue:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 | Counter: {{ counter }}
9 |
10 |
11 | -
12 |
13 |
14 | +
15 |
16 |
17 | Same Counter: {{ sameCounter }}
18 |
19 |
20 |
--------------------------------------------------------------------------------
/turbo.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://turborepo.org/schema.json",
3 | "globalDependencies": [
4 | ".nuxtrc",
5 | "modules/**",
6 | "shared"
7 | ],
8 | "tasks": {
9 | "build": {
10 | "dependsOn": [
11 | "^build"
12 | ],
13 | "outputs": [
14 | ".output/**",
15 | ".output/server/node_modules/**",
16 | ".vercel/**"
17 | ]
18 | },
19 | "generate": {
20 | "dependsOn": [
21 | "^build"
22 | ],
23 | "outputs": [
24 | ".output/public/**",
25 | ".vercel/**"
26 | ]
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/examples/experimental/wasm/app.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 | a = {{ a }}
14 |
15 |
16 | b = {{ b }}
17 |
18 |
19 | Computation performed server-side with WASM :
20 |
21 | {{ a }} + {{ b }} = {{ data.sum }}
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/examples/features/layouts/layouts/custom.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Default #header slot content for layouts/custom.vue
5 |
6 |
7 |
8 |
9 |
10 |
26 |
--------------------------------------------------------------------------------
/shared/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nuxt/examples-ui",
3 | "version": "0.0.2",
4 | "private": false,
5 | "scripts": {
6 | "dev": "nuxi dev",
7 | "build": "nuxi build",
8 | "start": "nuxi preview",
9 | "prepare": "nuxi prepare"
10 | },
11 | "main": "./nuxt.config.ts",
12 | "files": [
13 | "assets",
14 | "components",
15 | "nuxt.config.ts"
16 | ],
17 | "devDependencies": {
18 | "nuxt": "^4.0.1",
19 | "vue": "3.5.17"
20 | },
21 | "dependencies": {
22 | "@iconify-json/lucide": "^1.2.56",
23 | "@nuxt/ui": "4.0.1",
24 | "tailwindcss": "4.1.11"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/examples/advanced/error-handling/components/FaultyComponent.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 | Component is working ^_^
15 |
16 |
17 |
18 | Component failed to Render -_-
19 |
20 | (fix the issue)
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/.docs/4.advanced/teleport.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: Teleport
4 | description: 'This example shows how to use the with client-side and server-side rendering.'
5 | ---
6 |
7 | Vue 3 provides the [`` component](https://vuejs.org/guide/built-ins/teleport.html) which allows content to be rendered elsewhere in the DOM, outside of the Vue application.
8 |
9 | This example shows how to use the `` with client-side and server-side rendering.
10 |
11 | :read-more{to="/docs/api/components/teleports"}
12 |
13 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/advanced/teleport" file="app.vue"}
14 |
--------------------------------------------------------------------------------
/examples/auth/local/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | // https://nuxt.com/docs/api/configuration/nuxt-config
2 |
3 | // This code is demo only.
4 | if (!process.env.NUXT_AUTH_PASSWORD) {
5 | console.warn('Security warning: NUXT_AUTH_PASSWORD is not set. Using an example value. Please set it otherwise your session is unsecure!')
6 | process.env.NUXT_AUTH_PASSWORD = 'secretsecretsecretsecretsecretsecretsecret'
7 | }
8 |
9 | export default defineNuxtConfig({
10 | // Learn more: https://nuxt.com/docs/getting-started/layers
11 | extends: [
12 | '@nuxt/examples-ui',
13 | './auth',
14 | ],
15 |
16 | compatibilityDate: '2024-04-03',
17 | })
18 |
--------------------------------------------------------------------------------
/examples/advanced/error-handling/plugins/error.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtPlugin((nuxtApp) => {
2 | nuxtApp.hook('vue:error', (..._args) => {
3 | console.log('vue:error')
4 | // if (process.client) {
5 | // console.log(..._args)
6 | // }
7 | })
8 | nuxtApp.hook('app:error', (..._args) => {
9 | console.log('app:error')
10 | // if (process.client) {
11 | // console.log(..._args)
12 | // }
13 | })
14 | nuxtApp.vueApp.config.errorHandler = (..._args) => {
15 | console.log('global error handler')
16 | // if (process.client) {
17 | // console.log(..._args)
18 | // }
19 | }
20 | })
21 |
--------------------------------------------------------------------------------
/examples/advanced/testing/tests/basic.test.ts:
--------------------------------------------------------------------------------
1 | import { fileURLToPath } from 'node:url'
2 | import { describe, expect, it } from 'vitest'
3 | import { setup, $fetch, isDev } from '@nuxt/test-utils'
4 |
5 | describe('example', async () => {
6 | await setup({
7 | rootDir: fileURLToPath(new URL('..', import.meta.url)),
8 | server: true,
9 | })
10 |
11 | it('Renders Hello Nuxt', async () => {
12 | expect(await $fetch('/')).toMatch('Hello Nuxt!')
13 | })
14 |
15 | if (isDev()) {
16 | it('[dev] ensure vite client script is added', async () => {
17 | expect(await $fetch('/')).toMatch('/_nuxt/@vite/client"')
18 | })
19 | }
20 | })
21 |
--------------------------------------------------------------------------------
/examples/advanced/locale/app.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
16 |
17 | {{ date }}
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/examples/ui/tailwindcss/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Nuxt with TailwindCSS
5 |
6 |
7 |
11 |
12 | System
13 |
14 |
15 | Light
16 |
17 |
18 | Dark
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/examples/auth/local/auth/server/api/auth/login.post.ts:
--------------------------------------------------------------------------------
1 | export default eventHandler(async (event) => {
2 | const session = await useAuthSession(event)
3 | const { email, password } = await readBody(event)
4 | const user = await findUserByEmail(email)
5 | if (!user) {
6 | throw createError({
7 | message: 'Email not found! Please register.',
8 | statusCode: 401,
9 | })
10 | }
11 | if (!user.password || user.password !== (await hash(password))) {
12 | throw createError({
13 | message: 'Incorrect password!',
14 | statusCode: 401,
15 | })
16 | }
17 | await session.update({
18 | id: user.id,
19 | name: user.name,
20 | email: user.email,
21 | })
22 | return session
23 | })
24 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "github>nuxt/renovate-config-nuxt"
5 | ],
6 | "rebaseStalePrs": true,
7 | "prCreation": "not-pending",
8 | "packageRules": [
9 | {
10 | "groupName": "nuxt core",
11 | "groupSlug": "nuxt",
12 | "matchPackageNames": [
13 | "nuxt",
14 | "@nuxt/kit",
15 | "@nuxt/schema",
16 | "@nuxt/vite-builder",
17 | "@nuxt/webpack-builder",
18 | "@nuxt/rspack-builder"
19 | ]
20 | },
21 | {
22 | "groupName": "nuxt ui",
23 | "groupSlug": "nuxt-ui",
24 | "matchPackageNames": [
25 | "@nuxt/ui"
26 | ]
27 | }
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/examples/routing/pages/app.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.e2e/tests/advanced/module-extend-pages.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('module-extend-pages'))
5 | test.beforeEach(async ({ page }) => {
6 | await page.goto('/')
7 | await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
8 | })
9 |
10 | test('Page that has been added by a module works', async ({ page }) => {
11 | await page.getByRole('link', { name: 'Test Page' }).click()
12 | await expect(page.getByText('Test page added by module')).toBeVisible()
13 |
14 | await page.getByRole('link', { name: 'Homepage' }).click()
15 | await expect(page.getByText('Go to Test Page')).toBeVisible()
16 | })
17 |
--------------------------------------------------------------------------------
/examples/auth/local/auth/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | // https://nuxt.com/docs/api/configuration/nuxt-config
2 |
3 | // This code is demo only.
4 | if (!process.env.NUXT_AUTH_PASSWORD) {
5 | console.warn('Security warning: NUXT_AUTH_PASSWORD is not set. Using an example value. Please set it otherwise your session is unsecure!')
6 | process.env.NUXT_AUTH_PASSWORD = 'secretsecretsecretsecretsecretsecretsecret'
7 | }
8 |
9 | export default defineNuxtConfig({
10 | runtimeConfig: {
11 | auth: {
12 | name: 'nuxt-session',
13 | password: process.env.NUXT_AUTH_PASSWORD || '',
14 | },
15 | },
16 |
17 | compatibilityDate: '2024-04-03',
18 | nitro: {
19 | storage: {
20 | '.data:auth': { driver: 'fs', base: './.data/auth' },
21 | },
22 | },
23 | })
24 |
--------------------------------------------------------------------------------
/examples/advanced/config-extends/pages/index.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
13 | appConfig:
14 | {{ JSON.stringify(appConfig, null, 2) }}
15 | runtimeConfig:
16 | {{ JSON.stringify(themeConfig, null, 2) }}
17 |
18 | Base Button
19 | Fancy Button
20 | UI Button
21 |
22 |
23 | {{ foo }} {{ bar }}
24 |
25 | {{ $myPlugin() }}
26 |
27 |
28 |
--------------------------------------------------------------------------------
/examples/features/data-fetching/components/TheQuote.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 | Fetching...
12 |
13 |
Could not load quote: {{ error.data }}
14 |
18 |
19 | {{ quote.quote }}
20 |
21 |
22 | — {{ quote.author }}
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/examples/auth/local/app.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
14 | Home
15 |
16 |
17 | Secret
18 |
19 |
23 | Login
24 |
25 |
29 | Profile
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/.e2e/playwright.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, devices } from '@playwright/test'
2 |
3 | /**
4 | * See https://playwright.dev/docs/test-configuration.
5 | */
6 | export default defineConfig({
7 | testDir: './tests',
8 | fullyParallel: true,
9 | forbidOnly: !!process.env.CI,
10 | retries: process.env.CI ? 3 : 1,
11 | workers: process.env.CI ? 1 : undefined,
12 | reporter: [['html', { open: 'never' }]],
13 | snapshotPathTemplate: '{testDir}/../__snapshots__/{testFilePath}/{arg}{ext}',
14 | use: {
15 | trace: 'on-first-retry',
16 | screenshot: 'only-on-failure',
17 | },
18 | expect: {
19 | toHaveScreenshot: {
20 | maxDiffPixelRatio: 0.05,
21 | },
22 | },
23 | projects: [
24 | {
25 | name: 'chromium',
26 | use: { ...devices['Desktop Chrome'] },
27 | },
28 | ],
29 | })
30 |
--------------------------------------------------------------------------------
/.scripts/typecheck.mjs:
--------------------------------------------------------------------------------
1 | import { basename } from 'node:path'
2 | import { glob } from 'tinyglobby'
3 | import { exec } from 'tinyexec'
4 | import { consola } from 'consola'
5 |
6 | const packages = await glob([
7 | 'shared/**/package.json',
8 | 'examples/**/package.json',
9 | '!**/node_modules',
10 | '!**/.nitro',
11 | '!**/.vercel',
12 | '!**/.output',
13 | ], { absolute: true })
14 |
15 | for (const pkg of packages) {
16 | const cwd = pkg.replace('/package.json', '')
17 |
18 | await exec('nuxi', ['prepare'], { nodeOptions: { cwd }, throwOnError: true })
19 | const res = await exec('vue-tsc', ['--noEmit'], { nodeOptions: { cwd } })
20 | if (res.exitCode !== 0) {
21 | consola.withTag(basename(cwd)).error(res.stdout.trim())
22 | process.exit(1)
23 | }
24 | else {
25 | consola.success('type checked', basename(cwd))
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/examples/auth/local/pages/profile.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 | ID:
20 |
21 |
22 | Name:
26 |
27 |
28 | Email:
32 |
33 |
34 |
35 | Logout
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/examples/advanced/jsx/app.vue:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/examples/advanced/error-handling/error.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
{{ error?.message }}
16 | There was an error 😱
17 |
18 |
19 |
20 | Clear error
21 |
22 |
23 |
24 | Trigger another error
25 |
26 |
27 |
31 | Navigate home
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/.docs/1.features/1.auto-imports.md:
--------------------------------------------------------------------------------
1 | ---
2 | toc: false
3 | title: Auto Imports
4 | description: 'This example demonstrates the auto-imports feature in Nuxt.'
5 | ---
6 |
7 | Example of the auto-imports feature in Nuxt with:
8 | - Vue components in the `components/` directory are auto-imported and can be used directly in your templates.
9 | - Vue composables in the `composables/` directory are auto-imported and can be used directly in your templates and JS/TS files.
10 | - JS/TS variables and functions in the `utils/` directory are auto-imported and can be used directly in your templates and JS/TS files.
11 |
12 | :read-more{to="/docs/guide/directory-structure/components"}
13 | :read-more{to="/docs/guide/directory-structure/composables"}
14 | :read-more{to="/docs/guide/directory-structure/utils"}
15 |
16 | :sandbox{repo="nuxt/examples" branch="main" dir="examples/features/auto-imports" file="app.vue"}
17 |
--------------------------------------------------------------------------------
/examples/auth/local/auth/composables/auth.ts:
--------------------------------------------------------------------------------
1 | export const useAuth = () => useNuxtApp().$auth
2 |
3 | export const authLogin = async (email: string, password: string) => {
4 | await $fetch('/api/auth/login', {
5 | method: 'POST',
6 | body: {
7 | email: email,
8 | password: password,
9 | },
10 | })
11 | useAuth().redirectTo.value = null
12 | await useAuth().updateSession()
13 | await navigateTo(useAuth().redirectTo.value || '/')
14 | }
15 |
16 | export const authRegister = async (email: string, password: string) => {
17 | await $fetch('/api/auth/register', {
18 | method: 'POST',
19 | body: {
20 | email: email,
21 | password: password,
22 | },
23 | })
24 | return await authLogin(email, password)
25 | }
26 |
27 | export const authLogout = async () => {
28 | await $fetch('/api/auth/logout', {
29 | method: 'POST',
30 | })
31 | await useAuth().updateSession()
32 | }
33 |
--------------------------------------------------------------------------------
/examples/advanced/teleport/components/MyModal.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 | Open Modal
12 |
13 |
14 |
18 |
22 |
23 | {{ title }}
24 |
25 |
26 |
27 |
28 | Close
29 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
--------------------------------------------------------------------------------
/examples/advanced/use-custom-fetch-composable/plugins/customFetch.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtPlugin((nuxtApp) => {
2 | const userAuth = useCookie('token')
3 | const config = useRuntimeConfig()
4 |
5 | const $customFetch = $fetch.create({
6 | baseURL: config.baseUrl as string ?? 'https://api.nuxt.com',
7 | onRequest({ request, options, error }) {
8 | if (userAuth.value) {
9 | // Add Authorization header
10 | options.headers.set('Authorization', `Bearer ${userAuth.value}`)
11 | }
12 | },
13 | onResponse({ response }) {
14 | // response._data = new myBusinessResponse(response._data)
15 | },
16 | async onResponseError({ response }) {
17 | if (response.status === 401) {
18 | await nuxtApp.runWithContext(() => navigateTo('/login'))
19 | }
20 | },
21 | })
22 | // Expose to useNuxtApp().$customFetch
23 | return {
24 | provide: {
25 | customFetch: $customFetch,
26 | },
27 | }
28 | })
29 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nuxt-examples",
3 | "private": true,
4 | "version": "1.0.0",
5 | "license": "MIT",
6 | "scripts": {
7 | "build": "turbo run build --concurrency 80% && node .scripts/build.mjs",
8 | "lint": "eslint",
9 | "lint:fix": "eslint --fix",
10 | "typecheck": "node .scripts/typecheck.mjs"
11 | },
12 | "devDependencies": {
13 | "@nuxt/cli": "^3.25.1",
14 | "@nuxt/eslint": "^1.5.2",
15 | "@nuxt/eslint-config": "^1.5.2",
16 | "@types/node": "^22.16.0",
17 | "consola": "^3.4.2",
18 | "eslint": "^9.30.1",
19 | "pathe": "^2.0.3",
20 | "pkg-types": "^2.2.0",
21 | "tinyexec": "^1.0.1",
22 | "tinyglobby": "^0.2.14",
23 | "turbo": "2.5.4",
24 | "typescript": "5.8.3",
25 | "vue-tsc": "3.0.4"
26 | },
27 | "resolutions": {
28 | "@nuxt/examples-ui": "workspace:*",
29 | "@nuxt/kit": "4.1.3",
30 | "nuxt": "4.1.0",
31 | "vue": "3.5.17"
32 | },
33 | "packageManager": "pnpm@10.21.0"
34 | }
35 |
--------------------------------------------------------------------------------
/examples/features/layouts/pages/dynamic.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
Custom layout defined dynamically with the NuxtLayout component
11 |
12 |
13 |
14 | Header slot
15 |
16 | Default slot
17 |
21 | Toggle layout
22 |
23 |
24 |
25 |
26 |
27 |
43 |
--------------------------------------------------------------------------------
/examples/advanced/teleport/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | Hello from Modal teleport!
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | node_modules
3 | jspm_packages
4 | .pnpm-store
5 |
6 | package-lock.json
7 | */**/yarn.lock
8 |
9 | # Logs
10 | *.log
11 |
12 | # Temp directories
13 | .temp
14 | .tmp
15 | .cache
16 |
17 | # Generated dirs
18 | dist
19 | .nuxt
20 | .nuxt-*
21 | .output
22 | .gen
23 |
24 | # Junit reports
25 | reports
26 |
27 | # Coverage reports
28 | coverage
29 | *.lcov
30 | .nyc_output
31 |
32 | # VSCode
33 | .vscode
34 |
35 | # Intellij idea
36 | *.iml
37 | .idea
38 |
39 | # OSX
40 | .DS_Store
41 | .AppleDouble
42 | .LSOverride
43 |
44 | # Files that might appear in the root of a volume
45 | .DocumentRevisions-V100
46 | .fseventsd
47 | .Spotlight-V100
48 | .TemporaryItems
49 | .Trashes
50 | .VolumeIcon.icns
51 | .com.apple.timemachine.donotpresent
52 |
53 | # Directories potentially created on remote AFP share
54 | .AppleDB
55 | .AppleDesktop
56 | Network Trash Folder
57 | Temporary Items
58 | .apdisk
59 |
60 | .vercel_build_output
61 | .build-*
62 | .env
63 | .netlify
64 | .turbo
65 | .vercel
66 |
67 | # Playwright
68 | **/test-results/
69 | **/playwright-report/
70 | **/playwright/.cache/
71 |
--------------------------------------------------------------------------------
/examples/features/meta-tags/pages/index.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 | We are using renderless <Html>, <Meta>, <Title> components
15 | that can magically bind the meta inside Vue components.
16 |
17 |
18 |
19 |
20 |
Lucky number: {{ number }}
21 |
25 |
26 |
27 |
28 |
29 |
30 | Click me and see the title updates
31 |
32 |
33 |
34 |
35 |
36 | About page
37 |
38 |
39 |
40 |
41 |
42 |
47 |
--------------------------------------------------------------------------------
/examples/auth/local/auth/server/utils/session.ts:
--------------------------------------------------------------------------------
1 | import type { H3Event, SessionConfig } from 'h3'
2 | import crypto from 'uncrypto'
3 |
4 | const sessionConfig: SessionConfig = useRuntimeConfig().auth || {}
5 |
6 | export type AuthSession = {
7 | id: string
8 | name: string
9 | email: string
10 | }
11 |
12 | export const useAuthSession = async (event: H3Event) => {
13 | const session = await useSession(event, sessionConfig)
14 | return session
15 | }
16 |
17 | export const requireAuthSession = async (event: H3Event) => {
18 | const session = await useAuthSession(event)
19 | if (!session.data.email) {
20 | throw createError({
21 | message: 'Not Authorized',
22 | statusCode: 401,
23 | })
24 | }
25 | return session
26 | }
27 |
28 | export async function hash(str: string) {
29 | const msgUint8 = new TextEncoder().encode(str)
30 | const hashBuffer = await crypto.subtle.digest('SHA-512', msgUint8)
31 | const hashArray = Array.from(new Uint8Array(hashBuffer))
32 | const hashHex = hashArray
33 | .map(b => b.toString(16).padStart(2, '0'))
34 | .join('')
35 | return hashHex
36 | }
37 |
--------------------------------------------------------------------------------
/examples/routing/universal-router/app.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
10 | A page...
11 |
12 |
13 |
14 | Processing navigation in 0.{{ timer }}s
15 |
16 |
17 |
18 |
22 | Home
23 |
24 |
28 | Forbidden
29 |
30 |
34 | Redirect
35 |
36 |
40 |
41 |
42 | Custom: {{ href }}
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 - Nuxt Project
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/examples/routing/universal-router/plugins/add.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtPlugin(() => {
2 | const timer = useState('timer', () => 0)
3 |
4 | if (import.meta.client) {
5 | let timerRunning = false
6 | addRouteMiddleware(async () => {
7 | if (timerRunning) return
8 |
9 | console.log('Starting timer...')
10 | timerRunning = true
11 | timer.value = 5
12 |
13 | do {
14 | await new Promise(resolve => setTimeout(resolve, 100))
15 | console.log('Timer:', timer.value)
16 | timer.value--
17 | } while (timer.value > 0)
18 |
19 | console.log('...and navigating')
20 | timerRunning = false
21 | })
22 | }
23 |
24 | addRouteMiddleware((to) => {
25 | if (to.path === '/forbidden') {
26 | return false
27 | }
28 | })
29 |
30 | addRouteMiddleware((to) => {
31 | const { $config } = useNuxtApp()
32 | if ($config) {
33 | console.log('Accessed runtime config within middleware.')
34 | }
35 |
36 | if (to.path !== '/redirect') {
37 | return
38 | }
39 |
40 | console.log('Heading to', to.path, 'but I think we should go somewhere else...')
41 | return '/secret'
42 | })
43 | })
44 |
--------------------------------------------------------------------------------
/.e2e/tests/features/auto-imports.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('auto-imports'))
5 | test.beforeEach(async ({ page }) => {
6 | await page.goto('/')
7 | await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
8 | })
9 |
10 | test('Heading is visible', async ({ page }) => {
11 | await expect(
12 | page.getByRole('heading', { name: 'Demo with auto imports' }),
13 | ).toBeVisible()
14 | })
15 |
16 | test('Alert shows "Hello NUXT!" without editing the input', async ({
17 | page,
18 | }) => {
19 | page.once('dialog', (dialog) => {
20 | expect(dialog.message()).toBe('Hello NUXT!')
21 | dialog.dismiss()
22 | })
23 | await page.getByRole('button', { name: 'Hello' }).click()
24 | })
25 |
26 | test('Alert shows the right message when the input has been edited', async ({
27 | page,
28 | }) => {
29 | await page.getByRole('textbox').fill('Test')
30 | page.once('dialog', (dialog) => {
31 | expect(dialog.message()).toBe('Hello TEST!')
32 | dialog.dismiss()
33 | })
34 | await page.getByRole('button', { name: 'Hello' }).click()
35 | })
36 |
--------------------------------------------------------------------------------
/examples/auth/local/auth/server/utils/db.ts:
--------------------------------------------------------------------------------
1 | import { randomUUID } from 'uncrypto'
2 |
3 | export interface User {
4 | id: string
5 | createdAt: string
6 | name: string
7 | email: string
8 | password: string
9 | }
10 |
11 | export async function findUserByEmail(email: string): Promise {
12 | const storage = useStorage()
13 | const key = getUserKey(email!)
14 | return await storage.getItem(key) as User
15 | }
16 |
17 | export async function createUser(user: Partial) {
18 | const storage = useStorage()
19 | const key = getUserKey(user.email!)
20 | if (await storage.hasItem(key)) {
21 | throw createError({ message: 'Email already exists!', statusCode: 409 })
22 | }
23 | return await storage.setItem(key, {
24 | id: randomUUID(),
25 | ...user,
26 | })
27 | }
28 |
29 | export async function updateUserByEmail(email: string, updates: Partial) {
30 | const storage = useStorage()
31 | const user = await findUserByEmail(email)
32 | const key = getUserKey(user.email!)
33 | return await storage.setItem(key, {
34 | ...user,
35 | ...updates,
36 | })
37 | }
38 |
39 | function getUserKey(email: string) {
40 | return `db:auth:users:${encodeURIComponent(email)}`
41 | }
42 |
--------------------------------------------------------------------------------
/patches/@nuxtjs__tailwindcss.patch:
--------------------------------------------------------------------------------
1 | diff --git a/dist/module.mjs b/dist/module.mjs
2 | index 5f10c126846f6dafef05339f9097ee1c1bc0b2b2..4da27fdd488c12b382921bed8004ca74341f9e46 100644
3 | --- a/dist/module.mjs
4 | +++ b/dist/module.mjs
5 | @@ -21,7 +21,7 @@ const compatibility = {
6 | async function resolveCSSPath(cssPath, nuxt = useNuxt()) {
7 | if (typeof cssPath === "string") {
8 | const _cssPath = await resolvePath(cssPath, { extensions: [".css", ".sass", ".scss", ".less", ".styl"] });
9 | - return existsSync(_cssPath) ? [_cssPath, `Using Tailwind CSS from ~/${relative(nuxt.options.srcDir, _cssPath)}`] : await tryResolveModule("tailwindcss/package.json").then((twLocation) => twLocation ? [join(twLocation, "../tailwind.css"), "Using default Tailwind CSS file"] : Promise.reject("Unable to resolve tailwindcss. Is it installed?"));
10 | + return existsSync(_cssPath) ? [_cssPath, `Using Tailwind CSS from ~/${relative(nuxt.options.srcDir, _cssPath)}`] : await tryResolveModule("tailwindcss/package.json", import.meta.url).then((twLocation) => twLocation ? [join(twLocation, "../tailwind.css"), "Using default Tailwind CSS file"] : Promise.reject("Unable to resolve tailwindcss. Is it installed?"));
11 | } else {
12 | return [
13 | false,
14 |
--------------------------------------------------------------------------------
/.e2e/utils/index.ts:
--------------------------------------------------------------------------------
1 | import type { BrowserContext, Fixtures, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs } from '@playwright/test'
2 | import { withoutProtocol } from 'ufo'
3 |
4 | export const wait = (ms: number) =>
5 | new Promise(resolve => setTimeout(resolve, ms))
6 |
7 | // eslint-disable-next-line @typescript-eslint/no-empty-object-type
8 | export const getSettingsForDeployment = (slug: string): Fixtures<{}, {}, PlaywrightTestArgs & PlaywrightTestOptions, PlaywrightWorkerArgs> => ({
9 | baseURL: process.env.DEPLOY_URL || `https://${slug}.example.nuxt.space/`,
10 | extraHTTPHeaders: { cookie: `forced=${slug}` },
11 | })
12 |
13 | export async function addForcedCookie(context: BrowserContext, slug: string) {
14 | return addCookies(context, slug, [{ name: 'forced', value: slug }])
15 | }
16 |
17 | export async function addCookies(context: BrowserContext, slug: string, cookies: Array<{ name: string, value: string }>) {
18 | const domain = withoutProtocol(process.env.DEPLOY_URL || `https://${slug}.example.nuxt.space`)
19 | await context.addCookies(cookies.map(c => ({
20 | name: c.name,
21 | value: c.value,
22 | domain,
23 | path: '/',
24 | })).concat([{ name: 'forced', value: slug, domain, path: '/' }]))
25 | }
26 |
--------------------------------------------------------------------------------
/examples/ui/tailwindcss/pages/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
12 |
13 |
14 | The Coldest Sunset
15 |
16 |
17 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptatibus
18 | quia, nulla! Maiores et perferendis eaque, exercitationem praesentium
19 | nihil.
20 |
21 |
22 |
23 | #photography
24 | #travel
25 | #winter
26 |
27 |
28 |
29 | About
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/.github/workflows/playwright.yml:
--------------------------------------------------------------------------------
1 | name: e2e
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | url:
7 | required: false
8 | description: The URL to run the test suite against. If omitted, it runs against all.
9 | type: string
10 | deployment_status:
11 |
12 | jobs:
13 | test:
14 | timeout-minutes: 60
15 | runs-on: ubuntu-latest
16 | container:
17 | image: mcr.microsoft.com/playwright:v1.53.2-noble
18 | steps:
19 | - uses: actions/checkout@v5
20 | - run: corepack enable
21 | - uses: actions/setup-node@v5
22 | with:
23 | node-version: lts/*
24 | cache: "pnpm"
25 |
26 | - name: Install dependencies
27 | run: pnpm install
28 |
29 | - name: Install playwright
30 | run: pnpm playwright install
31 | working-directory: .e2e
32 |
33 | - name: Run Playwright tests
34 | run: pnpm --filter e2e test:all
35 | env:
36 | DEPLOY_URL: ${{ github.event.inputs.url || github.event.deployment.payload.web_url || github.event.deployment_status.target_url }}
37 |
38 | - uses: actions/upload-artifact@v4
39 | if: always()
40 | with:
41 | name: playwright-report
42 | path: .e2e/playwright-report/
43 | retention-days: 30
44 |
--------------------------------------------------------------------------------
/examples/features/data-fetching/pages/external.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 | Result of https://dummyjson.com/products/
20 |
24 |
25 |
26 |
30 | Previous
31 |
32 | -
33 |
34 | Next
35 |
36 |
37 |
38 | Fetching...
39 |
40 |
{{ error }}
41 |
{{ product }}
42 |
46 | Back to Home
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/examples/features/layouts/app.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
24 | layouts/default.vue
25 |
26 |
31 | layouts/custom.vue
32 |
33 |
38 | layouts/other.vue
39 |
40 |
45 | Remove layout
46 |
47 |
48 |
49 |
50 |
51 |
56 |
--------------------------------------------------------------------------------
/examples/auth/local/README.md:
--------------------------------------------------------------------------------
1 | # Nuxt with Local Auth
2 |
3 | Simple password based starter made with Nuxt goodies, built-in session, storage layer and composables.
4 |
5 | This project uses [Nuxt Extend Layers](https://nuxt.com/docs/getting-started/layers) feature to implement local auth in [`auth`](./auth) directory with a modular approach. This way you can share and reuse your authentication implementation across projects and keep the code clean.
6 |
7 | Default database is using built-in key-value storage. You can rewrite it with a custom database by updating [`./auth/server/utils/db.ts`](./auth/server/utils/db.ts)
8 |
9 | Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more about Nuxt.
10 |
11 | ## Setup
12 |
13 | Make sure to install the dependencies:
14 |
15 | ```bash
16 | # yarn
17 | yarn install
18 |
19 | # npm
20 | npm install
21 |
22 | # pnpm
23 | pnpm install
24 | ```
25 |
26 | Copy `.env.example` to `.env` and provide a secure string for session password.
27 |
28 | ## Development Server
29 |
30 | Start the development server on http://localhost:3000
31 |
32 | ```bash
33 | npm run dev
34 | ```
35 |
36 | ## Production
37 |
38 | Build the application for production:
39 |
40 | ```bash
41 | npm run build
42 | ```
43 |
44 | Locally preview production build:
45 |
46 | ```bash
47 | npm run preview
48 | ```
49 |
50 | Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
51 |
--------------------------------------------------------------------------------
/examples/advanced/error-handling/app.vue:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
23 |
24 |
28 | Home
29 |
30 |
34 | Other
35 |
36 |
40 | 404
41 |
42 |
46 | Middleware
47 |
48 | showError('Fatal error')"
51 | >
52 | Trigger fatal error
53 |
54 |
58 | Trigger non-fatal error
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/.e2e/tests/features/state-management.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import type { Page } from '@playwright/test'
3 | import { getSettingsForDeployment } from '@/utils'
4 |
5 | test.use(getSettingsForDeployment('state-management'))
6 | test.beforeEach(async ({ page }) => {
7 | await page.goto('/')
8 | await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
9 | })
10 |
11 | test('Same value is displayed on load for both counters', async ({ page }) => {
12 | const counterValue = await getCounterValue(page)
13 | await expect(page.getByText(`Counter: ${counterValue}`)).toHaveCount(2)
14 | })
15 |
16 | test('Clicking on "-" decrements both counters', async ({ page }) => {
17 | const counterValue = await getCounterValue(page)
18 | await page.getByRole('button', { name: '-' }).click()
19 | await page.getByText(`Counter: ${counterValue - 1}`).first().isVisible()
20 | await expect(page.getByText(`Counter: ${counterValue - 1}`)).toHaveCount(2)
21 | })
22 |
23 | test('Clicking on "+" increments both counters', async ({ page }) => {
24 | const counterValue = await getCounterValue(page)
25 | await page.getByRole('button', { name: '+' }).click()
26 | await page.getByText(`Counter: ${counterValue + 1}`).first().isVisible()
27 | await expect(page.getByText(`Counter: ${counterValue + 1}`)).toHaveCount(2)
28 | })
29 |
30 | async function getCounterValue(page: Page) {
31 | const sameCounterText = await page.getByText('Same Counter:').textContent()
32 | return Number(sameCounterText.split(':').at(-1).trim())
33 | }
34 |
--------------------------------------------------------------------------------
/examples/advanced/locale/composables/locale.ts:
--------------------------------------------------------------------------------
1 | import type { Ref } from 'vue'
2 |
3 | export const useNuxtLocale = () => useState('locale', () => useDefaultLocale().value)
4 |
5 | export const useDefaultLocale = (fallback = 'en-US') => {
6 | const locale = ref(fallback)
7 | if (import.meta.server) {
8 | // Learn more about the nuxtApp interface on https://nuxt.com/docs/guide/going-further/internals#the-nuxtapp-interface
9 | const reqLocale = useRequestHeaders()['accept-language']?.split(',')[0]
10 | if (reqLocale) {
11 | locale.value = reqLocale
12 | }
13 | }
14 | else if (import.meta.client) {
15 | const navLang = navigator.language
16 | if (navLang) {
17 | locale.value = navLang
18 | }
19 | }
20 | return locale
21 | }
22 |
23 | export const useNuxtLocales = () => {
24 | const locale = useNuxtLocale()
25 | const locales = ref([
26 | 'en-US',
27 | 'en-GB',
28 | 'ko-KR',
29 | 'zh-CN',
30 | 'ar-EG',
31 | 'fa-IR',
32 | 'ja-JP-u-ca-japanese',
33 | ])
34 | if (!locales.value.includes(locale.value)) {
35 | locales.value.unshift(locale.value)
36 | }
37 | return locales
38 | }
39 |
40 | // Using Intl.DateTimeFormat for language-sensitive date and time formatting
41 | // Learn more: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat
42 | export const useNuxtLocaleDate = (date: Ref | Date, locale = useNuxtLocale()) => {
43 | return computed(() => new Intl.DateTimeFormat(locale.value, { dateStyle: 'full' }).format(unref(date)))
44 | }
45 |
--------------------------------------------------------------------------------
/examples/auth/local/auth/plugins/0.auth.ts:
--------------------------------------------------------------------------------
1 | import type { AuthSession } from '~~/auth/server/utils/session'
2 |
3 | export default defineNuxtPlugin(async (nuxtApp) => {
4 | // Skip plugin when rendering error page
5 | if (nuxtApp.payload.error) {
6 | return {}
7 | }
8 |
9 | const { data: session, refresh: updateSession }
10 | = await useFetch('/api/auth/session')
11 |
12 | const loggedIn = computed(() => !!session.value?.email)
13 |
14 | // Create a ref to know where to redirect the user when logged in
15 | const redirectTo = useState('authRedirect')
16 |
17 | /**
18 | * Add global route middleware to protect pages using:
19 | *
20 | * definePageMeta({
21 | * auth: true
22 | * })
23 | */
24 | //
25 |
26 | addRouteMiddleware(
27 | 'auth',
28 | (to) => {
29 | if (to.meta.auth && !loggedIn.value) {
30 | redirectTo.value = to.path
31 | return '/login'
32 | }
33 | },
34 | { global: true },
35 | )
36 |
37 | const currentRoute = useRoute()
38 |
39 | if (import.meta.client) {
40 | watch(loggedIn, async (loggedIn) => {
41 | if (!loggedIn && currentRoute.meta.auth) {
42 | redirectTo.value = currentRoute.path
43 | await navigateTo('/login')
44 | }
45 | })
46 | }
47 |
48 | if (loggedIn.value && currentRoute.path === '/login') {
49 | await navigateTo(redirectTo.value || '/')
50 | }
51 |
52 | return {
53 | provide: {
54 | auth: {
55 | loggedIn,
56 | session,
57 | redirectTo,
58 | updateSession,
59 | },
60 | },
61 | }
62 | })
63 |
--------------------------------------------------------------------------------
/.e2e/tests/advanced/locale.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('locale'))
5 | test.beforeEach(async ({ page }) => {
6 | await page.goto('/')
7 | await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
8 | })
9 |
10 | test.describe('British Locale', () => {
11 | test.use({
12 | locale: 'en-GB',
13 | })
14 |
15 | test('Date is in british format', async ({ page }) => {
16 | await expect(page.getByText('Wednesday 26 October 2016')).toBeVisible()
17 | })
18 |
19 | test('British locale has been selected', async ({ page }) => {
20 | await expect(page.getByRole('combobox')).toHaveText('en-GB')
21 | })
22 |
23 | test('Changing locales works', async ({ page }) => {
24 | await page.getByRole('combobox').click()
25 | await page.getByRole('option', { name: 'ko-KR' }).click()
26 | await expect(page.getByText('2016년 10월 26일 수요일')).toBeVisible()
27 |
28 | await page.getByRole('combobox').click()
29 | await page.getByRole('option', { name: 'fa-IR' }).click()
30 | await expect(page.getByText('۱۳۹۵ آبان ۵, چهارشنبه')).toBeVisible()
31 | })
32 | })
33 |
34 | test.describe('US Locale', () => {
35 | test.use({
36 | locale: 'en-US',
37 | })
38 |
39 | test('Date is in US format', async ({ page }) => {
40 | await expect(page.getByText('Wednesday, October 26, 2016')).toBeVisible()
41 | })
42 |
43 | test('US locale has been selected', async ({ page }) => {
44 | await expect(page.getByRole('combobox')).toHaveText('en-US')
45 | })
46 | })
47 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: ci
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - main
10 |
11 | # https://github.com/vitejs/vite/blob/main/.github/workflows/ci.yml
12 | env:
13 | # 7 GiB by default on GitHub, setting to 6 GiB
14 | # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
15 | NODE_OPTIONS: --max-old-space-size=6144
16 |
17 | # Remove default permissions of GITHUB_TOKEN for security
18 | # https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs
19 | permissions: {}
20 |
21 | jobs:
22 | lint:
23 | runs-on: ubuntu-latest
24 |
25 | steps:
26 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
27 | - run: corepack enable
28 | - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
29 | with:
30 | node-version: lts/*
31 | cache: "pnpm"
32 |
33 | - name: Install dependencies
34 | run: pnpm install
35 |
36 | - name: Lint
37 | run: pnpm lint
38 |
39 | typecheck:
40 | runs-on: ubuntu-latest
41 |
42 | steps:
43 | - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
44 | - run: corepack enable
45 | - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
46 | with:
47 | node-version: lts/*
48 | cache: "pnpm"
49 |
50 | - name: Install dependencies
51 | run: pnpm install
52 |
53 | - name: Typecheck
54 | run: pnpm typecheck
55 |
--------------------------------------------------------------------------------
/.e2e/README.md:
--------------------------------------------------------------------------------
1 | # Nuxt Example's E2E Tests
2 |
3 | This project contains the end-to-end tests for the examples in the repository.
4 |
5 | ## Getting Started
6 |
7 | Install the dependencies if you haven't already in the project root:
8 |
9 | ```sh
10 | pnpm install
11 | ```
12 |
13 | ## Commands
14 |
15 | Running non-visual tests (recommended during development):
16 |
17 | ```sh
18 | pnpm -F e2e test
19 | ```
20 |
21 | Running [visual regression tests](https://playwright.dev/docs/test-snapshots):
22 |
23 | ```sh
24 | pnpm -F e2e test:visual
25 | ```
26 |
27 | Updating snapshots for visual regression tests:
28 |
29 | ```sh
30 | pnpm -F e2e test:visual:update-snapshots
31 | ```
32 |
33 | Running every test:
34 |
35 | ```sh
36 | pnpm -F e2e test:all
37 | ```
38 |
39 | Opening the [code generator](https://playwright.dev/docs/codegen-intro#running-codegen):
40 |
41 | ```sh
42 | pnpm -F e2e codegen
43 | ```
44 |
45 | Starting in [UI mode](https://playwright.dev/docs/test-ui-mode):
46 |
47 | ```sh
48 | pnpm -F e2e ui
49 | ```
50 |
51 | ## Note for Windows Users
52 |
53 | Windows users shouldn't run visual regression tests directly, because the CI uses ubuntu and different operating systems has different font loading behavior.
54 |
55 | In case you want to run these tests, you should use a docker image:
56 |
57 | ```ps
58 | docker run --rm --network host -v $(pwd):/work/ -w /work/ -it node:20-bookworm /bin/bash
59 | cd .e2e
60 | npm install
61 |
62 | # just running the tests
63 | npx run test:visual
64 |
65 | # updating snapshots
66 | npx run test:visual:update-snapshots
67 | ```
68 |
69 | See: [official docs for visual testing](https://playwright.dev/docs/test-snapshots)
70 |
--------------------------------------------------------------------------------
/.e2e/tests/routing/universal-router.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { addForcedCookie, getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('universal-router'))
5 |
6 | test('Global middleware is being registered', async ({ page }) => {
7 | const globalMiddlewareMessageLoggedPromise = page.waitForEvent('console', {
8 | predicate: message => message.text() === 'running global middleware',
9 | })
10 |
11 | await page.goto('/')
12 | await globalMiddlewareMessageLoggedPromise
13 | await expect(page.getByText('Current route: /', { exact: true })).toBeVisible()
14 | })
15 |
16 | test('Timer is shows during client-side navigation', async ({ page }) => {
17 | await page.goto('/')
18 | await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
19 | await page.getByRole('link', { name: 'Home' }).click()
20 | await expect(page.getByText('A page... Processing navigation')).toBeVisible()
21 | await expect(page.getByText('A page... Processing navigation')).toBeHidden()
22 | })
23 |
24 | test('Middleware redirects from the "/redirect" page to the "/secret" page', async ({ page, context }) => {
25 | await addForcedCookie(context, 'middleware')
26 | await page.goto('/redirect')
27 | await expect(page.getByText('You should never see this page')).toBeHidden()
28 | await expect(page).toHaveURL('/secret')
29 | })
30 |
31 | test('Middleware redirects from the "/redirect" page to the "/secret" page using custom NuxtLink', async ({
32 | page,
33 | }) => {
34 | await page.goto('/')
35 | await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
36 | await page.getByRole('button', { name: 'Custom: /redirect' }).click()
37 | await expect(page).toHaveURL('/secret')
38 | })
39 |
--------------------------------------------------------------------------------
/examples/advanced/use-cookie/app.vue:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
22 |
23 |
24 | Welcome, {{ user.name }}! 👋
25 |
26 |
27 |
32 |
33 | You have logged in {{ logins }} times !
34 |
35 |
36 |
37 |
38 |
43 | Log out
44 |
45 |
46 |
47 |
48 |
49 | Login
50 |
51 |
57 |
58 |
64 | Log in
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Nuxt Examples
2 |
3 | 👉 https://nuxt.com/docs/examples
4 |
5 | ---
6 |
7 | ## Sites
8 |
9 | - [hello-world](https://hello-world.example.nuxt.space/) - ([source](./examples/hello-world/))
10 |
11 | ### Features
12 |
13 | Inside [features/](./examples/features).
14 |
15 | - [auto-imports](https://auto-imports.example.nuxt.space/)
16 | - [data-fetching](https://data-fetching.example.nuxt.space/)
17 | - [state-management](https://state-management.example.nuxt.space/)
18 | - [meta-tags](https://meta-tags.example.nuxt.space/)
19 | - [layouts](https://layouts.example.nuxt.space/)
20 |
21 | ### Routing
22 |
23 | Inside [routing/](./examples/routing).
24 |
25 | - [middleware](https://middleware.example.nuxt.space/)
26 | - [pages](https://pages.example.nuxt.space/)
27 | - [universal-router](https://universal-router.example.nuxt.space/)
28 |
29 | ### UI Frameworks
30 |
31 | Inside [ui/](./examples/ui).
32 |
33 | - [daisyui](https://daisyui.example.nuxt.space/)
34 | - [tailwindcss](https://tailwindcss.example.nuxt.space/)
35 | - [sass](https://sass.example.nuxt.space/)
36 | - [vuetify](https://vuetify.example.nuxt.space/)
37 |
38 | ### Authentication
39 |
40 | Inside [auth/](./examples/auth).
41 |
42 | - [local](https://local-auth.example.nuxt.space/)
43 |
44 | ## Advanced
45 |
46 | Inside [advanced/](./examples/advanced).
47 |
48 | - [config-extends](https://config-extends.example.nuxt.space/)
49 | - [error-handling](https://error-handling.example.nuxt.space/)
50 | - [jsx](https://jsx.example.nuxt.space/)
51 | - [locale](https://locale.example.nuxt.space/)
52 | - [module-extend-pages](https://module-extend-pages.example.nuxt.space/)
53 | - [teleport](https://teleport.example.nuxt.space/)
54 | - [testing](https://testing.example.nuxt.space/)
55 | - [use-cookie](https://use-cookie.example.nuxt.space/)
56 | - [use-custom-fetch-composable](https://use-custom-fetch-composable.example.nuxt.space/)
57 |
58 | ## Experimental
59 |
60 | Inside [experimental/](./examples/experimental).
61 |
62 | - [wasm](https://wasm.example.nuxt.space/)
63 |
--------------------------------------------------------------------------------
/shared/components/Logo.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
18 |
25 |
29 |
30 |
35 |
36 |
40 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/.e2e/tests/features/data-fetching.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('data-fetching'))
5 |
6 | test.describe('Index page', () => {
7 | test('Hello world is shown on the index page', async ({ page }) => {
8 | await page.goto('/')
9 | await expect(page.getByText('Result of /api/hello:')).toBeVisible()
10 | await expect(page.getByText('{ "hello": "world" }')).toBeVisible()
11 | })
12 | })
13 |
14 | test.describe('External page', () => {
15 | test('Visiting "External Page" from index shows item with ID: 1', async ({
16 | page,
17 | }) => {
18 | await page.goto('/')
19 | await page.getByRole('link', { name: 'External' }).click()
20 |
21 | await expect(page.getByRole('spinbutton')).toHaveValue('1')
22 | await expect(page.getByText('"id": 1')).toBeVisible()
23 | })
24 |
25 | test('Visiting "External Page" directly shows item with ID: 1', async ({
26 | page,
27 | }) => {
28 | await page.goto('/external')
29 |
30 | await expect(page.getByRole('spinbutton')).toHaveValue('1')
31 | await expect(page.getByText('"id": 1')).toBeVisible()
32 | })
33 | })
34 |
35 | test.describe('Component page', () => {
36 | test('Visiting "Component Page" from index shows the first quote', async ({
37 | page,
38 | }) => {
39 | await page.goto('/')
40 | await page.getByRole('link', { name: 'Component' }).click()
41 |
42 | await expect(
43 | page.getByText(
44 | 'Your heart is the size of an ocean. Go find yourself in its hidden depths.',
45 | ),
46 | ).toBeVisible()
47 | await expect(page.getByText('Rumi')).toBeVisible()
48 | })
49 |
50 | test('Visiting "Component Page" directly shows the first quote', async ({
51 | page,
52 | }) => {
53 | await page.goto('/component')
54 |
55 | await expect(
56 | page.getByText(
57 | 'Your heart is the size of an ocean. Go find yourself in its hidden depths.',
58 | ),
59 | ).toBeVisible()
60 | await expect(page.getByText('Rumi')).toBeVisible()
61 | })
62 | })
63 |
--------------------------------------------------------------------------------
/examples/ui/daisyui/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello daisyUI
5 |
6 |
10 |
14 | Theme
15 |
16 |
20 | {{ theme }}
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | Hello there
29 |
30 |
31 | Provident cupiditate voluptatem et in. Quaerat fugiat ut assumenda excepturi exercitationem quasi. In deleniti eaque aut repudiandae et a id nisi.
32 |
33 |
34 | Get Started
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
46 |
47 |
48 |
49 | Shoes!
50 |
51 |
If a dog chews shoes whose shoes does he choose?
52 |
53 |
54 | Buy Now
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
97 |
--------------------------------------------------------------------------------
/.e2e/tests/routing/middleware.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { addForcedCookie, getSettingsForDeployment, wait } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('middleware'))
5 |
6 | test('Global middleware is being registered', async ({ page }) => {
7 | const globalMiddlewareMessageLoggedPromise = page.waitForEvent('console', {
8 | predicate: message => message.text() === 'running global middleware',
9 | })
10 |
11 | await page.goto('/')
12 | await globalMiddlewareMessageLoggedPromise
13 | await expect(page.getByText('Current route: /', { exact: true })).toBeVisible()
14 | })
15 |
16 | test('Global middleware from plugin is being registered', async ({ page }) => {
17 | const globalMiddlewareMessageLoggedPromise = page.waitForEvent('console', {
18 | predicate: message =>
19 | message.text() === 'this global middleware was added in a plugin',
20 | })
21 |
22 | await page.goto('/')
23 | await globalMiddlewareMessageLoggedPromise
24 | await expect(page.getByText('Current route: /', { exact: true })).toBeVisible()
25 | })
26 |
27 | test('Inline middleware on the "forbidden" page cancels navigation', async ({
28 | page,
29 | }) => {
30 | await page.goto('/')
31 |
32 | const strictlyForbiddenLoggedPromise = page.waitForEvent('console', {
33 | predicate: message => message.text() === 'Strictly forbidden.',
34 | })
35 | await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
36 | await page.getByRole('link', { name: 'Forbidden' }).click()
37 | await strictlyForbiddenLoggedPromise
38 | await wait(500)
39 |
40 | await expect(page.getByText('Current route: /', { exact: true })).toBeVisible()
41 | })
42 |
43 | test('Middleware redirects from the "/redirect" page to the "/secret" page', async ({ page, context }) => {
44 | await addForcedCookie(context, 'middleware')
45 | await page.goto('/redirect')
46 | await expect(page.getByText('You should never see this page')).toBeHidden()
47 | await expect(page).toHaveURL('/secret')
48 | })
49 |
50 | test('Named middleware is registered on the secret page', async ({ page }) => {
51 | const namedMiddlewareLoggedPromise = page.waitForEvent('console', {
52 | predicate: message =>
53 | message.text() === 'this named middleware was added in a plugin',
54 | })
55 |
56 | await page.goto('/secret')
57 | await namedMiddlewareLoggedPromise
58 | await expect(page.getByText('You\'ve landed on a page that wasn\'t in the menu!')).toBeVisible()
59 | })
60 |
--------------------------------------------------------------------------------
/.e2e/tests/advanced/config-extends.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('config-extends'))
5 |
6 | test('App config merged', async ({ page }) => {
7 | // TODO need a unique locator
8 | await page.goto('/')
9 | await expect(
10 | page.getByText(
11 | '"bar": "user", "baz": "base", "array": [ "user", "user", "user" ], "arrayNested": { "nested": { "array": [ "base", "base", "base" ] } }, "foo": "user" }',
12 | ),
13 | ).toBeVisible()
14 | })
15 |
16 | test.fixme('Runtime config is shown', async () => {
17 | // TODO it is not shown
18 | })
19 |
20 | test('Base button is shown', async ({ page }) => {
21 | await page.goto('/')
22 | await expect(
23 | page.getByRole('button', { name: 'Base Button' }),
24 | ).toHaveAttribute('role', 'button')
25 | })
26 |
27 | test('Fancy button from base layer is overridden', async ({ page }) => {
28 | await page.goto('/')
29 | await expect(page.getByRole('button', { name: 'Fancy Button' })).toHaveClass(
30 | 'border p-2 fancy-button',
31 | )
32 | })
33 |
34 | test('UI button is shown', async ({ page }) => {
35 | await page.goto('/')
36 | await expect(page.getByRole('button', { name: 'UI Button' })).toBeVisible()
37 | })
38 |
39 | test('"useFoo()" composable and "getBar()" util is usable from base layer', async ({
40 | page,
41 | }) => {
42 | await page.goto('/')
43 | await expect(page.getByText('foo bar')).toBeVisible()
44 | })
45 |
46 | test('Plugin from base layer is registered', async ({ page }) => {
47 | await page.goto('/')
48 | await expect(
49 | page.getByText('String generated from my auto-imported plugin!'),
50 | ).toBeVisible()
51 | })
52 |
53 | test('"api/hello" endpoint works', async ({ page }) => {
54 | await page.goto('/api/hello')
55 | await expect(page.getByText('hello')).toBeVisible()
56 | })
57 |
58 | test('"api/base" endpoint works', async ({ page }) => {
59 | await page.goto('/api/base')
60 | await expect(page.getByText('base')).toBeVisible()
61 | })
62 |
63 | test('page inherited from base layer loads', async ({ page }) => {
64 | await page.goto('/foo')
65 | await expect(page.getByText('Hello from extended page !')).toBeVisible()
66 | })
67 |
68 | test('Middleware for inherited page loads', async ({ page }) => {
69 | const inheritedMiddlewareLoggedPromise = page.waitForEvent('console', {
70 | predicate: message =>
71 | message.text() === 'Hello from extended middleware !',
72 | })
73 |
74 | await page.goto('/foo')
75 | await inheritedMiddlewareLoggedPromise
76 | })
77 |
--------------------------------------------------------------------------------
/.e2e/tests/advanced/use-cookie.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { addCookies, addForcedCookie, getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('use-cookie'))
5 |
6 | test('Login screen shows by default', async ({ page }) => {
7 | await page.goto('/')
8 | await expect(page.getByRole('heading', { name: 'Login' })).toBeVisible()
9 | })
10 |
11 | test('Logging in multiple times increases counter', async ({ page }) => {
12 | await page.goto('/')
13 | await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
14 |
15 | await page.getByPlaceholder('Enter your name...').fill('Nuxt')
16 | await page.getByRole('button', { name: 'Log in' }).click()
17 |
18 | await expect(page.getByText('You have logged in 1 times!')).toBeVisible()
19 | await page.getByRole('button', { name: 'Log out' }).click()
20 |
21 | await page.getByPlaceholder('Enter your name...').press('Control+a')
22 | await page.getByPlaceholder('Enter your name...').fill('Nuxt')
23 | await page.getByRole('button', { name: 'Log in' }).click()
24 |
25 | await expect(page.getByText('You have logged in 2 times!')).toBeVisible()
26 | await page.getByRole('button', { name: 'Log out' }).click()
27 |
28 | await page.getByPlaceholder('Enter your name...').press('Control+a')
29 | await page.getByPlaceholder('Enter your name...').fill('Nuxt')
30 | await page.getByRole('button', { name: 'Log in' }).click()
31 |
32 | await expect(page.getByText('You have logged in 3 times!')).toBeVisible()
33 | })
34 |
35 | test('Automatic login with existing cookies', async ({ context, page }) => {
36 | await addCookies(context, 'use-cookie', [
37 | {
38 | name: 'user',
39 | value: '{"name":"Nuxt"}',
40 | },
41 | {
42 | name: 'logins',
43 | value: '1',
44 | },
45 | ])
46 |
47 | await page.goto('/')
48 |
49 | await expect(page.getByRole('heading', { name: 'Welcome, Nuxt! 👋' })).toBeVisible()
50 | await expect(page.getByText('You have logged in 1 times!')).toBeVisible()
51 | })
52 |
53 | test('Clearing cookies resets the timer', async ({ context, page }) => {
54 | await page.goto('/')
55 | await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
56 |
57 | await page.getByPlaceholder('Enter your name...').fill('Nuxt')
58 | await page.getByRole('button', { name: 'Log in' }).click()
59 | await expect(page.getByText('You have logged in 1 times!')).toBeVisible()
60 | await page.getByRole('button', { name: 'Log out' }).click()
61 |
62 | await context.clearCookies()
63 | await addForcedCookie(context, 'use-cookie')
64 | await page.reload({ waitUntil: 'load' })
65 | await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
66 |
67 | await page.getByPlaceholder('Enter your name...').fill('Nuxt')
68 | await page.getByRole('button', { name: 'Log in' }).click()
69 | await expect(page.getByText('You have logged in 1 times!')).toBeVisible()
70 | })
71 |
--------------------------------------------------------------------------------
/.e2e/tests/routing/pages.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('pages'))
5 |
6 | test.describe('Linked pages', () => {
7 | test.beforeEach(async ({ page }) => {
8 | await page.goto('/')
9 | await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
10 | })
11 |
12 | test('Home page is shown', async ({ page }) => {
13 | await expect(page.getByText('Home').nth(1)).toBeVisible()
14 | await expect(page.getByText('Current route: /')).toBeVisible()
15 | })
16 |
17 | test('Navigating to "About" page', async ({ page }) => {
18 | await page.getByRole('link', { name: 'About' }).click()
19 | await expect(page.getByText('About').nth(1)).toBeVisible()
20 | await expect(page.getByText('Current route: /about')).toBeVisible()
21 | })
22 |
23 | test('Navigating to "Parent/index" page', async ({ page }) => {
24 | await page.getByRole('link', { name: 'Parent (index)' }).click()
25 | await expect(page.getByText('Parent Parent/index')).toBeVisible()
26 | await expect(page.getByText('Current route: /parent')).toBeVisible()
27 | })
28 |
29 | test('Navigating to "Parent/b" page', async ({ page }) => {
30 | await page.getByRole('link', { name: 'Parent (b)' }).click()
31 | await expect(page.getByText('Parent Parent/b')).toBeVisible()
32 | await expect(page.getByText('Current route: /parent/b')).toBeVisible()
33 | })
34 |
35 | test('Navigating to keyed child page', async ({ page }) => {
36 | await page.getByRole('button', { name: 'Keyed child', exact: true }).click()
37 | await expect(page.getByText('Child reloaded: 1')).toBeVisible()
38 | await expect(page.getByText('Current route: /parent/reload-')).toBeVisible()
39 | })
40 |
41 | test('Navigating to keyed child with different path param increases counter', async ({
42 | page,
43 | }) => {
44 | await page.getByRole('button', { name: 'Keyed child', exact: true }).click()
45 | await expect(page.getByText('Child reloaded: 1')).toBeVisible()
46 |
47 | await page.getByRole('button', { name: 'Keyed child', exact: true }).click()
48 | await expect(page.getByText('Child reloaded: 2')).toBeVisible()
49 | })
50 |
51 | test('Navigating to non-keyed child child page', async ({ page }) => {
52 | await page.getByRole('button', { name: 'Non-Keyed child' }).click()
53 | await expect(page.getByText('Child reloaded: 1')).toBeVisible()
54 | await expect(page.getByText('Current route: /parent/static-')).toBeVisible()
55 | })
56 |
57 | test('Navigating to non-keyed child child with different path param does not increases counter', async ({
58 | page,
59 | }) => {
60 | await page.getByRole('button', { name: 'Non-Keyed child' }).click()
61 | await expect(page.getByText('Child reloaded: 1')).toBeVisible()
62 |
63 | await page.getByRole('button', { name: 'Non-Keyed child' }).click()
64 | await expect(page.getByText('Child reloaded: 1')).toBeVisible()
65 | })
66 | })
67 |
68 | test('Navigating to catchall route', async ({ page }) => {
69 | await page.goto('/catchall/1')
70 | await expect(page.getByText('test-[ "1" ]')).toBeVisible()
71 | await expect(page.getByText('Current route: /catchall/1')).toBeVisible()
72 | })
73 |
--------------------------------------------------------------------------------
/.scripts/build.mjs:
--------------------------------------------------------------------------------
1 | import fsp from 'node:fs/promises'
2 | import { glob } from 'tinyglobby'
3 | import { readPackageJSON } from 'pkg-types'
4 | import { join, resolve } from 'pathe'
5 |
6 | const stringify = contents => JSON.stringify(contents, null, 2)
7 |
8 | const packages = await glob([
9 | 'examples/**/package.json',
10 | '!**/node_modules',
11 | '!**/.nitro',
12 | '!**/.vercel',
13 | '!**/.output',
14 | ]).then(r => r.sort())
15 | const names = new Set()
16 |
17 | await fsp.rm('.vercel/output', { recursive: true, force: true })
18 |
19 | // Create public files
20 | await fsp.mkdir('.vercel/output/static', { recursive: true })
21 | await fsp.mkdir('.vercel/output/functions', { recursive: true })
22 | for (const config of packages) {
23 | const { name } = await readPackageJSON(resolve(config))
24 | const output = resolve(config, '../.vercel/output')
25 | try {
26 | const stats = await fsp.stat(output)
27 | if (!stats.isDirectory()) continue
28 | }
29 | catch {
30 | continue
31 | }
32 |
33 | await fsp.cp(join(output, 'static'), `.vercel/output/static/${name}`, {
34 | recursive: true,
35 | })
36 | await fsp.cp(
37 | join(output, 'functions/__fallback.func'),
38 | `.vercel/output/functions/${name}.func`,
39 | {
40 | recursive: true,
41 | },
42 | )
43 | names.add(name)
44 | }
45 |
46 | // Create middleware
47 | await fsp.mkdir('.vercel/output/functions/_middleware.func', {
48 | recursive: true,
49 | })
50 | await fsp.writeFile(
51 | '.vercel/output/functions/_middleware.func/index.js',
52 | `
53 | const names = ${stringify([...names])}
54 |
55 | export default function middleware(req) {
56 | const forced = req.url.match(/\\?force=(.*)$/)?.[1]
57 | const hostname = req.headers.get('host')
58 | const subdomain = forced || req.headers.get('cookie')?.match(/forced=([^;]*)(;|$)/)?.[1] || hostname.split('.').shift()
59 |
60 | if (names.includes(subdomain)) {
61 | const response = new Response()
62 | const url = new URL(req.url)
63 | response.headers.set('x-middleware-rewrite', '/' + subdomain + url.pathname)
64 | if (forced) {
65 | response.headers.set('set-cookie', \`forced=$\{forced}\`)
66 | }
67 | return response
68 | }
69 |
70 | return new Response(null, {
71 | status: 307,
72 | headers: {
73 | Location: 'https://nuxt.com/docs/examples/essentials/hello-world/'
74 | }
75 | })
76 |
77 | }`,
78 | )
79 | await fsp.writeFile(
80 | '.vercel/output/functions/_middleware.func/.vc-config.json',
81 | stringify({
82 | runtime: 'edge',
83 | entrypoint: 'index.js',
84 | }),
85 | )
86 | await fsp.writeFile(
87 | '.vercel/output/config.json',
88 | stringify({
89 | version: 3,
90 | routes: [
91 | {
92 | src: '/(.*)',
93 | middlewarePath: '_middleware',
94 | continue: true,
95 | },
96 | {
97 | handle: 'filesystem',
98 | },
99 | ...[...names].map(name => ({
100 | src: `/${name}/(.*)`,
101 | dest: `/${name}`,
102 | })),
103 | ],
104 | }),
105 | )
106 |
107 | console.log('Successfully built nuxt/examples:')
108 | let index = 0
109 | const README = await fsp.readFile('README.md', 'utf-8')
110 | const missingPackages = []
111 | for (const name of names) {
112 | const treeChar = index++ === names.size - 1 ? '└─' : '├─'
113 | process.stdout.write(` ${treeChar} ${name}\n`)
114 | if (!README.includes(`https://${name}.example.nuxt.space`)) {
115 | missingPackages.push(name)
116 | }
117 | }
118 |
119 | if (missingPackages.length) {
120 | throw new Error(`Packages not found in README: ${missingPackages.join(', ')}`)
121 | }
122 |
--------------------------------------------------------------------------------
/.e2e/tests/features/meta-tags.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 | import { getSettingsForDeployment } from '@/utils'
3 |
4 | test.use(getSettingsForDeployment('meta-tags'))
5 |
6 | const INDEX_LANG = 'en'
7 | const INDEX_DEFAULT_TITLE = 'Lucky number: 1 - Meta Tags Example'
8 | const INDEX_DEFAULT_DESCRIPTION = 'My page\'s 1 description'
9 | const ABOUT_PAGE_TITLE = 'About page - Meta Tags Example'
10 | const ABOUT_PAGE_DESCRIPTION = 'This is the about page'
11 |
12 | test.describe('Index page', () => {
13 | test.beforeEach(async ({ page }) => {
14 | await page.goto('/')
15 | })
16 |
17 | test('HTML lang on index page is \'en\'', async ({ page }) => {
18 | await expect(page.locator('html')).toHaveAttribute('lang', INDEX_LANG)
19 | })
20 |
21 | test('Index page has \'my-body-class\' CSS class', async ({ page }) => {
22 | await expect(page.locator('body.my-body-class')).toBeVisible()
23 | })
24 |
25 | test('Lucky number is initially 1 in the title and description', async ({
26 | page,
27 | }) => {
28 | await expect(page.locator('meta[name="description"]')).toHaveAttribute(
29 | 'content',
30 | INDEX_DEFAULT_DESCRIPTION,
31 | )
32 | await expect(page).toHaveTitle(INDEX_DEFAULT_TITLE)
33 | })
34 | })
35 |
36 | test.describe('About page', () => {
37 | test.beforeEach(async ({ page }) => {
38 | await page.goto('/about')
39 | })
40 |
41 | test('\'my-body-class\' CSS class is not present on the body', async ({
42 | page,
43 | }) => {
44 | await expect(page.locator('body.my-body-class')).not.toBeVisible()
45 | await expect(page.locator('body')).toBeVisible()
46 | })
47 |
48 | test('Title and description is set', async ({ page }) => {
49 | await expect(page.locator('meta[name="description"]')).toHaveAttribute(
50 | 'content',
51 | ABOUT_PAGE_DESCRIPTION,
52 | )
53 | await expect(page).toHaveTitle(ABOUT_PAGE_TITLE)
54 | })
55 | })
56 |
57 | test.describe('Moving from index to about, and back to the index page', () => {
58 | test('HTML lang attribute changes', async ({ page }) => {
59 | await page.goto('/')
60 | await expect(page.locator('html')).toHaveAttribute('lang', INDEX_LANG)
61 |
62 | await page.getByRole('link', { name: 'About page' }).click()
63 | await expect(page.locator('html')).not.toHaveAttribute('lang', INDEX_LANG)
64 |
65 | await page.getByRole('link', { name: 'Back home' }).click()
66 | await expect(page.locator('html')).toHaveAttribute('lang', INDEX_LANG)
67 | })
68 |
69 | test('\'my-body-class\' CSS class removed then added back', async ({
70 | page,
71 | }) => {
72 | await page.goto('/')
73 | await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
74 | await expect(page.locator('body.my-body-class')).toBeVisible()
75 |
76 | await page.getByRole('link', { name: 'About page' }).click()
77 | await expect(page.locator('body.my-body-class')).not.toBeVisible()
78 | await expect(page.locator('body')).toBeVisible()
79 |
80 | await page.getByRole('link', { name: 'Back home' }).click()
81 | await expect(page.locator('body.my-body-class')).toBeVisible()
82 | })
83 |
84 | test('Title and description changes', async ({ page }) => {
85 | await page.goto('/')
86 | await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
87 | await expect(page.locator('meta[name="description"]')).toHaveAttribute(
88 | 'content',
89 | INDEX_DEFAULT_DESCRIPTION,
90 | )
91 | await expect(page).toHaveTitle(INDEX_DEFAULT_TITLE)
92 |
93 | await page.getByRole('link', { name: 'About page' }).click()
94 | await expect(page.locator('meta[name="description"]')).toHaveAttribute(
95 | 'content',
96 | ABOUT_PAGE_DESCRIPTION,
97 | )
98 | await expect(page).toHaveTitle(ABOUT_PAGE_TITLE)
99 |
100 | await page.getByRole('link', { name: 'Back home' }).click()
101 | await expect(page.locator('meta[name="description"]')).toHaveAttribute(
102 | 'content',
103 | INDEX_DEFAULT_DESCRIPTION,
104 | )
105 | await expect(page).toHaveTitle(INDEX_DEFAULT_TITLE)
106 | })
107 | })
108 |
--------------------------------------------------------------------------------
/.e2e/tests/advanced/error-handling.spec.ts:
--------------------------------------------------------------------------------
1 | import type { Page } from '@playwright/test'
2 | import { test, expect } from '@playwright/test'
3 | import { getSettingsForDeployment } from '@/utils'
4 |
5 | test.use(getSettingsForDeployment('error-handling'))
6 |
7 | test('Home page loads without any errors', async ({ page }) => {
8 | await page.goto('/')
9 | await expect(page.getByText('Current route: /')).toBeVisible()
10 | })
11 |
12 | test('Error in setup() runs the global error handler and vue:error hook', async ({
13 | page,
14 | }) => {
15 | const globalErrorHandlerPromise = waitForGlobalErrorHandlerToRan(page)
16 | const vueErrorHookPromise = waitForVueErrorHookToRan(page)
17 |
18 | await page.goto('?setup')
19 |
20 | await globalErrorHandlerPromise
21 | await vueErrorHookPromise
22 | })
23 |
24 | test('Error in mounted() runs the global error handler and vue:error hook', async ({
25 | page,
26 | }) => {
27 | const globalErrorHandlerPromise = waitForGlobalErrorHandlerToRan(page)
28 | const vueErrorHookPromise = waitForVueErrorHookToRan(page)
29 |
30 | await page.goto('?mounted')
31 |
32 | await globalErrorHandlerPromise
33 | await vueErrorHookPromise
34 | })
35 |
36 | test('404 error triggers app:error hook and navigates to the error page', async ({
37 | page,
38 | }) => {
39 | await page.goto('/')
40 |
41 | const appErrorHookPromise = waitForAppErrorHookToRan(page)
42 | await page.getByRole('link', { name: '404' }).click()
43 | await appErrorHookPromise
44 |
45 | await expect(
46 | page.getByRole('heading', { name: 'Page not found: /404' }),
47 | ).toBeVisible()
48 | await expect(page.getByText('There was an error')).toBeVisible()
49 | })
50 |
51 | test('Clearing the error on the 404 page navigates home', async ({ page }) => {
52 | await page.goto('/404')
53 |
54 | await page.getByRole('button', { name: 'Clear error' }).click()
55 |
56 | await expect(page.getByRole('link', { name: 'Home' })).toBeVisible()
57 | })
58 |
59 | test('Clicking on "Navigate home" on the 404 page navigates home', async ({
60 | page,
61 | }) => {
62 | await page.goto('/404')
63 |
64 | await page.getByRole('link', { name: 'Navigate home' }).click()
65 |
66 | await expect(page.getByRole('link', { name: 'Home' })).toBeVisible()
67 | })
68 |
69 | test('Error in middleware navigates to the error page and triggers the app:error hook', async ({
70 | page,
71 | }) => {
72 | await page.goto('/')
73 |
74 | const appErrorHookPromise = waitForAppErrorHookToRan(page)
75 | await page.getByRole('link', { name: 'Middleware' }).click()
76 | await appErrorHookPromise
77 |
78 | await expect(
79 | page.getByRole('heading', { name: 'error in middleware' }),
80 | ).toBeVisible()
81 | await expect(page.getByText('There was an error')).toBeVisible()
82 | })
83 |
84 | test('Clicking on the "Trigger fatal error" button navigates to the error page and triggers the app:error hook', async ({
85 | page,
86 | }) => {
87 | await page.goto('/')
88 | await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
89 |
90 | const appErrorHookPromise = waitForAppErrorHookToRan(page)
91 | await page.getByRole('button', { name: 'Trigger fatal error' }).click()
92 | await appErrorHookPromise
93 |
94 | await expect(page.getByText('There was an error')).toBeVisible()
95 | })
96 |
97 | test('Triggering non-fatal error with button runs the global error handler and vue:error hook', async ({
98 | page,
99 | }) => {
100 | await page.goto('/')
101 | await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
102 |
103 | const globalErrorHandlerPromise = waitForGlobalErrorHandlerToRan(page)
104 | const vueErrorHookPromise = waitForVueErrorHookToRan(page)
105 |
106 | await page.getByRole('button', { name: 'Trigger non-fatal error' }).click()
107 | await globalErrorHandlerPromise
108 | await vueErrorHookPromise
109 | })
110 |
111 | function waitForGlobalErrorHandlerToRan(page: Page) {
112 | return page.waitForEvent('console', {
113 | predicate: message => message.text() === 'global error handler',
114 | })
115 | }
116 |
117 | function waitForVueErrorHookToRan(page: Page) {
118 | return page.waitForEvent('console', {
119 | predicate: message => message.text() === 'vue:error',
120 | })
121 | }
122 |
123 | function waitForAppErrorHookToRan(page: Page) {
124 | return page.waitForEvent('console', {
125 | predicate: message => message.text() === 'app:error',
126 | })
127 | }
128 |
--------------------------------------------------------------------------------
/shared/components/NuxtExample.vue:
--------------------------------------------------------------------------------
1 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
59 |
60 |
61 |
62 |
67 |
68 |
69 |
70 |
71 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
92 |
93 |
101 | {{ item.label }}
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
114 |
115 |
119 | Current route:
123 |
124 |
129 | {{ dir }}
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
150 |
--------------------------------------------------------------------------------
/examples/auth/local/pages/login.vue:
--------------------------------------------------------------------------------
1 |
38 |
39 |
40 |
41 |
45 |
46 |
50 |
51 |
52 |
53 |
57 |
58 |
59 | {{ item.label }}
60 |
61 |
62 | Log in to your account.
63 |
64 |
65 |
66 |
67 |
68 |
74 |
79 |
80 |
85 |
91 |
92 |
99 |
100 |
101 |
102 |
103 |
104 |
108 | Log in
109 |
110 |
111 |
112 |
113 |
114 |
115 |
119 |
120 |
121 |
122 |
126 |
127 |
128 | {{ item.label }}
129 |
130 |
131 | Create an account
132 |
133 |
134 |
135 |
136 |
137 |
143 |
148 |
149 |
154 |
161 |
162 |
169 |
170 |
171 |
172 |
173 |
174 |
179 | Register
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
--------------------------------------------------------------------------------