Setting Up a Nuxt 3 Starter Project

Nuxt 3 Starter Project

How to set up a Nuxt 3 project, install essential modules, and follow best practices for a clean and efficient development process.

17/03/25

Go Back

Setting Up a Nuxt 3 Starter Project

Nuxt 3 is a robust framework designed for building modern web applications using Vue.js. This guide will walk you through the process of setting up a Nuxt 3 project, installing essential modules, and adhering to best practices to maintain a clean and efficient development workflow. You can view the completed project on GitHub.

Prerequisites

Before getting started, make sure you have the following installed:

Additional Tips

  • Use an even-numbered Node.js version (e.g., 18, 20, etc.)
  • Install the Nuxtr extension for enhanced development tools
  • WSL (for Windows users) - Windows Subsystem for Linux improves performance with a Linux-based environment

Creating a Nuxt 3 Project

To create a new Nuxt 3 project, open your terminal and run:

pnpm create nuxt <project-name>
cd <project-name>
pnpm dev -o

Your browser should automatically open http://localhost:3000, displaying your new Nuxt app.

Installing Essential Modules

For a fully functional Nuxt 3 setup, install the following modules using your favorite package manager (e.g., pnpm, yarn, or npm):

Add them to your nuxt.config.ts:

export default defineNuxtConfig({
    devtools: { enabled: true },
    modules: [
        '@nuxtjs/seo',
        '@nuxt/fonts',
        '@nuxt/icon',
        '@nuxt/image',
        '@nuxt/eslint',
    ],
});

Project Structure & Naming Conventions

To maintain a clean project structure, create these folders:

  • pages/
    - Holds all your application pages
  • components/
    - Reusable Vue components
  • layouts/
    - Defines page layouts (e.g. default, mobile, etc.)

Naming Conventions:

  • Use kebab-case for files and folders (e.g., public/blog-images)
  • Use CamelCase for component names (e.g., MyComponent.vue)
  • Components should have multi-word names to avoid conflicts

These are just recommendations, but following them will help keep your project organized and maintainable. If you have a different preference, feel free to adjust as needed. As long as you're consistent!

Creating Our First Page

Create an index.vue file inside the pages folder:

<template>
    <div>
        <h1>Hello World!</h1>
    </div>
</template>

Layouts in Nuxt 3

Layouts are very powerful in Nuxt for structuring your application. Let’s create a default layout. I use this a lot for headers and footer because they stay the same on multiple pages. You can also create a mobile.vue or whatever that comes to mind.

Create default.vue in the layouts folder:

<template>
    <div>
        <!-- You can add a header here -->
        <slot />
        <!-- You can add a footer here -->
    </div>
</template>

The "slot" tag is where the page content will be rendered.

Now, modify app.vue to use layouts:

<template>
    <NuxtLayout>
        <NuxtPage />
    </NuxtLayout>
</template>

Modules

Nuxt Fonts

To use fonts in our web-app, I recommend using @nuxt/fonts. It's more optimized including than including the url in the 'head' section and is very easy to configure.

Configuration

Add the following to your nuxt.config.ts:

export default defineNuxtConfig({
    modules: ['@nuxt/fonts'],
    fonts: {
        families: [
            { name: 'Space Grotesk', preload: true, display: 'swap' },
            { name: 'Poppins', preload: true, display: 'swap' },
        ],
        providers: {
            google: false, // Disable Google Fonts for GDPR compliance
        },
    },
});

Icons

@nuxt/icon is a no-brainer in each project for me. It provides a quick setup, a wide collection of icons, and is very easy to use. See the full collection at: icones.js.org. Let's add an icon to our index page.

Example Usage

<template>
    <div>
        <h1>Hello world!</h1>
        <Icon name="uil:globe" style="color: black" />
    </div>
</template>

Nuxt Image

@nuxt/img is a powerful image optimization module for Nuxt applications. It automatically optimizes your images for better performance and user experience while being incredibly simple to implement. Check out the docs for more information: image.nuxt.com.

Configuration

Add the following to your nuxt.config.ts:

export default defineNuxtConfig({
    // other configurations
    image: {
        quality: 80,
        format: ['webp', 'avif', 'jpg'],
    },
});

Example Usage

hello-world.jpg is an image in the public folder.

