Skip to content

Commit 25cf40a

Browse files
authoredMar 5, 2025··
feat: support error pages (#330)
* feat: support error pages * fix: missing test snapshot
1 parent fbdf60c commit 25cf40a

File tree

9 files changed

+101
-6
lines changed

9 files changed

+101
-6
lines changed
 

‎docs/content/0.getting-started/1.installation.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ navigation:
99

1010
Want to know why you might need this module? Check out the [introduction](/docs/og-image/getting-started/introduction).
1111

12-
To get started with Nuxt OG IMage, you need to install the dependency and add it to your Nuxt config.
12+
To get started with Nuxt OG Image, you need to install the dependency and add it to your Nuxt config.
1313

1414
:ModuleInstall{name="og-image"}
1515

‎docs/content/0.getting-started/5.getting-familar-with-nuxt-og-image.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ Within the playground, you should now see the background color change to green.
199199

200200
## Conclusion
201201

202-
Thanks for following along! You know have a basic understanding of how to use the module.
202+
Thanks for following along! You now have a basic understanding of how to use the module.
203203

204204
It's recommended to look through the rest of the documentation to get a full understanding of what's possible.
205205

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
title: Error pages
3+
description: How to display og images for error pages
4+
---
5+
6+
Nuxt OG Image supports displaying images for pages with a non-200 status code (for example a 404 page). It supports both errors thrown by Nuxt, as well as custom errors created using `setResponseStatus`.
7+
8+
To define an og image for an error page, call `defineOgImageComponent` in the setup script of your `error.vue` file:
9+
10+
```vue [error.vue]
11+
<script lang="ts" setup>
12+
defineOgImageComponent('NuxtSeo')
13+
</script>
14+
```
15+
16+
You can use this, for example, to display a generic OG Image containing the status code and status message by
17+
accessing the error provided by Nuxt:
18+
19+
```vue [error.vue]
20+
<script lang="ts" setup>
21+
import type { NuxtError } from '#app'
22+
23+
const props = defineProps<{
24+
error: NuxtError
25+
}>()
26+
27+
defineOgImageComponent('NuxtSeo', {
28+
title: error.statusCode.toString(),
29+
description: error.statusText
30+
})
31+
</script>
32+
```
33+
34+
## Limitations
35+
36+
Note that displaying OG Images for error pages is only supported for status codes ranging 400 to 499. Pages with status codes >= 500 won't generate an OG Image.
37+

‎playground/error.vue

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<script lang="ts" setup>
2+
import { defineOgImageComponent } from '#imports'
3+
import type { NuxtError } from '#app'
4+
5+
const props = defineProps<{
6+
error: NuxtError
7+
}>()
8+
9+
defineOgImageComponent('NuxtSeo', {
10+
title: props.error.statusCode.toString(),
11+
description: props.error.statusMessage,
12+
theme: '#fcfcfc',
13+
colorMode: 'dark',
14+
})
15+
</script>
16+
<template>
17+
<p>{{ error.statusCode }} - {{ error.statusMessage }}</p>
18+
</template>

‎playground/pages/not-found.vue

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<script lang="ts" setup>
2+
import { createError } from '#imports'
3+
4+
throw createError({
5+
statusCode: 404,
6+
statusMessage: 'Not found'
7+
})
8+
</script>
9+
<template>
10+
<p>not found page</p>
11+
</template>

‎src/runtime/server/og-image/context.ts

+15-4
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ async function doFetchWithErrorHandling(fetch: any, path: string) {
220220
.catch((err: any) => {
221221
return err
222222
})
223-
let errorDescription
223+
let errorDescription: string
224224
// if its a redirect let's get the redirect path
225225
if (res.status >= 300 && res.status < 400) {
226226
// follow valid redirects
@@ -229,17 +229,28 @@ async function doFetchWithErrorHandling(fetch: any, path: string) {
229229
}
230230
errorDescription = `${res.status} redirected to ${res.headers.get('location') || 'unknown'}`
231231
}
232-
else if (res.status >= 400) {
232+
// if its an internal error, return the error
233+
else if (res.status >= 500) {
233234
// try get the error message from the response
234235
errorDescription = `${res.status} error: ${res.statusText}`
235236
}
237+
// status codes 400-499 are not handled here to allow displaying og images for error pages
238+
236239
if (errorDescription) {
237240
return [null, createError({
238241
statusCode: 500,
239242
statusMessage: `[Nuxt OG Image] Failed to parse \`${path}\` for og-image extraction. ${errorDescription}`,
240243
})]
241244
}
242-
return [res._data || await res.text(), null]
245+
246+
if (res._data) {
247+
return [res._data, null]
248+
}
249+
else if (res.text) {
250+
return [await res.text(), null]
251+
}
252+
253+
return ['', null]
243254
}
244255

245256
// TODO caching
@@ -279,7 +290,7 @@ async function fetchPathHtmlAndExtractOptions(e: H3Event, path: string, key: str
279290
if (!_payload) {
280291
return createError({
281292
statusCode: 500,
282-
statusMessage: `[Nuxt OG Image] HTML response from ${path} is missing the #nuxt-og-image-options script tag. Check you have used defined an og image for this page.`,
293+
statusMessage: `[Nuxt OG Image] HTML response from ${path} is missing the #nuxt-og-image-options script tag. Make sure you have defined an og image for this page.`,
283294
})
284295
}
285296

‎test/fixtures/basic/error.vue

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<script lang="ts" setup>
2+
defineOgImage({
3+
renderer: 'satori',
4+
props: {
5+
title: 'Hello World',
6+
},
7+
})
8+
</script>
9+
10+
<template>
11+
<p>Error page</p>
12+
</template>
Loading

‎test/integration/base.test.ts

+6
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ describe('build', () => {
4444
})
4545

4646
expect(Buffer.from(defaults)).toMatchImageSnapshot()
47+
48+
const errorPageImage: ArrayBuffer = await $fetch('/prefix/__og-image__/image/not-found/og.png', {
49+
responseType: 'arrayBuffer',
50+
})
51+
52+
expect(Buffer.from(errorPageImage)).toMatchImageSnapshot()
4753
}, 60000)
4854

4955
it('dynamic images', async () => {

0 commit comments

Comments
 (0)
Please sign in to comment.