---
title: "Images"
description: "Handle WordPress images in your Nuxt app"
canonical_url: "https://wpnuxt.com/guide/images"
---
# Images

> Handle WordPress images in your Nuxt app

WordPress images are served from your WordPress domain. WPNuxt provides utilities and patterns to handle them efficiently.

## The Challenge

WordPress stores images at URLs like:

```text
https://your-wordpress.com/wp-content/uploads/2024/01/photo.jpg
```

In a headless setup, you need to:

1. Serve images from WordPress or proxy them
2. Optimize images for performance
3. Handle responsive images

## Quick Comparison

<table>
<thead>
  <tr>
    <th>
      Approach
    </th>
    
    <th>
      Best For
    </th>
    
    <th>
      Setup
    </th>
    
    <th>
      Optimization
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Direct WordPress URLs
    </td>
    
    <td>
      Prototyping, simple sites
    </td>
    
    <td>
      None
    </td>
    
    <td>
      None
    </td>
  </tr>
  
  <tr>
    <td>
      Proxy with route rules
    </td>
    
    <td>
      Production SSR sites
    </td>
    
    <td>
      <code>
        routeRules
      </code>
      
       config
    </td>
    
    <td>
      Via image provider
    </td>
  </tr>
  
  <tr>
    <td>
      @wpnuxt/blocks
    </td>
    
    <td>
      Sites using Gutenberg blocks
    </td>
    
    <td>
      <code>
        imageDomains
      </code>
      
       config
    </td>
    
    <td>
      NuxtImg built-in
    </td>
  </tr>
  
  <tr>
    <td>
      Nuxt Image standalone
    </td>
    
    <td>
      Custom layouts, no blocks
    </td>
    
    <td>
      <code>
        @nuxt/image
      </code>
      
       module
    </td>
    
    <td>
      Full NuxtImg control
    </td>
  </tr>
</tbody>
</table>

## Approaches

### 1. Direct WordPress URLs (Simple)

Use WordPress image URLs directly. Images are served from WordPress.

```vue
<script setup lang="ts">
const { data: post } = await usePostByUri({ uri: '/hello-world/' })
const imageUrl = post.value?.featuredImage?.node?.sourceUrl
</script>

<template>
  <img :src="imageUrl" :alt="post?.featuredImage?.node?.altText" />
</template>
```

**Pros:** Simple, no configuration needed
**Cons:** No optimization, relies on WordPress hosting

### 2. Proxy with Route Rules (Recommended)

Proxy `/wp-content/` requests to WordPress. Images appear to come from your Nuxt domain.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  routeRules: {
    '/wp-content/**': {
      proxy: 'https://your-wordpress.com/wp-content/**'
    }
  }
})
```

Then use relative paths:

```vue
<script setup lang="ts">
import { getRelativeImagePath } from '#imports'

const { data: post } = await usePostByUri({ uri: '/hello-world/' })
const imageUrl = getRelativeImagePath(post.value?.featuredImage?.node?.sourceUrl)
// Returns: /wp-content/uploads/2024/01/photo.jpg
</script>

<template>
  <img :src="imageUrl" :alt="post?.featuredImage?.node?.altText" />
</template>
```

**Pros:** Same-origin requests, works with image optimization
**Cons:** Adds proxy overhead

### 3. Nuxt Image with @wpnuxt/blocks

`@wpnuxt/blocks` includes `@nuxt/image` and uses `<NuxtImg>` for optimized images.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  modules: ['@wpnuxt/core', '@wpnuxt/blocks'],

  wpNuxtBlocks: {
    imageDomains: ['your-wordpress.com']
  }
})
```

The `CoreImage` block component automatically uses `<NuxtImg>`:

```vue
<NuxtImg
  src="https://your-wordpress.com/wp-content/uploads/photo.jpg"
  alt="Description"
  width="800"
  height="600"
/>
```

### 4. Nuxt Image Standalone

Use `@nuxt/image` without `@wpnuxt/blocks`:

```bash
pnpm add @nuxt/image
```

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  modules: ['@wpnuxt/core', '@nuxt/image'],

  image: {
    domains: ['your-wordpress.com']
  }
})
```

```vue
<script setup lang="ts">
const { data: post } = await usePostByUri({ uri: '/hello-world/' })
</script>

<template>
  <NuxtImg
    :src="post?.featuredImage?.node?.sourceUrl"
    :alt="post?.featuredImage?.node?.altText"
    width="800"
    height="600"
    loading="lazy"
  />
</template>
```

## Production Setup

For production, combine proxy route rules with `<NuxtImg>` to get both same-origin image serving and optimization in one setup.

### Configuration

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  modules: ['@wpnuxt/core', '@nuxt/image'],

  // Proxy WordPress uploads through your domain
  routeRules: {
    '/wp-content/**': {
      proxy: 'https://your-wordpress.com/wp-content/**'
    }
  },

  // Allow NuxtImg to optimize images from your domain
  image: {
    domains: ['your-wordpress.com']
  }
})
```

