The Perfect Guide to Setting Up a New Nuxt Project
Every time I create a new Nuxt project, I follow specific steps to ensure an optimal setup. I've been working with Nuxt since 2019 and have developed specific habits when initiating new projects.
Through my experience, I've explored numerous modules and reviewed projects from both experts and beginners. This has given me a solid understanding of what works well in the Nuxt ecosystem. Setting up a new project can be daunting, especially for newcomers, so I've decided to share this guide to help you set up your Nuxt project as efficiently as possible.
Creating a New Nuxt Project
Let's begin with creating a new Nuxt project. This is the simplest step, requiring just one command:
npx nuxi@latest init <project-name>
Tip
You can also create a v4 ready project with npx nuxi init nuxt-app -t v4-compat
, avoiding the need for Prepare for Nuxt 4.
Note
I always choose pnpm as my package manager. You can select the one you prefer, but I recommend trying pnpm.
Running this command will scaffold a new Nuxt project within the <project-name>
directory. The app is minimalistic—no configuration, no modules, just Nuxt and an app.vue
file.
Update the Dependencies
Before proceeding, it's essential to update dependencies to their latest versions. This ensures you can leverage the newest features and bug fixes while avoiding issues that outdated dependencies might cause. Execute the following command to update them:
npx taze -w
The taze package, developed by Anthony Fu, updates all dependencies to their latest versions. It's similar to npm-check-updates
but more powerful due to its adherence to semver versioning, offering both speed and reliability.
Prepare for Nuxt 4
Currently, the latest stable version of Nuxt is version 3. However, version 4 is in development and promises numerous features and enhancements. Although not officially released, you can prepare your projects for this future update by adding the following configuration in your nuxt.config.js
:
export default defineNuxtConfig({
future: {
compatibilityVersion: 4,
}
})
This setup enables you to start developing your projects as though you're already using Nuxt 4. This foresight not only allows you to benefit from upcoming features but also minimizes the work required to upgrade when Nuxt 4 is released.
To make the most of Nuxt 4, create a new app
folder and move the app.vue
file into it:
mkdir app && mv app.vue app
Tip
You can also create a v4 ready project by using the npx nuxi init nuxt-app -t v4-compat
command.
Linting and Formatting
Nuxt provides an excellent developer experience for linting and formatting. Install both the linter and the formatter with the following command:
npx nuxi module add eslint && npx @antfu/ni -D typescript
This command installs the @nuxt/eslint
module, which offers a 0-config ESLint setup for Nuxt projects. Enable formatting, and it will automatically fix issues upon saving a file. I always configure it in my nuxt.config.ts
:
export default defineNuxtConfig({
eslint: {
config: {
stylistic: true
}
}
})
Additionally, create a .vscode/settings.json
file to disable the prettier extension, preventing conflicts with the ESLint formatter:
{
"prettier.enable": false
}
Add two scripts to your package.json
file:
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint --fix ."
}
}
Now, you can run pnpm run lint
to check for issues and pnpm run lint:fix
to automatically fix them.
These predefined configurations make it straightforward to set up ESLint with TypeScript and Vue support, ensuring consistent and clean code.
UI and Components
With a clean project setup, the latest dependencies, preparation for Nuxt 4, and robust linting and formatting, it's time to focus on UI and components. This step varies based on project objectives and design requirements.
Nuxt UI and Nuxt UI Pro
If the project emphasizes business logic over UI, I use the Nuxt UI and Nuxt UI Pro component libraries. They are well-designed and easy to use. Reading the Nuxt UI source code is insightful, and I also have an article on building a component library with Vue.
The Complete Guide to Building a Vue.js Component LibraryNote
As of writing, Nuxt UI 3 is not officially released, but it can be used in projects. If you're reading this later, let me know in the comments, and I'll update this guide.
First, install Nuxt UI and Tailwind CSS:
pnpm add @nuxt/ui@next tailwindcss@next
Add the module to your nuxt.config.ts
file:
export default defineNuxtConfig({
modules: ['@nuxt/ui']
})
Import necessary CSS in your app/assets/css/main.css
file:
@import "tailwindcss";
@import "@nuxt/ui";
Ensure this CSS file is included in the nuxt.config.ts
file:
export default defineNuxtConfig({
css: ['~/assets/css/main.css']
})
Update your .vscode/settings.json
file to enhance experience with the Tailwind CSS IntelliSense extension:
{
"files.associations": {
"*.css": "tailwindcss"
},
"editor.quickSuggestions": {
"strings": "on"
}
}
Lastly, modify your app/app.vue
file to include the Nuxt UI component <UApp>
, automatically injecting global components:
<template>
<UApp>
<NuxtPage />
</UApp>
</template>
Note
Nuxt UI Pro is a paid extension offering layout components for rapid app development. It's a worthwhile investment that saves time and effort, while supporting the Nuxt team and open-source development. 💚
Tailwind CSS
For projects requiring specific designs or when collaborating with designers, I turn to Tailwind CSS. It's a utility-first CSS framework that streamlines the design process to such an extent that working without it is unimaginable. The upcoming version, Tailwind CSS 4, includes an indispensable Vite plugin, eliminating the need for additional modules and simplifying the setup.
Install the latest Tailwind CSS version:
pnpm add tailwindcss@next @tailwindcss/vite
Create an app/assets/css/main.css
file and import Tailwind CSS:
@import "tailwindcss";
Update your nuxt.config.ts
file to utilize the Vite plugin:
import Tailwind from '@tailwindcss/vite'
export default defineNuxtConfig({
css: ['~/assets/css/main.css'],
vite: {
plugins: [
Tailwind()
]
}
})
Enhance your developer experience by updating your .vscode/settings.json
file for the Tailwind CSS IntelliSense extension:
{
"files.associations": {
"*.css": "tailwindcss"
},
"editor.quickSuggestions": {
"strings": "on"
}
}
The setup is incredibly straightforward!
Icons
Incorporating icons into your project is essential, albeit deceptively complex. Anthony Fu's article elaborates on finding the perfect icon solution.
If utilizing Nuxt UI, icons are already included. You can safely skip this section.
For Tailwind CSS users, two options are available:
- Use the Nuxt Icons module provides access to over 200,000 icons from various icon sets:
npx nuxi module add icon
This is the simplest solution and with the latest improvements from the v1 release, it's a powerful choice. I recommend starting with this option.
- Use the Tailwind CSS plugin, Tailwind CSS Icons, offers similar icons via a different approach:
npx @antfu/ni -D @egoist/tailwindcss-icons
Create a tailwind.config.js
file and include the plugin:
import { getIconCollections, iconsPlugin } from '@egoist/tailwindcss-icons'
/** @type {import('tailwindcss').Config} */
module.exports = {
plugins: [
iconsPlugin({
collections: getIconCollections([/** ... */]),
}),
],
}
Import the configuration in your app/assets/css/main.css
file:
@import "tailwindcss";
@config "../../../tailwind.config.js";
I personally prefer the second solution due to its uniform setup across projects, including non-Nuxt ones, and at the time I made this choice, the Nuxt Icons module was suffering from many drawbacks. However, that's not the case anymore and I highly recommend you to start with Nuxt Icons.
Fonts
Fonts define your project's personality and influence user perception. Nuxt provides a solution: Nuxt Fonts. This zero-config module automatically loads required fonts by scanning CSS files. Installation is straightforward:
npx nuxi module add fonts
This module is part of my projects unless I'm using Nuxt UI, where it's included. But I have to say that I rarely need to install it since Nuxt UI suffices for most scenarios.
CI
For personal projects, I use GitHub and always set up a CI to enforce linting and autofix errors. This approach ensures clean, consistent code. While linters and formatters are great, they're useless if unused.
I utilize GitHub Actions, detailed in a .github/workflows/ci.yml
file:
name: CI
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4
with:
node-version: 22
cache: pnpm
- name: Install dependencies
run: pnpm install
- name: Lint files
run: pnpm run lint
To automate code formatting and commits, I use autofix.ci:
name: autofix.ci # needed to securely identify the workflow
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
autofix:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- run: corepack enable
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4
with:
node-version: 20.5
cache: pnpm
- name: Install dependencies
run: pnpm install
- name: Lint & Fix
run: pnpm run lint:fix
- uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c
Keep Dependencies Up-to-date
Maintaining up-to-date dependencies is crucial. With numerous projects, this can be time-consuming. I use Renovate in each project to automate dependency updates:
Create a renovate.json
file with:
{
"extends": [
"github>nuxt/renovate-config-nuxt"
]
}
This tool is indispensable, and I find it challenging to work on projects lacking Renovate (like some work projects).
Tips, Tricks, and Additional Considerations
Here are some extra tips and tricks I find valuable, even if not directly related to the setup:
Always Place Scripts First
Organize vue
files by placing the script
section first. This offers clarity by presenting component logic before the template:
<script lang="ts">
// ...
</script>
<template>
// ...
</template>
Embrace TypeScript
I advocate using TypeScript across all vue
files and utility or composable scripts. Adding lang="ts"
even without TypeScript code enhances the developer experience:
<script lang="ts" setup>
// ...
</script>
Note
Always opt for the setup
syntax in components.
Avoid Using process.env
in nuxt.config.ts
Refrain from directly accessing process.env
in nuxt.config.ts
. For instance, assigning defaults for runtimeConfig
shouldn't use process.env
:
export default defineNuxtConfig({
runtimeConfig: {
apiUrl: ''
}
})
Tip
Hover over the apiUrl
key in your IDE for environment variable hints. Nuxt provides complex typing, such as NUXT_API_URL
.
Create an .env
file at the project's root to define environment variables:
NUXT_API_URL=https://api.example.com
Exclude the .env
file using .gitignore
:
echo ".env" >> .gitignore
Provide a .env.example
file to guide other developers:
NUXT_API_URL=https://api.example.com
Audit Before Installing Modules
Conduct an audit before adding new modules to evaluate necessity and functionality. Sometimes, it's possible to proceed without them or to choose a superior alternative. Avoid basing decisions on stars or downloads. Instead, peruse documentation, source code, issues, and PRs for a comprehensive quality assessment. The Nuxt ecosystem evolves rapidly, and some modules may become outdated or incompatible with newer Nuxt versions.
Choosing Between useFetch
and $fetch
Avoid using fetch
directly; opt for $fetch
, an enhanced instance of ofetch. Distinguish usage as follows:
- Use
$fetch
for client-side operations, such as form data submissions. - Use
useFetch
where server-side rendering is feasible, like fetching API data to display on pages.
The Perfect Setup is Yours
This guide embodies everything I do to initialize a new Nuxt project. This comprehensive setup takes around 10 minutes, resulting in a clean, powerful, and future-ready project that allows focusing on business logic without distractions.
Warning
Avoid creating a template project from this guide. The ecosystem is dynamic, and new modules swiftly emerge. Each project might necessitate nuanced adjustments. This guide is a starting point, a checklist for initial setup. However, always adapt to the specific project needs. Maintaining a template demands effort and is generally not worthwhile.
I hope this guide enhances your Nuxt project setup. If you have questions or want to share your configuration, please leave a comment below.
Thanks for reading! My name is Estéban, and I love to write about web development.
I've been coding for several years now, and I'm still learning new things every day. I enjoy sharing my knowledge with others, as I would have appreciated having access to such clear and complete resources when I first started learning programming.
If you have any questions or want to chat, feel free to comment below or reach out to me on Bluesky, X, and LinkedIn.
I hope you enjoyed this article and learned something new. Please consider sharing it with your friends or on social media, and feel free to leave a comment or a reaction below—it would mean a lot to me! If you'd like to support my work, you can sponsor me on GitHub!