---
contentId: 17995d3c-aadc-4dc8-a2f0-278bc35157f0
title: "The Perfect Guide to Setting Up a New Nuxt Project"
description: "A comprehensive guide to efficiently setting up a Nuxt project, ensuring a clean, powerful, and future-proof project."
date: 2024-12-21
---

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:

```bash
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](#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:

```bash
npx taze -w
```

The **taze** package, developed by [Anthony Fu](https://antfu.me), 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`:

```ts
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:

```bash
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.

<CalloutReadMore text="Upgrading to Nuxt 4" href="https://nuxt.com/docs/getting-started/upgrade#opting-in-to-nuxt-4" />

## Linting and formatting

Nuxt provides an excellent developer experience for linting and formatting. Install both the linter and the formatter with the following command:

```bash
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](https://eslint.nuxt.com) projects. Enable formatting, and it will automatically fix issues upon saving a file. I always configure it in my `nuxt.config.ts`:

```ts
export default defineNuxtConfig({
  eslint: {
    config: {
      stylistic: true // [!code highlight]
    }
  }
})
```

Additionally, create a `.vscode/settings.json` file to disable the prettier extension, preventing conflicts with the ESLint formatter:

```json
{
  "prettier.enable": false
}
```

Add two scripts to your `package.json` file:

```json
{
  "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](https://ui.nuxt.com) and Nuxt UI Pro component libraries. They are well-designed and easy to use. Reading the [Nuxt UI source code](https://github.com/nuxt/ui) is insightful, and I also have an article on building a component library with Vue.

<CalloutReadMore id="55d2cdcf-ba27-4bfe-9bc1-492e866ff3b1" />

> [!NOTE]
> 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:

```bash
pnpm add @nuxt/ui@next tailwindcss@next
```

Add the module to your `nuxt.config.ts` file:

```ts
export default defineNuxtConfig({
  modules: ['@nuxt/ui']
})
```

Import necessary CSS in your `app/assets/css/main.css` file:

```css
@import "tailwindcss";
@import "@nuxt/ui";
```

Ensure this CSS file is included in the `nuxt.config.ts` file:

```ts
export default defineNuxtConfig({
  css: ['~/assets/css/main.css']
})
```

Update your `.vscode/settings.json` file to enhance experience with the [Tailwind CSS IntelliSense extension](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss):

```json
{
  "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:

```vue
<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](https://tailwindcss.com). 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:

```bash
pnpm add tailwindcss@next @tailwindcss/vite@next
```

Create an `app/assets/css/main.css` file and import Tailwind CSS:

```css
@import "tailwindcss";
```

Update your `nuxt.config.ts` file to utilize the Vite plugin:

```ts
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](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss):

```json
{
  "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](https://nuxt.com/blog/nuxt-icon-v1-0) 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:

1. Use the [Nuxt Icons](https://github.com/nuxt/icon) module provides access to over 200,000 icons from various icon sets:

```bash
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.

2. Use the Tailwind CSS plugin, [Tailwind CSS Icons](https://github.com/egoist/tailwindcss-icons), offers similar icons via a different approach:

```bash
npx @antfu/ni -D @egoist/tailwindcss-icons
```

Create a `tailwind.config.js` file and include the plugin:

```js
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:

```css
@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](https://github.com/nuxt/icon).

## Fonts

Fonts define your project's personality and influence user perception. **Nuxt** provides a solution: [Nuxt Fonts](https://fonts.nuxt.com/). This zero-config module automatically loads required fonts by scanning CSS files. Installation is straightforward:

```bash
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:

```yaml
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](https://autofix.ci/):

```yaml
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](https://docs.renovatebot.com/) in each project to automate dependency updates:

Create a `renovate.json` file with:

```json
{
  "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:

```vue
<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:

```vue
<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`:

```ts
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`:

```bash
echo ".env" >> .gitignore
```

Provide a `.env.example` file to guide other developers:

```
NUXT_API_URL=https://api.example.com
```

<CalloutReadMore text="Runtime Config: The Common Mistakes" href="https://www.youtube.com/watch?v=_FYV5WfiWvs" />

### 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**](https://github.com/unjs/ofetch). Distinguish usage as follows:

1. Use `$fetch` for client-side operations, such as form data submissions.
2. 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.
