Nuxt docs, chapter by chapter

API — components

Every built-in Nuxt component from the API reference with its props, slots and rules — ClientOnly, DevOnly, NuxtClientFallback, NuxtPage, NuxtLayout, NuxtLink, NuxtLoadingIndicator, NuxtErrorBoundary, NuxtIsland, NuxtRouteAnnouncer, NuxtAnnouncer, NuxtTime, NuxtImg, NuxtPicture, NuxtWelcome and Teleport.

Sixteen components ship with Nuxt (two of them from @nuxt/image). Their props are small, their rules are precise, and "what does pageKey do" or "what is NuxtClientFallback" are quick interview probes.

Know

  • <ClientOnly> — renders its slot only after hydration. Props placeholderTag/fallbackTag (tag rendered on the server) and placeholder/fallback (text); slot #fallback for server-side content until mounted.
  • <DevOnly> — renders its slot only in development; excluded from production builds; #fallback slot for a production replacement.
  • <NuxtClientFallback> — experimental (experimental.clientFallback): if any child throws during SSR, the content is rendered on the client instead. Props placeholderTag/fallbackTag (default div), placeholder/fallback (rendered as raw HTML, so never user input), keepFallback (default false); event @ssr-error (server only); #fallback slot.
  • <NuxtPage> — required to render pages; a wrapper around <RouterView> that also handles transitions and keep-alive. Props name, route, pageKey (string or function controlling re-rendering; also settable via definePageMeta({ key })), transition, keepalive. With Suspense inside, the new page component may mount before the old one unmounts, unlike a plain Vue app. Do not use $route in pageKey; use the route slot variable.
  • <NuxtLayout> — renders the layout named by name (string | false, default default; reactive allowed; names are kebab-cased) with a fallback layout for invalid names; extra props are passed through to the layout as $attrs/useAttrs().
  • <NuxtLink> — drop-in for <RouterLink> and <a>: decides internal vs external by itself; external forces an <a> (needed for static files in public/ such as PDFs); to accepts strings and route objects (query handling inherited from Vue Router); target, rel (defaults for external links), noRel; prefetching of the target page's chunk and payload when the link enters the viewport, tunable with prefetch, noPrefetch, prefetchOn (visibility | interaction), prefetchedClass; activeClass/exactActiveClass; trailingSlash; replace, ariaCurrentValue; custom for headless usage with a slot. defineNuxtLink() creates a pre-configured variant.
  • <NuxtLoadingIndicator> — a progress bar between navigations hooked to page:loading:start/page:loading:end. Props color, errorColor, height (default 3), duration (2000), throttle (200), estimatedProgress; default slot for custom content; useLoadingIndicator() exposes the same state.
  • <NuxtErrorBoundary> — catches client-side errors from its default slot; #error="{ error, clearError }" slot; @error event.
  • <NuxtIsland> — renders a server component without client JavaScript; props name (required), lazy (non-blocking), props, source (a remote island server; requires experimental.componentIslands: 'local+remote'), dangerouslyLoadClientComponents. Props and context travel as GET query parameters (cacheable, but visible in logs). Changing props refetches the island.
  • <NuxtRouteAnnouncer> (3.12+) — a visually hidden element announcing the page title on route change for assistive technologies; props atomic, politeness (off | polite | assertive); default slot; backed by useRouteAnnouncer().
  • <NuxtAnnouncer> (4.4.2+) — the in-page counterpart for dynamic updates (form validation, toasts, async results) driven by useAnnouncer(); place both announcers in app.vue.
  • <NuxtTime> (3.17+) — renders a <time> element with locale-aware formatting that stays consistent between server and client (no hydration mismatch for dates). Props: datetime (Date | number | string, required), locale, and the Intl.DateTimeFormat options (dateStyle, timeStyle, timeZone, …), plus relative formatting options.
  • <NuxtImg> / <NuxtPicture> — from @nuxt/image (npx nuxt module add image): NuxtImg outputs a plain <img> with provider-optimised URLs, resizing from width/height, responsive srcset from sizes, formats, lazy loading; NuxtPicture outputs <picture> with modern-format sources and fallbacks.
  • <NuxtWelcome> — the starter's welcome screen; remove it.
  • <Teleport> — Vue's Teleport; in Nuxt, teleporting to body is supported in SSR, while other targets need <ClientOnly> because the target does not exist during server rendering.

How it works

app/app.vue
<template>
  <NuxtLoadingIndicator color="var(--ui-primary)" :height="2" />
  <NuxtRouteAnnouncer />
  <NuxtAnnouncer />
  <NuxtLayout>
    <NuxtPage :page-key="route => route.fullPath" :transition="{ name: 'page', mode: 'out-in' }" />
  </NuxtLayout>
</template>
app/components/Docs/ComponentTour.vue
<script setup lang="ts">
const { polite } = useAnnouncer()
</script>

<template>
  <!-- Static file in public/: external forces a real <a> -->
  <NuxtLink to="/reports/2026.pdf" external target="_blank">Download report</NuxtLink>
  <!-- Prefetch on hover instead of on sight -->
  <NuxtLink to="/pricing" prefetch-on="interaction" active-class="font-bold">Pricing</NuxtLink>

  <!-- Dates without hydration mismatches -->
  <NuxtTime :datetime="post.publishedAt" date-style="medium" time-style="short" locale="en-GB" />

  <!-- Heavy static markup, zero client JS; interactive child opted in -->
  <NuxtIsland name="HighlightedMarkdown" :props="{ source: post.body }" lazy />

  <!-- Browser-only widget with a server placeholder -->
  <ClientOnly fallback-tag="div" fallback="Loading map…">
    <MapView />
  </ClientOnly>

  <!-- Optional subtree that must not take the page down -->
  <NuxtErrorBoundary @error="polite('Comments failed to load')">
    <Comments :post-id="post.id" />
    <template #error="{ clearError }">
      <button type="button" @click="clearError()">Retry comments</button>
    </template>
  </NuxtErrorBoundary>

  <DevOnly><DebugPanel /></DevOnly>
</template>
Gotcha· NuxtLink to a file in public/

<NuxtLink to="/report.pdf"> is treated as an internal route and client-side navigation fails with a 404 from the router. The docs' answer is the external prop, which renders a plain <a>.

Verify before the interview:

The full NuxtLink prop list (prefetchOn, prefetchedClass, trailingSlash, noRel) and the defineNuxtLink options; also whether NuxtClientFallback is still experimental.

docs ↗

Exercise

Exercise
  • Render a date with {{ new Date().toLocaleString() }} and with <NuxtTime>; compare the hydration warnings.
  • Put a <NuxtLink> to a PDF in public/ with and without external; click both.
  • Enable experimental.clientFallback, throw inside a child during SSR, and watch NuxtClientFallback recover on the client.

Be able to say

Be able to say· Which Nuxt components do you put in app.vue and why?

"NuxtLayout wrapping NuxtPage, because the page component is what turns the pages/ directory into routes and the layout wrapper picks the layout per page. NuxtLoadingIndicator for feedback during client-side navigation, NuxtRouteAnnouncer so screen readers hear the new page title on navigation, and since 4.4 NuxtAnnouncer so in-page updates can be announced through useAnnouncer. Everything else is per use: ClientOnly for browser-only widgets, NuxtIsland or .server.vue for heavy static markup, NuxtErrorBoundary around optional subtrees, NuxtTime for dates that must match between server and client."

Your notes

Open in Notes

Nothing yet. Notes filed here show up on this page and the section overview.