<template>
    <div>
        <div>
            <h1>Hello world!</h1>
            <Icon name="uil:globe" style="color: black" />
        </div>
        <NuxtImg src="/images/hello-world.png" alt="Nuxt Logo" />
    </div>
</template>

TailwindCSS

I'm a big fan of Tailwind for styling. The official documentation explains it best: Tailwind Nuxt Guide. Lets use it in our index page.

Example Usage

<template>
    <div class="flex h-screen flex-col items-center justify-center">
        <div class="flex items-center justify-center p-4 text-2xl">
            <Icon name="uil:globe" style="color: black" />
            <h1 class="text-blue-500">Hello world!</h1>
            <Icon name="uil:globe" style="color: black" />
        </div>
        <NuxtImg src="/images/hello-world.png" alt="Nuxt Logo" />
    </div>
</template>

ESLint & Prettier

ESLint and Prettier help maintain a clean and consistent codebase. Trust me, you need them!

There is already an excellent guide to set this up: Adding ESLint and Prettier to Nuxt 3. However, the article didn't mention this but you need to install @nuxtjs/eslint-config-typescript as well.

There are many prettier configurations available, but I like to use the following:

// .prettierrc
{
    "semi": true,
    "singleQuote": true,
    "useTabs": true,
    "tabWidth": 2,
    "trailingComma": "es5",
    "printWidth": 80,
    "endOfLine": "lf",
    "arrowParens": "always",
    "bracketSpacing": true,
    "embeddedLanguageFormatting": "auto",
    "plugins": [
        "prettier-plugin-organize-imports",
        "prettier-plugin-tailwindcss"
    ],
    "htmlWhitespaceSensitivity": "ignore",
    "vueIndentScriptAndStyle": true
}

SEO Configuration

You can change the SEO information on a per-page basis using the useHead function. I like to set default SEO metadata is set in app.vue, and specify the title per page.

Example setup in app.vue

<script setup>
    const description = `Hi, welcome to our nuxt starter site! This project includes all basic needs for almost every project!`;

    const ogTitle = 'Nuxt 3 - Starter project';

    const twitterDescription = `Hi, welcome to our nuxt starter site!`;

    const image = 'https://example.com/default-image.webp';

    const mySite = 'https://example.com';

    useHead({
        htmlAttrs: {
            lang: 'en',
        },
        link: [{ rel: 'canonical', href: mySite }],
        meta: [
            { name: 'description', content: description },
            {
                name: 'keywords',
                content: 'nuxt 3, starter, project',
            },
            { name: 'author', content: 'John Doe' },
            { name: 'publisher', content: 'John Doe' },
            { property: 'og:site_name', content: mySite },
            { property: 'og:type', content: 'website' },
            { property: 'og:url', content: mySite },
            { property: 'og:title', content: ogTitle },
            { property: 'og:description', content: description },
            { property: 'og:image', content: image },
            { name: 'twitter:card', content: 'summary_large_image' },
            { name: 'twitter:url', content: mySite },
            { name: 'twitter:title', content: ogTitle },
            { name: 'twitter:description', content: twitterDescription },
            { name: 'twitter:image', content: image },
        ],
    });
</script>

Example for page.vue

<script setup>
    useHead({
        title: 'Home',
        meta: [
            {
                name: 'description',
                content: 'Welcome to the index page of the Nuxt 3 starter project.',
            },
        ],
    });
</script>

Generating sitemap.xml & robots.txt with Nuxt SEO

@nuxt/seo is an essential module for any production Nuxt application. It automatically generates a sitemap and robots.txt file, making your site more discoverable by search engines.

Configuration

Add the following to your nuxt.config.ts:

export default defineNuxtConfig({
    // other configurations
    site: { url: 'https://example.com', name: 'My Awesome Website' },
});

The module works automatically once configured. You don't need to add any additional code to your pages or components. It will:

  • Generate a sitemap.xml file with all your routes
  • Create a robots.txt file with your specified rules
  • Update both files automatically when your content changes

While @nuxt/seo offers many more advanced features like structured data, canonical URL management, and social media tag optimization, the basic setup above covers the essential functionality for most projects.

That’s It!

Congratulations! You’ve set up a fully functional Nuxt 3 project with all the essential features. If you have any questions, feel free to reach out at: mail@lukasolivier.be