SuperAPI AI Directory

nuxt

Frontend & websites

View repository

Updated 10-16 14:57

About this skill

Nuxt

Nuxt is an intuitive full-stack framework for Vue.js, providing automatic routing, server-side rendering, static site generation, and optimized Nitro server engine performance.

When to Use

  • Full-Stack Vue 3 Web Applications: Nuxt 3/4 with universal SSR, static generation (SSG), and auto-imports.
  • Enterprise SEO & Fast Loading Pages: Marketing sites and e-commerce stores requiring dynamic meta tags and instant rendering.
  • Edge-Ready Server Engine (Nitro): Deploying serverless functions seamlessly across Cloudflare, Vercel, Netlify, and Node.
  • Modular Frontend Architecture: Utilizing first-party modules (@nuxtjs/tailwindcss, @pinia/nuxt, @vueuse/nuxt).

Quick Start

Nuxt auto-imports components and composables.

<script setup>
// useFetch is auto-imported
const { data: quote } = await useFetch("/api/quote");
</script>

<template>
  <blockquote>{{ quote.text }}</blockquote>
</template>

Core Concepts

Universal Data Fetching with useFetch & useAsyncData

SSR-friendly data fetching with automated deduplication:

<!-- pages/products/[id].vue -->
<script setup lang="ts">
interface Product {
  id: number;
  title: string;
  price: number;
}

const route = useRoute();
const productId = route.params.id;

const {
  data: product,
  pending,
  error,
} = await useFetch<Product>(`/api/products/${productId}`, {
  key: `product-${productId}`,
  lazy: false,
});

useSeoMeta({
  title: () =>
    product.value?.title ? `${product.value.title} - Store` : "Loading...",
  description: () => `Buy ${product.value?.title} online now.`,
});
</script>

<template>
  <div class="product-page">
    <div v-if="pending">Loading product details...</div>
    <div v-else-if="error">Error loading product: {{ error.message }}</div>
    <div v-else-if="product">
      <h1>{{ product.title }}</h1>
      <p class="price">${{ product.price }}</p>
    </div>
  </div>
</template>

Nitro Server Engine API Routes

Creating backend API endpoints directly inside server/api:

// server/api/products/[id].ts
export default defineEventHandler(async (event) => {
  const id = getRouterParam(event, "id");

  if (!id || isNaN(Number(id))) {
    throw createError({
      statusCode: 400,
      statusMessage: "Invalid product ID",
    });
  }

  return {
    id: Number(id),
    title: `Premium Mechanical Keyboard #${id}`,
    price: 149.99,
  };
});

Nuxt Middleware & Route Guards

Client and server route authentication verification:

// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
  const user = useCookie("auth_token");

  if (!user.value && to.path.startsWith("/dashboard")) {
    return navigateTo("/login");
  }
});

Common Patterns

Server API Route with useFetch Data Hydration

Problem: Client-side fetch triggers content flash and hurts search engine indexing.

Solution: Use Nuxt server routes with universal useFetch:

// server/api/products.ts
export default defineEventHandler(async (event) => {
  return await db.products.findMany({ take: 20 });
});

// pages/products.vue
<script setup>
const { data: products, pending, error } = await useFetch('/api/products');
</script>

<template>
  <div v-if="pending">Loading products...</div>
  <ul v-else>
    <li v-for="p in products" :key="p.id">{{ p.name }} - ${{ p.price }}</li>
  </ul>
</template>

Best Practices

Do:

  • Use useFetch inside <script setup> for top-level component data fetching to eliminate SSR double-fetch.
  • Leverage Nuxt Server API routes (server/api/) for backend proxying and secret key protection.
  • Use useSeoMeta() for reactive, type-safe SEO management.
  • Enable Nitro route rules (routeRules) for granular caching and ISR per page.

Don't:

  • Use standard fetch() directly in setup scripts; it executes on both server and client without hydration transfer.
  • Access window or document outside onMounted or without checking import.meta.client.
  • Mutate server-side state across user requests.

Troubleshooting

Error Cause Solution
window is not defined / document is not defined Accessing browser DOM during server-side prerender step. Wrap browser code in onMounted(() => { ... }) or <ClientOnly>.
[nuxt] [request error] [unhandled] 500 Server route threw unhandled exception. Check terminal console output for server stack trace and wrap in try/catch.
Component not found on auto-import Nested folder structure requires path prefix in component name. Follow naming convention: components/base/Button.vue -> <BaseButton />.

References