The proxy makes images same-origin (avoiding CORS and mixed-content issues), while `<NuxtImg>` handles optimization, responsive sizes, and lazy loading.

### Component Example

```vue
<script setup lang="ts">
import { getRelativeImagePath } from '#imports'

const { data: post } = await usePostByUri({ uri: route.path })

const featuredImage = computed(() => {
  const img = post.value?.featuredImage?.node
  if (!img) return null
  return {
    // Convert absolute WordPress URL to relative path for the proxy
    src: getRelativeImagePath(img.sourceUrl),
    alt: img.altText || '',
    width: img.mediaDetails?.width,
    height: img.mediaDetails?.height
  }
})
</script>

<template>
  <NuxtImg
    v-if="featuredImage"
    :src="featuredImage.src"
    :alt="featuredImage.alt"
    :width="featuredImage.width"
    :height="featuredImage.height"
    sizes="sm:100vw md:50vw lg:800px"
    loading="lazy"
  />
</template>
```

`getRelativeImagePath()` converts `https://your-wordpress.com/wp-content/uploads/photo.jpg` to `/wp-content/uploads/photo.jpg`. The proxy route rule then serves that path from your WordPress origin, and `<NuxtImg>` optimizes it with responsive sizes and lazy loading.

<callout type="info">

If you use `@wpnuxt/blocks`, the `CoreImage` block component already handles this pattern automatically — you only need to set `imageDomains` in the blocks config.

</callout>

## Utility: getRelativeImagePath

WPNuxt provides `getRelativeImagePath()` to convert absolute WordPress URLs to relative paths:

```ts
import { getRelativeImagePath } from '#imports'

const absoluteUrl = 'https://your-wordpress.com/wp-content/uploads/2024/01/photo.jpg'
const relativePath = getRelativeImagePath(absoluteUrl)
// Returns: /wp-content/uploads/2024/01/photo.jpg
```

This is useful when:

- Using route rule proxying
- Building static sites where you want consistent paths
- Avoiding hardcoded domains

## Featured Images

WordPress posts and pages can have featured images. The default fragments include featured image data:

```graphql
fragment Post on Post {
  featuredImage {
    node {
      sourceUrl
      altText
      mediaDetails {
        width
        height
      }
    }
  }
}
```

Access in your component:

```vue
<script setup lang="ts">
const { data: post } = await usePostByUri({ uri: route.path })

const featuredImage = computed(() => post.value?.featuredImage?.node)
</script>

<template>
  <NuxtImg
    v-if="featuredImage"
    :src="featuredImage.sourceUrl"
    :alt="featuredImage.altText"
    :width="featuredImage.mediaDetails?.width"
    :height="featuredImage.mediaDetails?.height"
  />
</template>
```

## Responsive Images

For more image optimization techniques including lazy loading and layout shift prevention, see [Performance](https://wpnuxt.com/guide/performance).

Use `<NuxtImg>` with `sizes` for responsive images:

```vue
<NuxtImg
  :src="imageUrl"
  sizes="sm:100vw md:50vw lg:800px"
  loading="lazy"
  placeholder
/>
```

Or use `<NuxtPicture>` for modern formats with fallbacks:

```vue
<NuxtPicture
  :src="imageUrl"
  format="avif,webp"
  sizes="sm:100vw md:50vw lg:800px"
/>
```

## Image Providers

For production optimization, consider using an image provider:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  image: {
    provider: 'cloudflare',
    cloudflare: {
      baseURL: 'https://your-site.com'
    }
  }
})
```

Supported providers include Cloudflare, Vercel, Imgix, Cloudinary, and more. See [Nuxt Image Providers](https://image.nuxt.com/providers/overview).

## Static Site Generation (SSG)

For static sites, images can be:

1. **Left as external URLs** - Images load from WordPress at runtime
2. **Proxied at build time** - Use Nitro prerender to cache images
3. **Downloaded locally** - Use a build script to fetch and store images

For most cases, keeping images on WordPress with a CDN is the simplest approach.

## Troubleshooting

### Images Not Loading

1. Check that the WordPress domain is in `imageDomains` or `image.domains`
2. Verify CORS headers allow requests from your Nuxt domain
3. Check the browser console for blocked requests

### Slow Image Loading

1. Use `loading="lazy"` for below-the-fold images
2. Configure an image provider for optimization
3. Set explicit `width` and `height` to prevent layout shift

### Mixed Content Errors

If your Nuxt site is HTTPS but WordPress is HTTP:

1. Enable HTTPS on WordPress
2. Or use the proxy approach to serve images from your domain

## Related Pages

- **Performance** — Optimize image loading and Core Web Vitals
- **Rendering Blocks** — Image handling within Gutenberg blocks


## Sitemap

See the full [sitemap](https://wpnuxt.com/sitemap.md) for all pages.
