Skip to content

Dynamic route missing useAsyncData or useFetch

A dynamic Nuxt page (pages/blog/[slug].vue) without useAsyncData() or useFetch() fetches its data on the client only. Googlebot and AI crawlers receive the page template with no content — no title, no body text, nothing to index.

Use useAsyncData() or useFetch() inside <script setup>. Both composables run on the server during SSR, so the data is present in the initial HTML response.

pages/blog/[slug].vue
<script setup lang="ts">
const route = useRoute()
const { data: post } = await useAsyncData(
`post-${route.params.slug}`,
() => $fetch(`/api/posts/${route.params.slug}`)
)
</script>
<template>
<article>
<h1>{{ post?.title }}</h1>
<p>{{ post?.excerpt }}</p>
</article>
</template>

useFetch is a shorthand that combines useAsyncData with $fetch. Use it when you do not need to customise the cache key.

<script setup lang="ts">
const route = useRoute()
const { data: post } = await useFetch(`/api/posts/${route.params.slug}`)
</script>
Terminal window
curl https://yourdomain.com/blog/your-post-slug | grep '<h1'

Confirm the response body contains the actual post title. Then re-run orino audit.