├── .dockerignore ├── .editorconfig ├── .eslintrc.cjs ├── .gitignore ├── .husky └── pre-commit ├── .lintstagedrc.json ├── .npmrc ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── compose.production.yaml ├── compose.yaml ├── i18n.config.ts ├── nuxt.config.ts ├── package-lock.json ├── package.json ├── public └── favicon.ico ├── src ├── app.vue ├── assets │ └── images │ │ └── cat.jpg ├── components │ ├── Container.vue │ ├── Counter.vue │ ├── HelloWorld.vue │ ├── LocaleSwitch.vue │ └── UserList.vue ├── composables │ └── useAsset.ts ├── error.vue ├── layouts │ ├── default.vue │ └── empty.vue ├── pages │ ├── [...slug].vue │ ├── index.vue │ └── users.vue ├── server │ └── api │ │ └── v1 │ │ └── hello.get.ts ├── stores │ └── counter.ts └── types │ └── index.ts ├── tests └── components │ └── HelloWorld.spec.ts ├── tsconfig.json └── vitest.config.js /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/.next 12 | **/.nuxt 13 | **/.output 14 | **/.cache 15 | **/*.*proj.user 16 | **/*.dbmdl 17 | **/*.jfm 18 | **/charts 19 | **/docker-compose* 20 | **/compose* 21 | **/Dockerfile* 22 | **/node_modules 23 | **/npm-debug.log 24 | **/obj 25 | **/secrets.dev.yaml 26 | **/values.dev.yaml 27 | **/build 28 | **/dist 29 | LICENSE 30 | README.md 31 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.md] 4 | trim_trailing_whitespace = false 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | max_line_length = 100 13 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | es2021: true, 4 | node: true 5 | }, 6 | extends: [ 7 | 'eslint:recommended', 8 | 'plugin:vue/vue3-essential', 9 | 'plugin:@typescript-eslint/recommended', 10 | '@nuxtjs/eslint-config-typescript' 11 | ], 12 | overrides: [ 13 | ], 14 | parserOptions: { 15 | ecmaVersion: 'latest', 16 | parser: '@typescript-eslint/parser', 17 | sourceType: 'module' 18 | }, 19 | plugins: [ 20 | 'vue', 21 | '@typescript-eslint' 22 | ], 23 | rules: { 24 | 'vue/multi-word-component-names': 'off', 25 | 'vue/no-multiple-template-root': 'off' 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log* 3 | .nuxt 4 | .nitro 5 | .cache 6 | .output 7 | .env 8 | dist 9 | .DS_Store 10 | *.local 11 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /.lintstagedrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "*.{js,ts,vue}": "npm run lint:fix" 3 | } 4 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | strict-peer-dependencies=false 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | ARG NODE_VERSION=18.14.2 4 | 5 | ################################################################################ 6 | # Set the base image 7 | FROM node:${NODE_VERSION}-alpine AS base 8 | # Set the working directory 9 | WORKDIR /usr/src/app 10 | 11 | ################################################################################ 12 | # Create a stage for installing dependecies 13 | FROM base as dependencies 14 | # Copy the package.json and package-lock.json 15 | COPY package*.json ./ 16 | # Install dependencies 17 | RUN npm install 18 | 19 | ################################################################################ 20 | # Create a stage for running the application in development mode 21 | FROM dependencies as development 22 | # Copy the source code 23 | COPY . . 24 | # Expose the port 25 | EXPOSE 3000 26 | # Run the application 27 | CMD [ "npm", "run", "dev" ] 28 | 29 | ################################################################################ 30 | # Create a stage for building the application 31 | FROM dependencies as build 32 | # Copy the source code 33 | COPY . . 34 | # Build the application 35 | RUN npm run build 36 | # Remove extraneous packages 37 | RUN npm prune 38 | 39 | ################################################################################ 40 | # Create a stage for running the application in production mode 41 | FROM base AS production 42 | # Copy the built application 43 | COPY --from=build /usr/src/app/.output /usr/src/app/.output 44 | # Run the application 45 | CMD [ "node", ".output/server/index.mjs" ] 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Bogdan Morozyuk 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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | dev-up: 2 | docker compose up --build -d 3 | dev-down: 4 | docker compose down 5 | prod-up: 6 | docker compose -f compose.production.yaml up --build -d 7 | prod-down: 8 | docker compose -f compose.production.yaml down 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nuxt 3 Boilerplate 2 | 3 | A Nuxt 3 starter boilerplate with a lot of useful features. 4 | 5 | ## Quick Start 6 | 7 | - This project using `npm` as package manager 8 | - Clone this project to your computer `git clone https://github.com/yuzumi/nuxt3-boilerplate` 9 | - Install dependencies `npm install` 10 | - Run `npm run dev` to start development server and open `http://localhost:3000` in your browser 11 | 12 | ## Available scripts 13 | 14 | ### Setup 15 | 16 | Make sure to install the dependencies: 17 | 18 | ```bash 19 | npm install 20 | ``` 21 | 22 | ### DevTools 23 | 24 | Enable devtools: 25 | 26 | ```bash 27 | npm run devtools:enable 28 | ``` 29 | 30 | Disable devtools: 31 | 32 | ```bash 33 | npm run devtools:disable 34 | ``` 35 | 36 | ### Lint & format 37 | 38 | Manually check types: 39 | 40 | ```bash 41 | npm run typecheck 42 | ``` 43 | 44 | Find ESLint errors: 45 | 46 | ```bash 47 | npm run lint 48 | ``` 49 | 50 | Find ESLint errors and try to fix them: 51 | 52 | ```bash 53 | npm run lint:fix 54 | ``` 55 | 56 | ### Development Server 57 | 58 | Start the development server on 59 | 60 | ```bash 61 | npm run dev 62 | ``` 63 | 64 | ### Production 65 | 66 | Build the application for production: 67 | 68 | ```bash 69 | npm run build 70 | ``` 71 | 72 | Locally preview production build: 73 | 74 | ```bash 75 | npm run preview 76 | ``` 77 | 78 | Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information. 79 | 80 | ### Docker 81 | 82 | Create and start the development container: 83 | 84 | ```bash 85 | make dev-up 86 | ``` 87 | 88 | Stop and remove the development container: 89 | 90 | ```bash 91 | make dev-down 92 | ``` 93 | 94 | Create and start the production container: 95 | 96 | ```bash 97 | make prod-up 98 | ``` 99 | 100 | Stop and remove the production container: 101 | 102 | ```bash 103 | make prod-down 104 | ``` 105 | 106 | ## Features 107 | 108 | - [x] `src` directory 109 | - [x] [ESLint](https://qiita.com/kentarou_masuda/items/c0180fe383b01ba54cbf) 110 | - [x] [Strict type-checking](https://nuxt.com/docs/guide/concepts/typescript) 111 | - [x] [Husky](https://typicode.github.io/husky/) & [Lint-staged](https://github.com/okonet/lint-staged) 112 | - [x] [i18n](https://v8.i18n.nuxtjs.org/) 113 | - [x] [VueUse](https://vueuse.org/) 114 | - [x] [Pinia](https://pinia.vuejs.org/) 115 | - [x] [Nuxt DevTools](https://devtools.nuxtjs.org/) 116 | - [x] [Vitest](https://vitest.dev/) 117 | - [x] Layouts 118 | - [x] [Default](./src/layouts/default.vue) 119 | - [x] [Empty](./src/layouts/empty.vue) 120 | - [x] [Error page](./src/error.vue) 121 | - [x] [404 page](./src/pages/%5B...slug%5D.vue) 122 | - [x] [Global types](./src/types/index.ts) 123 | - [x] Composables 124 | - [x] [useAsset](./src/composables/asset.ts) 125 | 126 | ## Setup notes 127 | 128 | ### src directory 129 | 130 | 1. Set `srcDir` option in `nuxt.config` file. 131 | 132 | ```typescript 133 | // nuxt.config.ts 134 | 135 | export default defineNuxtConfig({ 136 | srcDir: 'src/', 137 | }); 138 | ``` 139 | 140 | ### ESLint 141 | 142 | 1. Install needed devDependencies 143 | 144 | ```bash 145 | npm i -D eslint eslint-plugin-vue 146 | ``` 147 | 148 | ```bash 149 | npm i -D typescript @typescript-eslint/eslint-plugin @typescript-eslint/parser @nuxtjs/eslint-config-typescript 150 | ``` 151 | 152 | 2. Generate config file 153 | 154 | ```bash 155 | npx eslint --init 156 | 157 | > How would you like to use ESLint? To check syntax and find problems 158 | > What type of modules does your project use? JavaScript modules (import/export) 159 | > Which framework does your project use? Vue.js 160 | > Does your project use TypeScript? Yes 161 | > Where does your code run? Node 162 | > What format do you want your config file to be in? JavaScript 163 | > Would you like to install them now? No 164 | ``` 165 | 166 | ```javascript 167 | // .eslintrc.cjs 168 | 169 | module.exports = { 170 | "env": { 171 | "es2021": true, 172 | "node": true 173 | }, 174 | "extends": [ 175 | "eslint:recommended", 176 | "plugin:vue/essential", 177 | "plugin:@typescript-eslint/recommended", 178 | "@nuxtjs/eslint-config-typescript" // Add here 179 | ], 180 | "parserOptions": { 181 | "ecmaVersion": 13, 182 | "parser": "@typescript-eslint/parser", 183 | "sourceType": "module" 184 | }, 185 | "plugins": [ 186 | "vue", 187 | "@typescript-eslint" 188 | ], 189 | "rules": { 190 | } 191 | }; 192 | ``` 193 | 194 | 3. Add task scripts 195 | 196 | ```json 197 | "scripts": { 198 | "lint": "eslint --ext .ts,.js,.vue .", 199 | "lint:fix": "eslint --fix --ext .ts,.js,.vue ." 200 | }, 201 | ``` 202 | 203 | 4. Update your VS Code settings to look like this: 204 | 205 | ```json 206 | { 207 | "eslint.format.enable": true, 208 | "editor.codeActionsOnSave": { 209 | "source.fixAll.eslint": true 210 | } 211 | } 212 | ``` 213 | 214 | ### Strict type-checking 215 | 216 | 1. Install needed devDependencies 217 | 218 | ```bash 219 | npm i -D vue-tsc typescript @types/node 220 | ``` 221 | 222 | 2. Enable the `typescript.typeCheck` option in your `nuxt.config` file. 223 | 224 | ```typescript 225 | export default defineNuxtConfig({ 226 | typescript: { 227 | strict: true, 228 | typeCheck: true, 229 | }, 230 | }); 231 | ``` 232 | 233 | 3. Optionally add task script to manually check your types with `nuxi`. 234 | 235 | ```json 236 | { 237 | "scripts": { 238 | "typecheck": "npx nuxi typecheck", 239 | }, 240 | } 241 | ``` 242 | 243 | ### Husky & Lint-staged 244 | 245 | 1. Install Husky 246 | 247 | ```bash 248 | npx husky-init && npm install 249 | ``` 250 | 251 | 2. Install Lint-staged 252 | 253 | ```bash 254 | npm install --save-dev lint-staged 255 | ``` 256 | 257 | 3. Inside `.husky/pre-commit` replace `npm test` with `npx lint-staged`. 258 | 259 | ```txt 260 | #!/usr/bin/env sh 261 | . "$(dirname -- "$0")/_/husky.sh" 262 | 263 | npx lint-staged 264 | ``` 265 | 266 | 4. In the root directory of your project, create the file `.lintstagedrc.json` 267 | with the following contents: 268 | 269 | ```json 270 | { 271 | "*.{js,jsx,vue,ts,tsx}": "npm run lint:fix" 272 | } 273 | ``` 274 | 275 | ### VueUse 276 | 277 | 1. Install VueUse 278 | 279 | ```bash 280 | npm i -D @vueuse/nuxt @vueuse/core 281 | ``` 282 | 283 | 2. Add VueUse to `nuxt.config` file 284 | 285 | ```typescript 286 | // nuxt.config.ts 287 | 288 | export default defineNuxtConfig({ 289 | modules: [ 290 | '@vueuse/nuxt', 291 | ], 292 | }) 293 | ``` 294 | 295 | ### Pinia 296 | 297 | 1. Install Pinia 298 | 299 | ```bash 300 | npm i pinia @pinia/nuxt 301 | ``` 302 | 303 | 2. Add Pinia to `nuxt.config` file 304 | 305 | ```typescript 306 | // nuxt.config.ts 307 | 308 | export default defineNuxtConfig({ 309 | imports: { 310 | // Auto-import pinia stores defined in `~/stores` 311 | dirs: ['stores'] 312 | }, 313 | modules: [ 314 | '@pinia/nuxt', 315 | ], 316 | pinia: { 317 | autoImports: [ 318 | 'defineStore', 319 | 'storeToRefs', 320 | ], 321 | }, 322 | }); 323 | ``` 324 | 325 | ### Nuxt DevTools 326 | 327 | 1. To enable devtools run: 328 | 329 | ```bash 330 | npm run devtools:enable 331 | ``` 332 | 333 | 2. To disable devtools run: 334 | 335 | ```bash 336 | npm run devtools:disable 337 | ``` 338 | 339 | ### Vitest 340 | 341 | 1. Install the following dependencies: 342 | 343 | ```bash 344 | npm i -D vitest jsdom @vitejs/plugin-vue 345 | ``` 346 | 347 | ```bash 348 | npm i -D @vue/test-utils @nuxt/test-utils 349 | ``` 350 | 351 | 2. Create your Vitest configuration file (vitest.config.js): 352 | 353 | ```javascript 354 | // vitest.config.js 355 | 356 | import { defineConfig } from 'vite' 357 | import vue from '@vitejs/plugin-vue' 358 | 359 | export default defineConfig({ 360 | plugins: [vue()], 361 | test: { 362 | globals: true, 363 | environment: 'jsdom', 364 | }, 365 | }) 366 | ``` 367 | 368 | 3. Add the following script to your project: 369 | 370 | ```json 371 | { 372 | "scripts": { 373 | "test": "vitest" 374 | } 375 | } 376 | ``` 377 | 378 | 4. Create your first test: 379 | 380 | 381 | ```typescript 382 | // tests/components/HelloWorld.vue 383 | 384 | import { describe, it, expect } from 'vitest' 385 | import { mount } from '@vue/test-utils' 386 | 387 | import HelloWorld from '../../src/components/HelloWorld.vue'; 388 | 389 | describe('HelloWorld', () => { 390 | it('renders correctly', () => { 391 | const wrapper = mount(HelloWorld) 392 | expect(wrapper.html()).contain('Hello, world!') 393 | }) 394 | }) 395 | ``` 396 | 397 | ### Global types 398 | 399 | 1. At the root of your project create a directory named `types` with an `index.ts` file. 400 | 2. Add your global types declaration like in the example below. 401 | 402 | ```typescript 403 | // ~/types/index.ts 404 | 405 | export { }; 406 | 407 | declare global { 408 | interface User { 409 | id: string; 410 | name: string; 411 | email: string; 412 | } 413 | } 414 | ``` 415 | 416 | ## Templates 417 | 418 | Other templates you may be interested in: 419 | 420 | - [nuxt3-awesome-starter](https://github.com/viandwi24/nuxt3-awesome-starter) 421 | - [nuxt3-starter ](https://github.com/xiaoluoboding/nuxt3-starter) 422 | - [nuxt3-boilerplate](https://github.com/taunoha/nuxt3-boilerplate) 423 | - [nuxt3-eslint-starter](https://github.com/weicheng2138/nuxt3-eslint-starter) 424 | 425 | ## License 426 | 427 | MIT [@yuzumi](https://github.com/yuzumi) 428 | -------------------------------------------------------------------------------- /compose.production.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | app: 3 | build: 4 | context: . 5 | target: production 6 | ports: 7 | - 3000:3000 8 | -------------------------------------------------------------------------------- /compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | app: 3 | build: 4 | context: . 5 | target: development 6 | ports: 7 | - 3000:3000 8 | - 24678:24678 9 | volumes: 10 | - ./src:/usr/src/app/src 11 | - /usr/src/app/node_modules 12 | -------------------------------------------------------------------------------- /i18n.config.ts: -------------------------------------------------------------------------------- 1 | export default defineI18nConfig(() => ({ 2 | legacy: false, 3 | locale: 'en', 4 | messages: { 5 | en: { 6 | welcome: 'Welcome' 7 | }, 8 | fr: { 9 | welcome: 'Bienvenue' 10 | } 11 | } 12 | })) 13 | -------------------------------------------------------------------------------- /nuxt.config.ts: -------------------------------------------------------------------------------- 1 | // https://nuxt.com/docs/api/configuration/nuxt-config 2 | export default defineNuxtConfig({ 3 | srcDir: 'src/', 4 | typescript: { 5 | strict: true, 6 | typeCheck: true 7 | }, 8 | imports: { 9 | // Auto-import pinia stores defined in `~/stores` 10 | dirs: ['stores'] 11 | }, 12 | modules: [ 13 | // Installed modules 14 | '@vueuse/nuxt', 15 | '@pinia/nuxt', 16 | '@nuxtjs/i18n' 17 | ], 18 | pinia: { 19 | autoImports: [ 20 | 'defineStore', 21 | 'storeToRefs' 22 | ] 23 | }, 24 | i18n: { 25 | strategy: 'prefix_except_default', 26 | detectBrowserLanguage: false, 27 | locales: [ 28 | { 29 | code: 'en', 30 | iso: 'en-US', 31 | name: 'English' 32 | }, 33 | { 34 | code: 'fr', 35 | iso: 'fr-FR', 36 | name: 'Français' 37 | } 38 | ], 39 | defaultLocale: 'en' 40 | } 41 | }) 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt3-boilerplate", 3 | "private": true, 4 | "type": "module", 5 | "author": { 6 | "name": "Bogdan Morozyuk", 7 | "email": "bogdan7morozyuk@gmail.com", 8 | "url": "https://github.com/yuzumi" 9 | }, 10 | "overrides": { 11 | "vue": "latest" 12 | }, 13 | "scripts": { 14 | "build": "nuxt build", 15 | "dev": "nuxt dev", 16 | "generate": "nuxt generate", 17 | "preview": "nuxt preview", 18 | "postinstall": "nuxt prepare && husky install", 19 | "typecheck": "npx nuxi typecheck", 20 | "devtools:enable": "npx nuxi@latest devtools enable", 21 | "devtools:disable": "npx nuxi@latest devtools disable", 22 | "lint": "eslint --ext .ts,.js,.vue .", 23 | "lint:fix": "eslint --fix --ext .ts,.js,.vue .", 24 | "test": "vitest", 25 | "prepare": "husky install" 26 | }, 27 | "devDependencies": { 28 | "@nuxt/test-utils": "^3.4.3", 29 | "@nuxtjs/eslint-config-typescript": "^12.0.0", 30 | "@nuxtjs/i18n": "^8.0.0-beta.12", 31 | "@types/node": "^18.15.11", 32 | "@typescript-eslint/eslint-plugin": "^5.57.1", 33 | "@typescript-eslint/parser": "^5.57.1", 34 | "@vitejs/plugin-vue": "^4.2.1", 35 | "@vue/test-utils": "^2.3.2", 36 | "@vueuse/core": "^9.13.0", 37 | "@vueuse/nuxt": "^9.13.0", 38 | "eslint": "^8.37.0", 39 | "eslint-plugin-vitest": "^0.1.4", 40 | "eslint-plugin-vue": "^9.10.0", 41 | "husky": "^8.0.0", 42 | "jsdom": "^21.1.1", 43 | "lint-staged": "^13.2.2", 44 | "nuxt": "^3.3.2", 45 | "typescript": "^5.0.3", 46 | "vitest": "^0.30.1", 47 | "vue-tsc": "^1.2.0" 48 | }, 49 | "dependencies": { 50 | "@pinia/nuxt": "^0.4.7", 51 | "pinia": "^2.0.33" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bohdanmoroziuk/nuxt3-boilerplate/81de023296d1d2cd246762887d13cbf13d968f0b/public/favicon.ico -------------------------------------------------------------------------------- /src/app.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 41 | -------------------------------------------------------------------------------- /src/assets/images/cat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bohdanmoroziuk/nuxt3-boilerplate/81de023296d1d2cd246762887d13cbf13d968f0b/src/assets/images/cat.jpg -------------------------------------------------------------------------------- /src/components/Container.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /src/components/Counter.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | 19 | 26 | 33 | -------------------------------------------------------------------------------- /src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/components/LocaleSwitch.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 22 | -------------------------------------------------------------------------------- /src/components/UserList.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 20 | -------------------------------------------------------------------------------- /src/composables/useAsset.ts: -------------------------------------------------------------------------------- 1 | export function useAsset (path: string): string { 2 | const assets = import.meta.glob('~/assets/**/*', { 3 | eager: true, 4 | import: 'default' 5 | }) 6 | 7 | // @ts-expect-error: wrong type info 8 | return assets['/assets/' + path] 9 | } 10 | -------------------------------------------------------------------------------- /src/error.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 34 | -------------------------------------------------------------------------------- /src/layouts/default.vue: -------------------------------------------------------------------------------- 1 | 3 | 4 | 15 | -------------------------------------------------------------------------------- /src/layouts/empty.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/pages/[...slug].vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | -------------------------------------------------------------------------------- /src/pages/index.vue: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | -------------------------------------------------------------------------------- /src/pages/users.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 21 | -------------------------------------------------------------------------------- /src/server/api/v1/hello.get.ts: -------------------------------------------------------------------------------- 1 | export default defineEventHandler(() => { 2 | return { 3 | message: 'Hello!' 4 | } 5 | }) 6 | -------------------------------------------------------------------------------- /src/stores/counter.ts: -------------------------------------------------------------------------------- 1 | export interface CounterState { 2 | count: number; 3 | } 4 | 5 | export const useCounterStore = defineStore('counter', () => { 6 | const state = ref({ 7 | count: 0 8 | }) 9 | 10 | const count = computed(() => state.value.count) 11 | 12 | const increment = () => { 13 | state.value.count += 1 14 | } 15 | 16 | const decrement = () => { 17 | state.value.count -= 1 18 | } 19 | 20 | return { 21 | count, 22 | increment, 23 | decrement 24 | } 25 | }) 26 | -------------------------------------------------------------------------------- /src/types/index.ts: -------------------------------------------------------------------------------- 1 | export {} 2 | 3 | declare global { 4 | interface User { 5 | id: string; 6 | name: string; 7 | email: string; 8 | } 9 | 10 | interface Post { 11 | id: string; 12 | title: string; 13 | body: string; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/components/HelloWorld.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest' 2 | import { mount } from '@vue/test-utils' 3 | 4 | import HelloWorld from '../../src/components/HelloWorld.vue' 5 | 6 | describe('HelloWorld', () => { 7 | it('renders correctly', () => { 8 | const wrapper = mount(HelloWorld) 9 | expect(wrapper.html()).contain('Hello, world!') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://nuxt.com/docs/guide/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json", 4 | "compilerOptions": { 5 | "types": ["node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /vitest.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | export default defineConfig({ 5 | plugins: [vue()], 6 | test: { 7 | globals: true, 8 | environment: 'jsdom' 9 | } 10 | }) 11 | --------------------------------------------------------------------------------