We use cookies to enhance your experience on the site
CodeWorlds

Nuxt 3 — Basics

Nuxt 3 is a meta-framework built on Vue 3 that provides SSR, SSG, file-based routing, and much more — out of the box, with no configuration. Think of it as the autopilot system of the NOVA LAB station — everything is configured and ready to go.

Creating a Nuxt 3 Project

1npx nuxi@latest init nova-lab-app
2cd nova-lab-app
3npm install
4npm run dev

File-Based Routing

In Nuxt 3, you don't configure the router manually. The file structure in the

pages/
folder automatically creates routes:

1pages/
2├── index.vue          →  /
3├── about.vue          →  /about
4├── crew/
5│   ├── index.vue      →  /crew
6│   └── [id].vue       →  /crew/123
7└── modules/
8    └── [...slug].vue  →  /modules/any/nested/path

The

index.vue
file is the main page of a given directory. Files with square brackets
[id].vue
are dynamic parameters.

Layouts

Layouts define the shared structure of pages (navigation, footer):

1<!-- layouts/default.vue -->
2<template>
3  <div class="station">
4    <nav class="nav">
5      <NuxtLink to="/">Home</NuxtLink>
6      <NuxtLink to="/about">About</NuxtLink>
7      <NuxtLink to="/crew">Crew</NuxtLink>
8    </nav>
9
10    <main>
11      <slot />
12    </main>
13
14    <footer>NOVA LAB &copy; 2087</footer>
15  </div>
16</template>

Pages automatically use the

default
layout. You can change the layout on a specific page:

1<!-- pages/dashboard.vue -->
2<script setup lang="ts">
3definePageMeta({
4  layout: 'admin'
5})
6</script>

useFetch — Data Fetching

useFetch
is a Nuxt composable for fetching data. It works both on the server (SSR) and on the client:

1<script setup lang="ts">
2interface CrewMember {
3  id: number
4  name: string
5  role: string
6}
7
8// useFetch works on server and client
9const { data: crew, pending, error } = await useFetch<CrewMember[]>(
10  '/api/crew'
11)
12</script>
13
14<template>
15  <div v-if="pending">Loading...</div>
16  <div v-else-if="error">Error: {{ error.message }}</div>
17  <ul v-else>
18    <li v-for="member in crew" :key="member.id">
19      {{ member.name }} — {{ member.role }}
20    </li>
21  </ul>
22</template>

useFetch
automatically:

  • Executes the request on the server during SSR
  • Serializes the data and sends it to the client (avoids double fetching)
  • Provides
    pending
    ,
    error
    ,
    data
    ,
    refresh
    states

useAsyncData — More Flexible

useAsyncData
gives full control over the data fetching logic:

1<script setup lang="ts">
2const { data: stats } = await useAsyncData('station-stats', () => {
3  return $fetch('/api/stats')
4})
5
6// With data transformation
7const { data: modules } = await useAsyncData(
8  'modules',
9  () => $fetch('/api/modules'),
10  {
11    transform: (data) => data.filter(m => m.active),
12    watch: [selectedSector]  // automatic refresh
13  }
14)
15</script>

Auto-imports

Nuxt 3 automatically imports:

  • Vue composables (
    ref
    ,
    computed
    ,
    watch
    ...)
  • Nuxt composables (
    useFetch
    ,
    useRoute
    ,
    useState
    ...)
  • Components from
    components/
  • Utilities from
    utils/
    and
    composables/

No need to write

import { ref } from 'vue'
— Nuxt does it for us!

1<script setup lang="ts">
2// No imports! Nuxt auto-imports ref, computed, useFetch
3const count = ref(0)
4const doubled = computed(() => count.value * 2)
5
6const { data } = await useFetch('/api/data')
7</script>

Nuxt 3 Project Structure

1nova-lab-app/
2├── pages/          # File-based routing
3├── components/     # Auto-imported components
4├── composables/    # Auto-imported composables
5├── layouts/        # Page layouts
6├── server/         # API endpoints (Nitro)
7│   └── api/        # /api/* routes
8├── public/         # Static files
9├── app.vue         # Root component
10└── nuxt.config.ts  # Nuxt configuration

Server API (Nitro)

Nuxt 3 uses Nitro to handle API endpoints:

1// server/api/crew.ts
2export default defineEventHandler((event) => {
3  return [
4    { id: 1, name: 'Dr. Nova', role: 'Commander' },
5    { id: 2, name: 'Atlas', role: 'Navigator' },
6    { id: 3, name: 'Echo', role: 'Engineer' }
7  ]
8})
Go to CodeWorlds