Receber por email
← Voltar para o catálogo

web-meta-framework-nuxt

Nuxt patterns - file-based routing, data fetching (useFetch/useAsyncData), useState, server routes, middleware, auto-imports, layouts, SEO

11estrelas
Atualizado há 7 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add agents-inc/skills

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/web-meta-framework-nuxt/svg)](https://www.skillteca.com.br/skills/web-meta-framework-nuxt)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Nuxt Framework Patterns

Quick Guide: Use useFetch for API calls in components (SSR-safe), useAsyncData for custom data sources or parallel fetches. Create server routes in server/api/. Auto-imports handle composables and components automatically. Use useState for SSR-friendly shared state. Data is a shallowRef by default -- use deep: true if you need deep reactivity.

<critical_requirements>

CRITICAL: Before Using This Skill

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST use useFetch or useAsyncData for data fetching in components -- NEVER raw $fetch in setup which causes double-fetching)

(You MUST use server/api/ for API routes -- handlers export default with defineEventHandler())

(You MUST use definePageMeta to attach middleware and configure page behavior -- it is a macro, values must be statically analyzable)

(You MUST use useHead or useSeoMeta for SEO metadata -- never manual <head> tags)

(You MUST ensure useState values are JSON-serializable for SSR hydration -- no functions, classes, or Symbols)

</critical_requirements>

Auto-detection: Nuxt, nuxt.config.ts, useFetch, useAsyncData, useState, defineEventHandler, definePageMeta, defineNuxtRouteMiddleware, NuxtLayout, NuxtPage, NuxtLink, navigateTo, server/api, pages/, layouts/, middleware/, composables/, useHead, useSeoMeta, app/ directory

When to use:

  • Building Vue 3 applications with file-based routing and SSR/SSG
  • Creating full-stack applications with server routes in the same project
  • Implementing data fetching that works seamlessly across server and client
  • Building SEO-optimized pages with automatic metadata handling
  • Leveraging auto-imports for composables and components

Key patterns covered:

  • File-based routing (pages/, dynamic routes, catch-all routes)
  • Data fetching (useFetch, useAsyncData, $fetch)
  • Server routes (server/api/, defineEventHandler)
  • Shared state (useState composable)
  • Route middleware (defineNuxtRouteMiddleware, navigateTo)
  • Layouts (layouts/, NuxtLayout, setPageLayout)
  • SEO (useHead, useSeoMeta)
  • Plugins (plugins/, defineNuxtPlugin)
  • Error handling (NuxtErrorBoundary, createError, showError)
  • Auto-imports (composables, components, utils)

When NOT to use:

  • Simple SPAs without SSR needs (consider Vue + Vite directly)
  • Static documentation sites without server logic (consider a static-site generator)

<philosophy>

Philosophy

Nuxt is a meta-framework for Vue 3 that provides file-based routing, automatic code splitting, server-side rendering, and a powerful data-fetching system. Built on Nitro server engine, it enables full-stack development with API routes colocated with your frontend.

Core Principles:

  1. Universal rendering by default -- Pages render on server first, then hydrate on client
  2. Auto-imports everywhere -- Composables, components, and utilities are automatically available
  3. File-based conventions -- Directories define behavior (pages/, server/, layouts/, middleware/)
  4. SSR-safe data fetching -- Composables prevent double-fetching between server and client
  5. Zero-config TypeScript -- Full type safety with automatic type generation
  6. Shallow reactivity for performance -- data from useFetch/useAsyncData is a shallowRef by default

</philosophy>

<patterns>

Core Patterns

Pattern 1: File-Based Routing

File names in pages/ become URL paths. Dynamic segments use bracket syntax.

| File | URL | Description | | --------------------------- | ------------------------ | ------------------ | | pages/index.vue | / | Home page | | pages/about.vue | /about | Static route | | pages/blog/[slug].vue | /blog/:slug | Dynamic parameter | | pages/users/[...slug].vue | /users/* | Catch-all route | | pages/posts/[[id]].vue | /posts or /posts/:id | Optional parameter |

<!-- pages/blog/[slug].vue -->
<script setup lang="ts">
const route = useRoute();
const slug = route.params.slug as string;
const { data: post, error } = await useFetch(`/api/posts/${slug}`);

if (error.value) {
  throw createError({ statusCode: 404, statusMessage: "Post not found" });
}
</script>

Why good: File names map to URLs, bracket syntax for dynamic params, createError triggers error page

See [examples/core.md](examples/core.md) for complete page examples with layouts and middleware.

Pattern 2: Data Fetching (useFetch / useAsyncData)

useFetch wraps useAsyncData + $fetch. It prevents double-fetching by transferring server data to client during hydration. Data is a shallowRef -- replace the whole object to trigger reactivity, or use deep: true.

// Simple fetch -- URL is cache key
const { data, error, status, refresh, clear } = await useFetch("/api/users");

// With reactive query params and auto-refetch
const page = ref(1);
const { data: users } = await useFetch("/api/users", {
  query: { page, limit: 20 },
  watch: [page],
});

// POST with immediate: false for user-triggered actions
const { execute, status } = useFetch("/api/users", {
  method: "POST",
  body: form,
  immediate: false,
  watch: false,
});

Use useAsyncData when combining multiple fetches or using non-HTTP sources:

const { data } = await useAsyncData("dashboard", async () => {
  const [users, stats] = await Promise.all([
    $fetch("/api/users"),
    $fetch("/api/stats"),
  ]);
  return { users, stats };
});

Critical: $fetch in <script setup> (outside useFetch/useAsyncData) runs on both server and client, causing double-fetching. Always wrap in a composable.

See [examples/data-fetching.md](examples/data-fetching.md) for typed responses, transforms, lazy loading, and server-only fetch patterns.

Pattern 3: Server Routes

Server routes live in server/api/ (prefixed with /api) or server/routes/ (no prefix). File suffix restricts HTTP method.

// server/api/users.get.ts
export default defineEventHandler(async (event) => {
  const query = getQuery(event);
  const page = Number(query.page) || 1;
  return db.users.findMany({ skip: (page - 1) * 20, take: 20 });
});

// server/api/users.post.ts
export default defineEventHandler(async (event) => {
  const body = await readBody(event);
  // Validate body with Zod or similar
  setResponseStatus(event, 201);
  return db.users.create({ data: body });
});

| Pattern | File | URL | | --------- | -------------------------- | ----------------- | | GET | server/api/users.get.ts | GET /api/users | | POST | server/api/users.post.ts | POST /api/users | | Dynamic | server/api/users/[id].ts | /api/users/:id | | Catch-all | server/api/[...path].ts | /api/* | | No prefix | server/routes/health.ts | /health |

See [examples/server-routes.md](examples/server-routes.md) for validation, error handling, server middleware, and CRUD patterns.

Pattern 4: useState for Shared State

useState is an SSR-friendly composable for shared reactive state. Values transfer from server to client during hydration and must be JSON-serializable.

// composables/use-user.ts
export function useUser() {
  const user = useState<User | null>("user", () => null);
  const isLoggedIn = computed(() => user.value !== null);

  async function login(credentials: { email: string; password: string }) {
    user.value = await $fetch<User>("/api/auth/login", {
      method: "POST",
      body: credentials,
    });
  }

  return { user: readonly(user), isLoggedIn, login };
}

Key constraints: Values must be JSON-serializable (no functions, cla

Compartilhar X LinkedIn