--- title: Nuxt & Sanity Integration Rules description: Integration guide for Nuxt, including @nuxtjs/sanity, visual editing, and data fetching. --- # Nuxt & Sanity Integration Rules ## 1. Setup & Configuration ### Scaffold a new Nuxt app ```bash npm create nuxt@latest my-app -- -t ui -M "" --packageManager npm --no-gitInit cd my-app ``` `-t ui` selects the Nuxt UI starter. `-M ""` skips the interactive module-selection prompt (empty string = no extra modules). `--packageManager npm` and `--no-gitInit` suppress the other two prompts so the scaffold runs end-to-end without input. ### Installation ```bash npx nuxi@latest module add sanity ``` `nuxi module add sanity` resolves to the official `@nuxtjs/sanity` module and registers it in `nuxt.config.ts` automatically. The module bundles `@sanity/client`, `@sanity/visual-editing`, `@portabletext/vue`, and `groq` as direct dependencies — no separate installs needed. `groq` and `defineQuery` are also **auto-imported** by the module, so you can use them in `.vue` files without an `import` statement. For manual image-URL building (an alternative to the auto-registered `` component), add `@sanity/image-url`: ```bash npm install @sanity/image-url ``` ### What the module auto-imports **Composables** (use directly in ` ``` ### Dynamic Routes (`[slug].vue`) Pull the slug off `useRoute()` and pass it as a query parameter. The `` component renders Portable Text — note the prop is `value`, not `blocks` (renamed in v2). ```vue ``` ## 3. Visual Editing (Live Preview) ### Automatic Setup When `visualEditing` is configured in `nuxt.config.ts`, the module handles: 1. Injecting the Visual Editing overlays. 2. Refreshing data when content changes in the Studio. 3. Enabling Stega encoding. ### Handling Stega in Logic If you use stega-encoded strings in logic (e.g. `v-if="post.layout === 'full'"`), you must clean them. `stegaClean` is exported from `@sanity/client/stega` (a transitive of `@nuxtjs/sanity`, so no separate install). ```typescript import { stegaClean } from '@sanity/client/stega' const layout = computed(() => stegaClean(props.layout)) ``` ## 4. Components ### Portable Text — `` The module auto-registers ``. Don't install `@portabletext/vue` separately; it's a direct dep of the module. ```vue ``` For custom blocks/marks, pass `:components`: ```vue ``` ### Images — two options **Option A — `` (recommended).** Auto-registered. Takes the asset's `_ref` (the `assetId`) and builds the URL via the module's resolved projectId/dataset. If `@nuxt/image` is installed, it transparently upgrades to `` for responsive sizing. ```vue ``` **Option B — `@sanity/image-url` builder.** Install `@sanity/image-url` separately and build URLs manually. Useful when you need fine-grained control (hotspot/crop, format negotiation, srcset). ```typescript import imageUrlBuilder from '@sanity/image-url' const builder = imageUrlBuilder(useSanity().client) // builder.image(source).width(800).url() ```