Displaying content in a Nuxt.js front end
You’ve configured your Studio with a post document type and learned how to query from your hosted dataset. Before deploying the Studio, let’s query and display this content on the front-end framework of your choice.

1Install a new Nuxt application
If you have an existing application, skip this first step and adapt the rest of the lesson to install Sanity dependencies to fetch and render content.
Run the following in a new tab or window in your Terminal (keep the Studio running) to create a new Nuxt application using the Nuxt UI template for Tailwind CSS.
You should now have your Studio and Nuxt application in two separate, adjacent folders:
# outside your studio directory npx nuxi@latest init -t ui nuxt-hello-world cd nuxt-hello-world
# outside your studio directory pnpm dlx nuxi@latest init -t ui nuxt-hello-world cd nuxt-hello-world
# outside your studio directory yarn dlx nuxi@latest init -t ui nuxt-hello-world cd nuxt-hello-world
# outside your studio directory bunx nuxi@latest init -t ui nuxt-hello-world cd nuxt-hello-world
├─ /nuxt-hello-world └─ /studio-hello-world
2Install Sanity dependencies
Run the following inside the nuxt-hello-world directory to:
- Install and configure the Nuxt Sanity integration
- Install
@sanity/image-urlfor generating images from Sanity content
npx nuxi@latest module add sanity npm install @sanity/image-url
pnpm dlx nuxi@latest module add sanity pnpm add @sanity/image-url
yarn dlx nuxi@latest module add sanity yarn add @sanity/image-url
bunx nuxi@latest module add sanity bun add @sanity/image-url
3Configure the Sanity client
Update the integration configuration to configure a Sanity Client to fetch content.
export default defineNuxtConfig({
compatibilityDate: "2024-04-03",
devtools: { enabled: true },
modules: ["@nuxt/ui", "@nuxtjs/sanity"],
// 👇 Add these lines
sanity: {
projectId: PROJECT_ID,
dataset: PROJECT_DATASET",
apiVersion: "2025-10-01",
},
});4Start the development server
Run the following command and open http://localhost:3000 in your browser.
npm run devpnpm run devyarn run devbun run dev5Update root layout
Remove the default entry point app.vue to use the pages directory strategy for routing.
rm app.vue6Display content on the home page
Nuxt performs data fetching inside script tags at the top of .vue files
Create a route for a page with a list of posts fetched from your Sanity dataset, and visit http://localhost:3000
<script setup lang="ts">
import type { SanityDocument } from "@sanity/client";
const POSTS_QUERY = groq`*[
_type == "post"
&& defined(slug.current)
]|order(publishedAt desc)[0...12]{_id, title, slug, publishedAt}`;
const { data: posts } = await useSanityQuery<SanityDocument[]>(POSTS_QUERY);
</script>
<template>
<main class="container mx-auto min-h-screen max-w-3xl p-8">
<h1 class="text-4xl font-bold mb-8">Posts</h1>
<ul class="flex flex-col gap-y-4">
<li v-for="post in posts" :key="post._id" class="hover:underline">
<nuxt-link :to="`/${post.slug.current}`">
<h2 class="text-xl font-semibold">{{ post.title }}</h2>
<p>{{ new Date(post.publishedAt).toLocaleDateString() }}</p>
</nuxt-link>
</li>
</ul>
</main>
</template>7Display individual posts
Create a new route for individual post pages.
The dynamic value of a slug when visiting /[slug] in the URL is used as a parameter in the GROQ query used by Sanity Client.
Notice that we’re using Tailwind CSS Typography’s prose class name to style the post’s body block content.
<script setup lang="ts">
import type { SanityDocument } from "@sanity/client";
import { createImageUrlBuilder, type SanityImageSource } from "@sanity/image-url";
const POST_QUERY = groq`*[_type == "post" && slug.current == $slug][0]`;
const { params } = useRoute();
const { data: post } = await useSanityQuery<SanityDocument>(POST_QUERY, params);
const { projectId, dataset } = useSanity().client.config();
const urlFor = (source: SanityImageSource) =>
projectId && dataset
? createImageUrlBuilder({ projectId, dataset }).image(source)
: null;
</script>
<template>
<main
v-if="post"
class="container mx-auto min-h-screen max-w-3xl p-8 flex flex-col gap-4"
>
<a href="/" class="hover:underline">← Back to posts</a>
<img
v-if="post.image"
:src="urlFor(post.image).width(550).height(310).url()"
:alt="post?.title"
class="aspect-video rounded-xl"
width="550"
height="310"
/>
<h1 v-if="post.title" class="text-4xl font-bold mb-8">{{ post.title }}</h1>
<div class="prose">
<p v-if="post.publishedAt">
Published: {{ new Date(post.publishedAt).toLocaleDateString() }}
</p>
<SanityContent v-if="post.body" :blocks="post.body" />
</div>
</main>
</template>Was this page helpful?