Build With Abdallah logo Build With Abdallah Software · AI · Automation
Tutorial 6 min read Jun 07, 2026

Building a Full-Stack Application with Nuxt 3 and Vite

In this tutorial, we will build a fullstack application using Nuxt 3 and Vite. Nuxt 3 is a powerful framework for building serverside rendered Vue.js applications, while Vite is a

A
Abdallah Mohamed
Senior Full-Stack Engineer
Building a Full-Stack Application with Nuxt 3 and Vite

Building a Full-Stack Application with Nuxt 3 and Vite

In this tutorial, we will build a full-stack application using Nuxt 3 and Vite. Nuxt 3 is a powerful framework for building server-side rendered Vue.js applications, while Vite is a fast build tool that leverages native ES modules. Combining these two technologies allows for efficient development and optimized production builds. This tutorial will guide you through setting up a Nuxt 3 project with Vite, creating a basic application structure, and implementing a simple feature.

Prerequisites

Before we begin, ensure you have the following installed on your system:

  • Node.js (version 16 or later)
  • npm (version 7 or later)

To verify if Node.js and npm are installed, run the following commands:

node -v
npm -v

If they are not installed, you can download and install them from the official Node.js website.

Project Structure

Once we set up our Nuxt 3 project, it will have the following structure:

nuxt3-vite-app/
├── node_modules/
├── pages/
│   └── index.vue
├── public/
├── nuxt.config.ts
├── package.json
└── tsconfig.json

Step 1: Setting Up a New Nuxt 3 Project

First, we'll create a new Nuxt 3 project using the official Nuxt CLI. Open your terminal and run the following command:

npx nuxi init nuxt3-vite-app

This command initializes a new Nuxt 3 project in a directory named nuxt3-vite-app. Once the setup is complete, navigate into the project directory:

cd nuxt3-vite-app

Next, install the project dependencies:

npm install

Explanation

The npx nuxi init command is used to scaffold a new Nuxt 3 application. This sets up the necessary files and directories for a Nuxt project. After that, npm install installs all the required dependencies specified in the package.json file.

Step 2: Configuring Vite

Nuxt 3 uses Vite as its default bundler, so there's minimal configuration required. However, you can customize the Vite configuration if needed by modifying the nuxt.config.ts file.

Open nuxt.config.ts and ensure it looks like this:

import { defineNuxtConfig } from 'nuxt3'

export default defineNuxtConfig({
  build: {
    transpile: [],
  },
  vite: {
    server: {
      fs: {
        allow: ['..']
      }
    }
  }
})

Explanation

The nuxt.config.ts file is where you configure your Nuxt application. We added a basic Vite configuration to allow file system access when running the development server, which is helpful for local development.

Step 3: Creating a Basic Page

Now, let's create a basic page to display in our application. Nuxt uses the file-based routing system, so any .vue file inside the pages directory automatically becomes a route.

Create a new file called index.vue inside the pages directory with the following content:

<template>
  <div>
    <h1>Welcome to Nuxt 3 with Vite</h1>
    <p>This is a simple full-stack application.</p>
  </div>
</template>

<script setup>
// You can add your script logic here
</script>

<style scoped>
h1 {
  color: #42b883;
}
</style>

Explanation

The index.vue file is the default route of our application. It contains a simple template with a heading and a paragraph. The <script setup> block is a new feature in Vue 3 that allows you to write component logic in a more concise way. The <style scoped> ensures that the styles are scoped to this component only.

To start the development server and view your application, run:

npm run dev

Visit http://localhost:3000 in your browser to see the application in action.

In the next part of this tutorial, we will expand the application by adding more features and functionality.

Step 4: Adding a Dynamic Route

Let's add a dynamic route to demonstrate how Nuxt handles dynamic pages. We'll create a page that displays user profiles based on a user ID.

Create a new directory users inside the pages directory, and then create a file named [id].vue inside the users directory:

<template>
  <div>
    <h2>User Profile</h2>
    <p>User ID: {{ userId }}</p>
  </div>
</template>

<script setup>
import { useRoute } from 'vue-router'

const route = useRoute()
const userId = route.params.id
</script>

<style scoped>
h2 {
  color: #35495e;
}
</style>

Explanation

The [id].vue file creates a dynamic route where id is a placeholder for any value. When you navigate to /users/123, the id parameter will be 123. We use the useRoute hook to access route parameters and display the user ID.

Step 5: Fetching Data from an API

To make the application more interactive, let's fetch user data from a public API. We'll use the onMounted lifecycle hook to fetch data when the component is mounted.

Modify the [id].vue file to include API fetching:

<template>
  <div>
    <h2>User Profile</h2>
    <p v-if="user">Name: {{ user.name }}</p>
    <p>User ID: {{ userId }}</p>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'

const route = useRoute()
const userId = route.params.id
const user = ref(null)

onMounted(async () => {
  const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`)
  user.value = await response.json()
})
</script>

<style scoped>
h2 {
  color: #35495e;
}
</style>

Explanation

We use the onMounted lifecycle hook to perform an API request to jsonplaceholder.typicode.com, a free online REST API. The ref function is used to create a reactive reference for the user object, which updates when the data is fetched.

Complete Working Example

Here's the complete structure and content of the project files:

nuxt.config.ts

import { defineNuxtConfig } from 'nuxt3'

export default defineNuxtConfig({
  build: {
    transpile: [],
  },
  vite: {
    server: {
      fs: {
        allow: ['..']
      }
    }
  }
})

pages/index.vue

<template>
  <div>
    <h1>Welcome to Nuxt 3 with Vite</h1>
    <p>This is a simple full-stack application.</p>
  </div>
</template>

<script setup>
// You can add your script logic here
</script>

<style scoped>
h1 {
  color: #42b883;
}
</style>

pages/users/[id].vue

<template>
  <div>
    <h2>User Profile</h2>
    <p v-if="user">Name: {{ user.name }}</p>
    <p>User ID: {{ userId }}</p>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'

const route = useRoute()
const userId = route.params.id
const user = ref(null)

onMounted(async () => {
  const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`)
  user.value = await response.json()
})
</script>

<style scoped>
h2 {
  color: #35495e;
}
</style>

Common Errors and Fixes

  1. Error: Cannot find module 'nuxt3'

    Fix: Ensure that you have installed all dependencies by running npm install in the project directory.

  2. Error: Failed to fetch

    Fix: Check your network connection and ensure that the API endpoint is correct and accessible.

  3. Error: Cannot read property 'id' of undefined

    Fix: Verify that the route parameter is correctly defined and accessed using useRoute().params.id.

Conclusion

In this tutorial, we built a basic full-stack application using Nuxt 3 and Vite. We set up a project, created static and dynamic pages, and fetched data from an API. This setup provides a foundation for building more complex applications with server-side rendering and fast development builds.

Sources