---
title: "Nuxt"
description: "Generate dynamic OG images and on-demand graphics in Nuxt 3 with the Imejis.io API. A Nitro server route keeps your API key private and streams a cached image."
url: "https://www.imejis.io/apis/nuxt"
published: "2026-07-27"
---

# Nuxt

## Nuxt

Give every page its own OG image from one Imejis template. The Nitro **server route** below acts as a proxy: your API key stays on the server via `runtimeConfig`, and crawlers only ever hit your own URL.

Set two environment variables and expose them to the server through `runtimeConfig`.

```bash title=".env"
IMEJIS_API_KEY=your_api_key
IMEJIS_DESIGN_ID=your_design_id
```

```typescript showLineNumbers title="nuxt.config.ts"
export default defineNuxtConfig({
  runtimeConfig: {
    imejisApiKey: process.env.IMEJIS_API_KEY,
    imejisDesignId: process.env.IMEJIS_DESIGN_ID,
  },
})
```

### 1. A server route that renders the image

```typescript showLineNumbers title="server/routes/og.get.ts"
export default defineEventHandler(async (event) => {
  const { title = "Untitled" } = getQuery(event)
  const config = useRuntimeConfig()

  const image = await $fetch<ArrayBuffer>(
    `https://render.imejis.io/v1/${config.imejisDesignId}`,
    {
      method: "POST",
      headers: { "dma-api-key": config.imejisApiKey as string },
      body: { "headline.text": String(title) },
      responseType: "arrayBuffer",
    }
  )

  setResponseHeaders(event, {
    "Content-Type": "image/jpeg",
    "Cache-Control": "public, immutable, no-transform, max-age=31536000",
  })
  return Buffer.from(image)
})
```

### 2. Reference it from your page

```vue showLineNumbers title="pages/blog/[slug].vue"
<script setup lang="ts">
const { slug } = useRoute().params
const { data: post } = await useFetch(`/api/posts/${slug}`)

useSeoMeta({
  title: () => post.value?.title,
  ogImage: () =>
    `https://your-site.com/og?title=${encodeURIComponent(post.value?.title ?? "")}`,
  twitterCard: "summary_large_image",
})
</script>
```

**Override any field.** Each dynamic component exposes keys like `headline.text`, `title.color`, or `image.image`. Send only the ones you want to change. You'll find a design's overridable fields in its Share / API panel.
