├── .npmrc
├── pages
└── index.vue
├── tsconfig.json
├── server
└── tsconfig.json
├── layouts
└── default.vue
├── public
├── favicon.ico
└── gradients
│ ├── hero-gradient-mobile.svg
│ ├── hero-gradient-tablet.svg
│ └── hero-gradient.svg
├── .gitignore
├── app.vue
├── .editorconfig
├── .vscode
├── extensions.json
└── settings.json
├── uno.config.ts
├── nuxt.config.ts
├── package.json
├── LICENSE
├── components
├── global
│ ├── NuxtDark.vue
│ └── Pinia.vue
└── Welcome.vue
├── README.md
└── eslint.config.js
/.npmrc:
--------------------------------------------------------------------------------
1 | shamefully-hoist=true
--------------------------------------------------------------------------------
/pages/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/server/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../.nuxt/tsconfig.server.json"
3 | }
4 |
--------------------------------------------------------------------------------
/layouts/default.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/matijaoe/nuxt-starter/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.log*
3 | .nuxt
4 | .nitro
5 | .cache
6 | .output
7 | .env
8 | dist
9 | .vercel
10 | .netlify
11 | **/.DS_Store
12 |
--------------------------------------------------------------------------------
/app.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "antfu.iconify",
4 | "antfu.unocss",
5 | "antfu.goto-alias",
6 | "csstools.postcss",
7 | "dbaeumer.vscode-eslint",
8 | "vue.volar",
9 | "matijao.vue-nuxt-snippets"
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/uno.config.ts:
--------------------------------------------------------------------------------
1 | import {
2 | defineConfig,
3 | presetAttributify,
4 | presetTypography,
5 | presetUno,
6 | presetWebFonts,
7 | transformerDirectives,
8 | transformerVariantGroup,
9 | } from 'unocss'
10 |
11 | export default defineConfig({
12 | presets: [
13 | presetUno(),
14 | presetAttributify(),
15 | presetTypography(),
16 | presetWebFonts({
17 | fonts: {
18 | sans: 'DM Sans',
19 | serif: 'DM Serif Display',
20 | mono: 'DM Mono',
21 | },
22 | }),
23 | ],
24 | transformers: [
25 | transformerDirectives(),
26 | transformerVariantGroup(),
27 | ],
28 | })
29 |
--------------------------------------------------------------------------------
/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 | modules: [
3 | '@unocss/nuxt',
4 | '@vueuse/nuxt',
5 | '@pinia/nuxt',
6 | 'nuxt-icon',
7 | '@nuxt/image',
8 | '@nuxtjs/color-mode',
9 | ],
10 |
11 | devtools: {
12 | enabled: true,
13 | },
14 |
15 | experimental: {
16 | typedPages: true,
17 | cookieStore: true,
18 | },
19 |
20 | features: {
21 | inlineStyles: false,
22 | },
23 |
24 | postcss: {
25 | plugins: {
26 | 'postcss-nesting': {},
27 | },
28 | },
29 |
30 | unocss: {
31 | preflight: true,
32 | },
33 |
34 | app: {
35 | head: {
36 | title: 'Nuxt Starter',
37 | },
38 | },
39 | })
40 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nuxt-starter",
3 | "type": "module",
4 | "private": true,
5 | "packageManager": "pnpm@9.1.0",
6 | "license": "MIT",
7 | "engines": {
8 | "node": ">=20"
9 | },
10 | "scripts": {
11 | "build": "nuxt build",
12 | "dev": "nuxt dev",
13 | "dev:tunnel": "nuxt dev --tunnel",
14 | "generate": "nuxt generate",
15 | "preview": "nuxt preview",
16 | "postinstall": "nuxt prepare",
17 | "lint": "eslint .",
18 | "format": "eslint . --fix"
19 | },
20 | "devDependencies": {
21 | "@antfu/eslint-config": "^2.20.0",
22 | "@nuxt/image": "^1.7.0",
23 | "@nuxtjs/color-mode": "^3.4.1",
24 | "@pinia/nuxt": "^0.5.1",
25 | "@unocss/eslint-config": "0.60.4",
26 | "@unocss/eslint-plugin": "^0.60.4",
27 | "@unocss/nuxt": "0.60.4",
28 | "@vueuse/nuxt": "10.10.0",
29 | "eslint": "^9.4.0",
30 | "eslint-plugin-format": "^0.1.1",
31 | "nuxt": "^3.11.2",
32 | "nuxt-icon": "0.6.10",
33 | "pinia": "^2.1.7",
34 | "postcss-nesting": "^12.1.5",
35 | "vue": "^3.4.27",
36 | "vue-router": "^4.3.2"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023-present, Matija Osrecki
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 |
--------------------------------------------------------------------------------
/components/global/NuxtDark.vue:
--------------------------------------------------------------------------------
1 |
2 |
31 |
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🧚🏻 Nuxt 3 starter template
2 |
3 | > Minimal Nuxt 3 starter template pre-configured with essential modules
4 |
5 |
6 |
7 |
8 |
9 |
10 | ## Included
11 | - [UnoCSS](https://github.com/unocss/unocss)
12 | - [`presetUno`](https://github.com/unocss/unocss/tree/main/packages/preset-uno)
13 | - [`presetAttributify`](https://github.com/unocss/unocss/tree/main/packages/preset-attributify)
14 | - [`presetTypography`](https://github.com/unocss/unocss/tree/main/packages/preset-typography)
15 | - [`presetWebFonts`](https://github.com/unocss/unocss/tree/main/packages/preset-web-fonts)
16 | - [`transformerDirectives`](https://github.com/unocss/unocss/tree/main/packages/transformer-directives)
17 | - [`transformerVariantGroup`](https://github.com/unocss/unocss/tree/main/packages/transformer-variant-group)
18 | - [VueUse](https://vueuse.org/)
19 | - [Pinia](https://pinia.vuejs.org/)
20 | - [TypeScript](https://www.typescriptlang.org/)
21 | - [PostCSS Nesting](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-nesting)
22 | - [ESLint](https://github.com/matijaoe/eslint-config)
23 | - [pnpm](https://pnpm.io/)
24 |
25 | ### Modules
26 | - [`@nuxt/devtools`](https://nuxt.com/modules/devtools)
27 | - [`nuxt-icon`](https://github.com/nuxt-modules/icon)
28 | - [`@nuxt/image`](https://image.nuxt.com/)
29 | - [`@nuxtjs/color-mode`](https://color-mode.nuxtjs.org/)
30 |
31 | ## Use the template
32 |
33 | ### StackBlitz
34 |
35 | [](https://stackblitz.com/github/matijaoe/nuxt-starter)
36 | [](https://pr.new/matijaoe/nuxt-starter)
37 |
38 | ### GitHub Template
39 | [Create a repo from this template on GitHub](https://github.com/matijaoe/nuxt-starter/generate)
40 |
41 | ### Local
42 | Clone the template locally, with no git history (using [`unjs/giget`](https://github.com/unjs/giget))
43 |
44 | ```bash
45 | npx giget gh:matijaoe/nuxt-starter
46 | ```
47 |
48 | ## Checklist
49 |
50 | - [ ] Install the recommended extensions
51 | - [ ] Change the author name in `LICENSE`
52 | - [ ] Delete `gradients` directory in `public`
53 | - [ ] Delete `Welcome.vue` component
54 | - [ ] Delete icon components in `components/global`
55 | - [ ] Remove any not needed modules from `nuxt.config.ts` and `package.json`
56 | - [ ] Customize `README.md`
57 |
58 | ## Setup
59 |
60 | ```bash
61 | # install dependencies
62 | pnpm i
63 |
64 | # update dependencies
65 | pnpm up --interactive --latest
66 |
67 | # start development server
68 | pnpm dev
69 |
70 | # build for production
71 | pnpm build
72 |
73 | # locally preview production build
74 | pnpm preview
75 | ```
76 |
77 | ## Related
78 |
79 | - 👽 [`vue-starter`](https://github.com/matijaoe/vue-starter)
80 | - 🔮 [`vue-anu-starter`](https://github.com/matijaoe/vue-anu-starter)
81 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.associations": {
3 | "*.css": "postcss"
4 | },
5 |
6 | // Enable the ESlint flat config support
7 | "eslint.experimental.useFlatConfig": true,
8 |
9 | // Disable the default formatter, use eslint instead
10 | "prettier.enable": false,
11 | "editor.formatOnSave": false,
12 |
13 | // Auto fix
14 | "editor.codeActionsOnSave": {
15 | "source.fixAll.eslint": "explicit",
16 | "source.organizeImports": "never"
17 | },
18 |
19 | // Silent the stylistic rules in you IDE, but still auto fix them
20 | "eslint.rules.customizations": [
21 | {
22 | "rule": "style/*",
23 | "severity": "off"
24 | },
25 | {
26 | "rule": "*-indent",
27 | "severity": "off"
28 | },
29 | {
30 | "rule": "*-spacing",
31 | "severity": "off"
32 | },
33 | {
34 | "rule": "*-spaces",
35 | "severity": "off"
36 | },
37 | {
38 | "rule": "*-order",
39 | "severity": "off"
40 | },
41 | {
42 | "rule": "*-dangle",
43 | "severity": "off"
44 | },
45 | {
46 | "rule": "*-newline",
47 | "severity": "off"
48 | },
49 | {
50 | "rule": "*quotes",
51 | "severity": "off"
52 | },
53 | {
54 | "rule": "*semi",
55 | "severity": "off"
56 | }
57 | ],
58 |
59 | // Enable eslint for all supported languages
60 | "eslint.validate": [
61 | "javascript",
62 | "javascriptreact",
63 | "typescript",
64 | "typescriptreact",
65 | "vue",
66 | "html",
67 | "markdown",
68 | "json",
69 | "jsonc",
70 | "yaml"
71 | ],
72 | // Enable the ESlint flat config support
73 | "eslint.experimental.useFlatConfig": true,
74 |
75 | // Disable the default formatter, use eslint instead
76 | "prettier.enable": false,
77 | "editor.formatOnSave": false,
78 |
79 | // Auto fix
80 | "editor.codeActionsOnSave": {
81 | "source.fixAll.eslint": "explicit",
82 | "source.organizeImports": "never"
83 | },
84 |
85 | // Silent the stylistic rules in you IDE, but still auto fix them
86 | "eslint.rules.customizations": [
87 | { "rule": "style/*", "severity": "off" },
88 | { "rule": "format/*", "severity": "off" },
89 | { "rule": "*-indent", "severity": "off" },
90 | { "rule": "*-spacing", "severity": "off" },
91 | { "rule": "*-spaces", "severity": "off" },
92 | { "rule": "*-order", "severity": "off" },
93 | { "rule": "*-dangle", "severity": "off" },
94 | { "rule": "*-newline", "severity": "off" },
95 | { "rule": "*quotes", "severity": "off" },
96 | { "rule": "*semi", "severity": "off" }
97 | ],
98 |
99 | // Enable eslint for all supported languages
100 | "eslint.validate": [
101 | "javascript",
102 | "javascriptreact",
103 | "typescript",
104 | "typescriptreact",
105 | "vue",
106 | "html",
107 | "markdown",
108 | "json",
109 | "jsonc",
110 | "yaml",
111 | "toml",
112 | "astro",
113 | ]
114 | }
115 |
--------------------------------------------------------------------------------
/public/gradients/hero-gradient-mobile.svg:
--------------------------------------------------------------------------------
1 |
65 |
--------------------------------------------------------------------------------
/components/Welcome.vue:
--------------------------------------------------------------------------------
1 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
71 |
72 |
73 |
74 |
75 | -
76 |
77 |
78 | {{ link.label }}
79 |
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 | {{ link.label }}
88 |
89 |
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 | {{ link.label }}
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
117 |
--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------
1 | import antfu from '@antfu/eslint-config'
2 |
3 | export default antfu({
4 | formatters: true,
5 | unocss: true,
6 | vue: true,
7 |
8 | ignores: [
9 | '**/dist',
10 | '**/.output',
11 | '**/.nuxt',
12 | '**/node_modules',
13 | ],
14 |
15 | javascript: {
16 | overrides: {
17 | 'default-param-last': 'error',
18 | 'no-console': ['warn', { allow: ['info', 'warn', 'error'] }],
19 | 'no-param-reassign': 'warn',
20 | 'no-unused-vars': [
21 | 'error',
22 | {
23 | args: 'after-used',
24 | caughtErrors: 'none',
25 | ignoreRestSiblings: true,
26 | vars: 'all',
27 | },
28 | ],
29 | 'no-use-before-define': [
30 | 'error',
31 | {
32 | allowNamedExports: false,
33 | classes: false,
34 | functions: false,
35 | variables: true,
36 | },
37 | ],
38 | 'unused-imports/no-unused-imports': 'warn',
39 | 'unused-imports/no-unused-vars': [
40 | 'error',
41 | {
42 | args: 'after-used',
43 | argsIgnorePattern: '^_',
44 | ignoreRestSiblings: true,
45 | vars: 'all',
46 | varsIgnorePattern: '^_',
47 | },
48 | ],
49 | 'max-statements-per-line': ['error', { max: 2 }],
50 | 'brace-style': ['error', '1tbs', { allowSingleLine: true }],
51 | 'arrow-parens': ['error', 'always'],
52 | },
53 | },
54 |
55 | typescript: {
56 | tsconfigPath: './tsconfig.json',
57 |
58 | parserOptions: {
59 | project: ['./tsconfig.json'],
60 | },
61 |
62 | overrides: {
63 | 'ts/ban-ts-comment': 'off',
64 | 'ts/consistent-type-definitions': ['error', 'type'],
65 | 'ts/naming-convention': ['error', {
66 | format: [
67 | 'PascalCase',
68 | ],
69 | leadingUnderscore: 'forbid',
70 | selector: 'interface',
71 | }, {
72 | format: [
73 | 'PascalCase',
74 | ],
75 | leadingUnderscore: 'forbid',
76 | selector: 'typeLike',
77 | }, {
78 | format: [
79 | 'PascalCase',
80 | 'camelCase',
81 | 'UPPER_CASE',
82 | 'snake_case',
83 | ],
84 | leadingUnderscore: 'allow',
85 | selector: 'variable',
86 | trailingUnderscore: 'allow',
87 | }],
88 | 'ts/no-explicit-any': 'warn',
89 | 'ts/no-use-before-define': 'off',
90 | 'ts/prefer-as-const': 'error',
91 | 'ts/prefer-destructuring': 'error',
92 | 'ts/prefer-for-of': 'error',
93 | 'ts/prefer-nullish-coalescing': 'error',
94 | 'ts/prefer-ts-expect-error': 'off',
95 | },
96 | },
97 |
98 | vue: {
99 | overrides: {
100 | 'vue/html-self-closing': 'error',
101 | 'vue/max-attributes-per-line': ['error', {
102 | multiline: { max: 1 },
103 | singleline: { max: 20 },
104 | }],
105 | 'vue/no-duplicate-attr-inheritance': 'error',
106 | 'vue/no-ref-object-reactivity-loss': 'error',
107 | 'vue/no-restricted-custom-event': ['warn', {
108 | event: 'input',
109 | message: 'If you intend a prop for v-model, it should be \'update:modelValue\' in Vue 3.',
110 | suggest: 'update:modelValue',
111 | }, {
112 | event: '/ed$/',
113 | message: 'Event should be in imperative mood, e.g. \'edit\' instead of \'edited\'.',
114 | }],
115 | 'vue/no-restricted-html-elements': [
116 | 'error',
117 | {
118 | element: 'a',
119 | message: 'Use over ',
120 | },
121 | ],
122 | 'vue/object-curly-newline': ['error', { consistent: true, multiline: true }],
123 | },
124 | },
125 |
126 | stylistic: {
127 | overrides: {
128 | // Auto-fixes
129 | 'style/arrow-parens': ['error', 'always'], // auto fix
130 | 'style/brace-style': ['error', '1tbs', { allowSingleLine: true }],
131 | 'style/max-statements-per-line': ['error', { max: 2 }],
132 | },
133 | },
134 |
135 | rules: {
136 | 'antfu/top-level-function': 'off',
137 | 'curly': ['error', 'all'],
138 |
139 | 'unicorn/catch-error-name': ['error', { name: 'err' }],
140 | 'unicorn/filename-case': [
141 | 'error',
142 | {
143 | case: 'kebabCase',
144 | ignore: [
145 | '.vue$',
146 | '.md$',
147 | ],
148 | },
149 | ],
150 | },
151 | })
152 |
--------------------------------------------------------------------------------
/public/gradients/hero-gradient-tablet.svg:
--------------------------------------------------------------------------------
1 |
85 |
--------------------------------------------------------------------------------
/public/gradients/hero-gradient.svg:
--------------------------------------------------------------------------------
1 |
85 |
--------------------------------------------------------------------------------
/components/global/Pinia.vue:
--------------------------------------------------------------------------------
1 |
2 |
106 |
107 |
--------------------------------------------------------------------------------