nuxt-og-image 2.0.0-beta.6 → 2.0.0-beta.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +311 -97
- package/dist/client/200.html +2 -2
- package/dist/client/404.html +2 -2
- package/dist/client/_nuxt/IconCSS.b41b9663.css +1 -0
- package/dist/client/_nuxt/IconCSS.c2e73ab2.js +1 -0
- package/dist/client/_nuxt/ImageLoader.7571516f.css +1 -0
- package/dist/client/_nuxt/ImageLoader.ed4bfccb.js +1 -0
- package/dist/client/_nuxt/entry.862302d7.css +1 -0
- package/dist/client/_nuxt/entry.f51ac6f7.js +7 -0
- package/dist/client/_nuxt/{error-404.1ff52902.js → error-404.a94c6c21.js} +1 -1
- package/dist/client/_nuxt/error-404.f3dd5020.css +1 -0
- package/dist/client/_nuxt/error-500.06915589.css +1 -0
- package/dist/client/_nuxt/{error-500.f7d30da5.js → error-500.3955092a.js} +1 -1
- package/dist/client/_nuxt/index.17db8b1a.js +1 -0
- package/dist/client/_nuxt/index.403133d8.css +1 -0
- package/dist/client/_nuxt/options.3e6c211b.js +1 -0
- package/dist/client/_nuxt/png.23a5e57c.js +1 -0
- package/dist/client/_nuxt/{shiki.3a930bb8.js → shiki.2980d306.js} +1 -1
- package/dist/client/_nuxt/svg.a8bba1f1.js +1 -0
- package/dist/client/_nuxt/{vnodes.a799f183.js → vnodes.64d635d6.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/options/index.html +2 -2
- package/dist/client/png/index.html +2 -2
- package/dist/client/svg/index.html +2 -2
- package/dist/client/vnodes/index.html +2 -2
- package/dist/module.d.ts +101 -11
- package/dist/module.json +2 -2
- package/dist/module.mjs +401 -141
- package/dist/runtime/browserUtil.d.ts +1 -0
- package/dist/runtime/browserUtil.mjs +10 -5
- package/dist/runtime/components/{OgImageDynamic.d.ts → OgImage/Cached.d.ts} +2 -3
- package/dist/runtime/components/OgImage/Cached.mjs +10 -0
- package/dist/runtime/components/{OgImageScreenshot.d.ts → OgImage/Screenshot.d.ts} +2 -4
- package/dist/runtime/components/{OgImageScreenshot.mjs → OgImage/Screenshot.mjs} +2 -2
- package/dist/runtime/components/{OgImageStatic.d.ts → OgImage/WithoutCache.d.ts} +2 -3
- package/dist/runtime/components/OgImage/WithoutCache.mjs +10 -0
- package/dist/runtime/components/OgImage/_OgImageDynamic.d.ts +7 -0
- package/dist/runtime/components/{OgImageDynamic.mjs → OgImage/_OgImageDynamic.mjs} +3 -3
- package/dist/runtime/components/OgImage/_OgImageStatic.d.ts +7 -0
- package/dist/runtime/components/{OgImageStatic.mjs → OgImage/_OgImageStatic.mjs} +3 -3
- package/dist/runtime/components/OgImage/index.d.ts +4 -0
- package/dist/runtime/components/OgImage/index.mjs +9 -0
- package/dist/runtime/components/OgImageTemplate/Fallback.vue +155 -0
- package/dist/runtime/composables/defineOgImage.d.ts +12 -4
- package/dist/runtime/composables/defineOgImage.mjs +46 -20
- package/dist/runtime/nitro/middleware/og.png.mjs +54 -8
- package/dist/runtime/nitro/middleware/playground.mjs +4 -3
- package/dist/runtime/nitro/plugins/prerender.d.ts +3 -0
- package/dist/runtime/nitro/plugins/prerender.mjs +28 -0
- package/dist/runtime/nitro/providers/browser/lambda.d.ts +1 -1
- package/dist/runtime/nitro/providers/browser/lambda.mjs +3 -3
- package/dist/runtime/nitro/providers/browser/{node.mjs → playwright.mjs} +0 -9
- package/dist/runtime/nitro/providers/browser/universal.d.ts +1 -0
- package/dist/runtime/nitro/providers/browser/universal.mjs +33 -0
- package/dist/runtime/nitro/providers/png/resvg-node.d.ts +4 -0
- package/dist/runtime/nitro/providers/png/resvg-node.mjs +6 -0
- package/dist/runtime/nitro/providers/png/resvg-wasm.d.ts +3 -0
- package/dist/runtime/nitro/providers/png/resvg-wasm.mjs +11 -0
- package/dist/runtime/nitro/providers/{svg2png/universal.d.ts → png/svg2png.d.ts} +2 -3
- package/dist/runtime/nitro/providers/png/svg2png.mjs +11 -0
- package/dist/runtime/nitro/providers/satori/{webworker.d.ts → yoga-wasm.d.ts} +2 -3
- package/dist/runtime/nitro/providers/satori/{webworker.mjs → yoga-wasm.mjs} +4 -5
- package/dist/runtime/nitro/renderers/browser.d.ts +2 -2
- package/dist/runtime/nitro/renderers/browser.mjs +14 -10
- package/dist/runtime/nitro/renderers/satori/index.d.ts +2 -2
- package/dist/runtime/nitro/renderers/satori/index.mjs +27 -32
- package/dist/runtime/nitro/renderers/satori/plugins/emojis.d.ts +1 -1
- package/dist/runtime/nitro/renderers/satori/plugins/emojis.mjs +19 -6
- package/dist/runtime/nitro/renderers/satori/plugins/encoding.d.ts +1 -1
- package/dist/runtime/nitro/renderers/satori/plugins/encoding.mjs +6 -7
- package/dist/runtime/nitro/renderers/satori/plugins/flex.d.ts +1 -1
- package/dist/runtime/nitro/renderers/satori/plugins/flex.mjs +8 -10
- package/dist/runtime/nitro/renderers/satori/plugins/imageSrc.d.ts +1 -1
- package/dist/runtime/nitro/renderers/satori/plugins/imageSrc.mjs +45 -13
- package/dist/runtime/nitro/renderers/satori/plugins/twClasses.d.ts +1 -1
- package/dist/runtime/nitro/renderers/satori/plugins/twClasses.mjs +5 -7
- package/dist/runtime/nitro/renderers/satori/utils.d.ts +4 -5
- package/dist/runtime/nitro/renderers/satori/utils.mjs +28 -17
- package/dist/runtime/nitro/routes/debug.d.ts +8 -0
- package/dist/runtime/nitro/routes/debug.mjs +14 -0
- package/dist/runtime/nitro/routes/font.mjs +2 -2
- package/dist/runtime/nitro/routes/html.mjs +100 -25
- package/dist/runtime/nitro/routes/options.d.ts +2 -2
- package/dist/runtime/nitro/routes/options.mjs +25 -22
- package/dist/runtime/nitro/routes/svg.mjs +5 -3
- package/dist/runtime/nitro/routes/vnode.mjs +5 -3
- package/dist/runtime/nitro/utils-pure.d.ts +3 -2
- package/dist/runtime/nitro/utils-pure.mjs +9 -10
- package/dist/runtime/nitro/utils.d.ts +11 -11
- package/dist/runtime/nitro/utils.mjs +68 -54
- package/dist/runtime/public-assets/__nuxt_og_image__/browser-provider-not-supported.png +0 -0
- package/dist/runtime/public-assets-optional/resvg/resvg.wasm +0 -0
- package/dist/types.d.ts +6 -0
- package/package.json +38 -27
- package/dist/client/_nuxt/IconCSS.a041aca0.js +0 -1
- package/dist/client/_nuxt/ImageLoader.9bf39d71.js +0 -1
- package/dist/client/_nuxt/entry.74018bda.js +0 -5
- package/dist/client/_nuxt/entry.7a8c1ab2.css +0 -1
- package/dist/client/_nuxt/error-404.1469f10f.css +0 -1
- package/dist/client/_nuxt/error-500.92b94fae.css +0 -1
- package/dist/client/_nuxt/error-component.cf7543e5.js +0 -3
- package/dist/client/_nuxt/index.3f356409.js +0 -1
- package/dist/client/_nuxt/options.56a3e5f9.js +0 -1
- package/dist/client/_nuxt/png.37f3e77b.js +0 -1
- package/dist/client/_nuxt/svg.186c6bd1.js +0 -1
- package/dist/runtime/components/OgImageBasic.island.vue +0 -92
- package/dist/runtime/nitro/providers/svg2png/universal.mjs +0 -9
- /package/dist/runtime/nitro/providers/browser/{node.d.ts → playwright.d.ts} +0 -0
- /package/dist/runtime/nitro/providers/satori/{node.d.ts → default.d.ts} +0 -0
- /package/dist/runtime/nitro/providers/satori/{node.mjs → default.mjs} +0 -0
- /package/dist/runtime/{public-assets → public-assets-optional/inter-font}/inter-latin-ext-400-normal.woff +0 -0
- /package/dist/runtime/{public-assets → public-assets-optional/inter-font}/inter-latin-ext-700-normal.woff +0 -0
- /package/dist/runtime/{public-assets → public-assets-optional/svg2png}/svg2png.wasm +0 -0
- /package/dist/runtime/{public-assets → public-assets-optional/yoga}/yoga.wasm +0 -0
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
Enlightened OG Image generation for Nuxt 3.
|
|
14
14
|
</p>
|
|
15
15
|
|
|
16
|
-
<img src="https://repository-images.githubusercontent.com/578125755/
|
|
16
|
+
<img src="https://repository-images.githubusercontent.com/578125755/90f77ca8-95be-4e06-9600-332afe1ba24f">
|
|
17
17
|
|
|
18
18
|
<p align="center">
|
|
19
19
|
<table>
|
|
@@ -38,7 +38,7 @@ Enlightened OG Image generation for Nuxt 3.
|
|
|
38
38
|
- ▲ Render using [Satori](https://github.com/vercel/satori): Tailwind classes, Google fonts, emoji support and more!
|
|
39
39
|
- 🤖 Or prerender using the Browser: Supporting painless, complex templates
|
|
40
40
|
- 📸 Feeling lazy? Just generate screenshots for every page: hide elements, wait for animations, and more
|
|
41
|
-
- ⚙️ Works on the edge: Vercel Edge and Cloudflare Workers
|
|
41
|
+
- ⚙️ Works on the edge: Vercel Edge, Netlify Edge and Cloudflare Workers
|
|
42
42
|
|
|
43
43
|
## Demos
|
|
44
44
|
|
|
@@ -46,13 +46,33 @@ Enlightened OG Image generation for Nuxt 3.
|
|
|
46
46
|
- [StackBlitz - Minimal Playground Example](https://stackblitz.com/edit/nuxt-starter-pxs3wk?file=pages/index.vue)
|
|
47
47
|
- [StackBlitz - Alpine Theme](https://stackblitz.com/edit/github-hgunsf?file=package.json)
|
|
48
48
|
|
|
49
|
+
## Runtime Provider Compatibility
|
|
50
|
+
|
|
51
|
+
Both Satori and Browser will work in Node based environments. Prerendering is fully supported.
|
|
52
|
+
|
|
53
|
+
When you want to generate dynamic images at runtime there are certain Nitro runtime limitations.
|
|
54
|
+
|
|
55
|
+
| Provider | Satori | Browser |
|
|
56
|
+
|---------------------------------------------------------------------------------|-----------------------|---------|
|
|
57
|
+
| Node | ✅ | ✅ |
|
|
58
|
+
| [Vercel](https://nuxt-og-image-playground.vercel.app/) | ✅ | ❌ |
|
|
59
|
+
| [Vercel Edge](https://nuxt-og-image-playground-gkdt.vercel.app/) | ✅ | ❌ |
|
|
60
|
+
| [Cloudflare Pages](https://nuxt-og-image-playground.pages.dev/) | ✅ | ❌ |
|
|
61
|
+
| [Netlify](https://nuxt-og-image-playground-netlify.netlify.app/) | ✅ | ❌ |
|
|
62
|
+
| [Netlify Edge](https://nuxt-og-image-playground-netlify-edge.netlify.app/) | (Soon) | ❌ |
|
|
63
|
+
| [StackBlitz](https://stackblitz.com/edit/nuxt-starter-pxs3wk?file=package.json) | ✅ (emojis don't work) | ❌ |
|
|
64
|
+
|
|
65
|
+
Other providers are yet to be tested. Please create an issue if your nitro preset is not listed.
|
|
66
|
+
|
|
49
67
|
## Install
|
|
50
68
|
|
|
69
|
+
Note: The `main` branch is documentation for the beta version, it's recommended to use this version.
|
|
70
|
+
|
|
51
71
|
```bash
|
|
52
72
|
# Install module
|
|
53
|
-
npm install --save-dev nuxt-og-image
|
|
73
|
+
npm install --save-dev nuxt-og-image@beta
|
|
54
74
|
# Using yarn
|
|
55
|
-
yarn add --dev nuxt-og-image
|
|
75
|
+
yarn add --dev nuxt-og-image@beta
|
|
56
76
|
```
|
|
57
77
|
|
|
58
78
|
## Setup
|
|
@@ -67,30 +87,8 @@ export default defineNuxtConfig({
|
|
|
67
87
|
})
|
|
68
88
|
```
|
|
69
89
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
This feature uses Nuxt Islands, which requires Nuxt >= 3.1.
|
|
73
|
-
|
|
74
|
-
### Add your host name
|
|
75
|
-
|
|
76
|
-
The `og:image` meta tag requires the full URL, so you must provide your site host.
|
|
77
|
-
|
|
78
|
-
_nuxt.config.ts_
|
|
79
|
-
|
|
80
|
-
```ts
|
|
81
|
-
export default defineNuxtConfig({
|
|
82
|
-
// Recommended
|
|
83
|
-
runtimeConfig: {
|
|
84
|
-
public: {
|
|
85
|
-
siteUrl: process.env.NUXT_PUBLIC_SITE_URL || 'https://example.com',
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
// OR
|
|
89
|
-
ogImage: {
|
|
90
|
-
host: 'https://example.com',
|
|
91
|
-
},
|
|
92
|
-
})
|
|
93
|
-
```
|
|
90
|
+
This module requires [Nuxt Server Components](https://nuxt.com/docs/guide/directory-structure/components#standalone-server-components)
|
|
91
|
+
which will be enabled for you.
|
|
94
92
|
|
|
95
93
|
# Guides
|
|
96
94
|
|
|
@@ -98,31 +96,31 @@ export default defineNuxtConfig({
|
|
|
98
96
|
|
|
99
97
|
For this guide, you will create your Satori OG image using the default component for your home page.
|
|
100
98
|
|
|
101
|
-
### 1. Define
|
|
102
|
-
|
|
103
|
-
Within your `pages/index.vue`, use `defineOgImageStatic` or `OgImageStatic` to define your `og:image` component.
|
|
99
|
+
### 1. Define an OG Image
|
|
104
100
|
|
|
105
|
-
|
|
101
|
+
Within your `pages/index.vue`, use `defineOgImage()` or `<OgImage />` to define your `og:image` component.
|
|
106
102
|
|
|
107
103
|
```vue
|
|
108
104
|
<script lang="ts" setup>
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// 2a. Use the Composition API
|
|
115
|
-
defineOgImageStatic()
|
|
105
|
+
const ogImageOptions = {
|
|
106
|
+
title: 'My awesome home page.',
|
|
107
|
+
}
|
|
108
|
+
// a. Use the Composition API
|
|
109
|
+
defineOgImage(ogImageOptions)
|
|
116
110
|
</script>
|
|
117
111
|
|
|
118
112
|
<template>
|
|
119
113
|
<div>
|
|
120
|
-
<!--
|
|
121
|
-
<
|
|
114
|
+
<!-- b. OR Component API -->
|
|
115
|
+
<OgImage v-bind="ogImageOptions" />
|
|
122
116
|
</div>
|
|
123
117
|
</template>
|
|
124
118
|
```
|
|
125
119
|
|
|
120
|
+
This will use the default template [OgImageBasic](./src/runtime/components/OgImageBasic.island.vue),
|
|
121
|
+
provided by this module.
|
|
122
|
+
|
|
123
|
+
|
|
126
124
|
### 2. View your `og:image`
|
|
127
125
|
|
|
128
126
|
Appending `/__og_image__` to the end of the URL will show you the playground for that pages `og:image`. This provides
|
|
@@ -132,54 +130,58 @@ For example, if your local site is hosted at `http://localhost:3000`, you can vi
|
|
|
132
130
|
|
|
133
131
|
### 3. Customize your `og:image`
|
|
134
132
|
|
|
135
|
-
While you have the playground open, start
|
|
136
|
-
|
|
137
|
-
```vue
|
|
138
|
-
<script lang="ts" setup>
|
|
139
|
-
defineOgImageStatic({
|
|
140
|
-
title: 'Welcome to my site!',
|
|
141
|
-
background: 'lightblue'
|
|
142
|
-
})
|
|
143
|
-
</script>
|
|
144
|
-
```
|
|
133
|
+
While you have the playground open, start customizing the OG Image by modifying the `ogImageOptions`.
|
|
134
|
+
Full HMR is supported, so you should see your changes instantly.
|
|
145
135
|
|
|
146
|
-
Congrats, you've set up your first Satori `og:image`!
|
|
136
|
+
Congrats, you've set up your first Satori `og:image`!
|
|
137
|
+
You can check out the [options](./src/runtime/components/OgImageBasic.island.vue) of the default template.
|
|
147
138
|
|
|
148
139
|
## Making your own Satori template
|
|
149
140
|
|
|
150
141
|
Templates for OG images are powered by Nuxt Islands, which are just Vue components. In this guide we'll create a new
|
|
151
142
|
template and use it for our `og:image`.
|
|
152
143
|
|
|
153
|
-
### 1. Create
|
|
154
|
-
|
|
155
|
-
Make a folder in your components directory called `islands`.
|
|
144
|
+
### 1. Create your template component
|
|
156
145
|
|
|
157
|
-
|
|
158
|
-
you can use the following template to begin:
|
|
146
|
+
Make a new file at the path `./components/OgImage/Default.vue` with the following contents:
|
|
159
147
|
|
|
160
148
|
```vue
|
|
161
149
|
<script setup lang="ts">
|
|
162
150
|
const props = defineProps({
|
|
163
151
|
title: String,
|
|
164
152
|
})
|
|
153
|
+
|
|
154
|
+
// inherited attrs can mess up the satori parser
|
|
155
|
+
defineOptions({
|
|
156
|
+
inheritAttrs: false,
|
|
157
|
+
})
|
|
165
158
|
</script>
|
|
166
159
|
|
|
167
160
|
<template>
|
|
168
161
|
<div class="w-full h-full flex text-white bg-blue-500 items-center justify-center">
|
|
169
|
-
<h1
|
|
162
|
+
<h1>
|
|
170
163
|
{{ title }} 👋
|
|
171
164
|
</h1>
|
|
172
165
|
</div>
|
|
173
166
|
</template>
|
|
167
|
+
<style scoped>
|
|
168
|
+
h1 {
|
|
169
|
+
font-size: 70px;
|
|
170
|
+
}
|
|
171
|
+
</style>
|
|
174
172
|
```
|
|
175
173
|
|
|
174
|
+
The convention is to use either the `OgImage` or `OgImageTemplate` folders within `components`.
|
|
175
|
+
|
|
176
|
+
See [componentDirs](#component-dirs) if you prefer to use a different named directory.
|
|
177
|
+
|
|
176
178
|
### 2. Use the new template
|
|
177
179
|
|
|
178
|
-
Now that you have your template, you can use it in for your `
|
|
180
|
+
Now that you have your template, you can use it in for your `defineOgImage` composable.
|
|
179
181
|
|
|
180
182
|
```vue
|
|
181
183
|
<script lang="ts" setup>
|
|
182
|
-
|
|
184
|
+
defineOgImage({
|
|
183
185
|
component: 'MyOgImage',
|
|
184
186
|
title: 'Welcome to my site!'
|
|
185
187
|
})
|
|
@@ -192,7 +194,7 @@ View this image in your browser by appending `/__og_image__` to the end of the U
|
|
|
192
194
|
|
|
193
195
|
Now that you have your template, you can start customizing it.
|
|
194
196
|
|
|
195
|
-
Any options you pass to the `
|
|
197
|
+
Any options you pass to the `defineOgImage` composable will be available in the component. With this in mind, we can
|
|
196
198
|
add support for changing the background color.
|
|
197
199
|
|
|
198
200
|
```vue
|
|
@@ -205,18 +207,23 @@ const props = defineProps({
|
|
|
205
207
|
|
|
206
208
|
<template>
|
|
207
209
|
<div :class="[backgroundColor]" class="w-full h-full flex text-white items-center justify-center">
|
|
208
|
-
<h1
|
|
210
|
+
<h1>
|
|
209
211
|
{{ title }} 👋
|
|
210
212
|
</h1>
|
|
211
213
|
</div>
|
|
212
214
|
</template>
|
|
215
|
+
<style scoped>
|
|
216
|
+
h1 {
|
|
217
|
+
font-size: 70px;
|
|
218
|
+
}
|
|
219
|
+
</style>
|
|
213
220
|
```
|
|
214
221
|
|
|
215
|
-
Now let's
|
|
222
|
+
Now let's customize the background to be green instead.
|
|
216
223
|
|
|
217
224
|
```vue
|
|
218
225
|
<script lang="ts" setup>
|
|
219
|
-
|
|
226
|
+
defineOgImage({
|
|
220
227
|
component: 'MyOgImage',
|
|
221
228
|
title: 'Welcome to my site!',
|
|
222
229
|
backgroundColor: 'bg-green-500'
|
|
@@ -241,6 +248,86 @@ Out of the box, this module provides support for the following:
|
|
|
241
248
|
|
|
242
249
|
If you find Satori is too limiting for your needs, you can always use the `browser` provider to capture browser screenshots instead.
|
|
243
250
|
|
|
251
|
+
|
|
252
|
+
## Bypassing cache
|
|
253
|
+
|
|
254
|
+
Caching og images is enabled by default, if you need to generate dynamically at runtime,
|
|
255
|
+
you can modify the use the `defineOgImageWithoutCache(options)` composable or `<OgImageWithoutCache v-bind="options" />` component.
|
|
256
|
+
|
|
257
|
+
This mode is not compatible with `nuxt generate`.
|
|
258
|
+
|
|
259
|
+
## SSG Images
|
|
260
|
+
|
|
261
|
+
When using `nuxt generate`, you will need to provide some additional configuration.
|
|
262
|
+
|
|
263
|
+
- You must provide a `siteUrl` so that the meta tags can be generated correctly as absolute URLs.
|
|
264
|
+
|
|
265
|
+
```ts
|
|
266
|
+
export default defineNuxtConfig({
|
|
267
|
+
// Recommended
|
|
268
|
+
runtimeConfig: {
|
|
269
|
+
public: {
|
|
270
|
+
siteUrl: process.env.NUXT_PUBLIC_SITE_URL || 'https://example.com',
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
// OR
|
|
274
|
+
ogImage: {
|
|
275
|
+
host: 'https://example.com',
|
|
276
|
+
},
|
|
277
|
+
})
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
- You must prerender all pages that use `og:image`.
|
|
281
|
+
|
|
282
|
+
```ts
|
|
283
|
+
export default defineNuxtConfig({
|
|
284
|
+
nitro: {
|
|
285
|
+
prerender: {
|
|
286
|
+
crawlLinks: true, // recommended
|
|
287
|
+
routes: [
|
|
288
|
+
'/',
|
|
289
|
+
// list all routes that use og:image if you're not using crawlLinks
|
|
290
|
+
'/about',
|
|
291
|
+
'/blog',
|
|
292
|
+
'/blog/my-first-post',
|
|
293
|
+
]
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
})
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## SSR Images
|
|
300
|
+
|
|
301
|
+
When using `nuxt build`, you can only use the `browser` provider with the `node` Nitro preset.
|
|
302
|
+
|
|
303
|
+
If you intend to use the `browser` provider in production, make sure you include the `playwright` dependency.
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
npm i playwright
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
You can get around this by prerendering any pages that use `og:image`. Note that dynamic browser generated images are not supported at all,
|
|
310
|
+
you should use the Satori provider.
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
```ts
|
|
314
|
+
export default defineNuxtConfig({
|
|
315
|
+
nitro: {
|
|
316
|
+
prerender: {
|
|
317
|
+
crawlLinks: true, // recommended
|
|
318
|
+
routes: [
|
|
319
|
+
'/',
|
|
320
|
+
// list all routes that use og:image if you're not using crawlLinks
|
|
321
|
+
'/about',
|
|
322
|
+
'/blog',
|
|
323
|
+
'/blog/my-first-post',
|
|
324
|
+
]
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
})
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
|
|
244
331
|
## Taking screenshots
|
|
245
332
|
|
|
246
333
|
If you want to simply take a screenshot of your page, you can use the `OgImageScreenshot` component or `defineOgImageScreenshot` composable.
|
|
@@ -251,11 +338,11 @@ defineOgImageScreenshot()
|
|
|
251
338
|
</script>
|
|
252
339
|
```
|
|
253
340
|
|
|
254
|
-
Alternatively you can pass the `{ provider: 'browser' }` option to `
|
|
341
|
+
Alternatively you can pass the `{ provider: 'browser' }` option to `defineOgImage`.
|
|
255
342
|
|
|
256
343
|
```vue
|
|
257
344
|
<script lang="ts" setup>
|
|
258
|
-
|
|
345
|
+
defineOgImage({
|
|
259
346
|
component: 'MyAwesomeOgImage',
|
|
260
347
|
// this will take a browser screenshot
|
|
261
348
|
provider: 'browser'
|
|
@@ -282,15 +369,144 @@ _package.json_
|
|
|
282
369
|
}
|
|
283
370
|
```
|
|
284
371
|
|
|
372
|
+
## Custom Fonts / Supporting non-english characters
|
|
373
|
+
|
|
374
|
+
When creating your OG Image, you'll probably want to use a font custom to your project.
|
|
375
|
+
|
|
376
|
+
To make this easier for you, Google Fonts are loaded by default with Inter 400 and Inter 700.
|
|
377
|
+
|
|
378
|
+
You can easily load different Google Fonts by using their name+weight. For example:
|
|
379
|
+
|
|
380
|
+
```ts
|
|
381
|
+
export default defineNuxtConfig({
|
|
382
|
+
ogImage: {
|
|
383
|
+
fonts: [
|
|
384
|
+
// will load the Noto Sans font from Google fonts
|
|
385
|
+
'Noto+Sans:400'
|
|
386
|
+
]
|
|
387
|
+
}
|
|
388
|
+
})
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
This also lets you support non-english characters by adding the appropriate font to your config.
|
|
392
|
+
|
|
393
|
+
For example, to support Hebrew characters, you can use the config:
|
|
394
|
+
|
|
395
|
+
```ts
|
|
396
|
+
export default defineNuxtConfig({
|
|
397
|
+
ogImage: {
|
|
398
|
+
fonts: [
|
|
399
|
+
// will load this font from Google fonts
|
|
400
|
+
'Noto+Sans+Hebrew:400'
|
|
401
|
+
]
|
|
402
|
+
}
|
|
403
|
+
})
|
|
404
|
+
````
|
|
405
|
+
|
|
406
|
+
If you'd like to load a font locally,
|
|
407
|
+
then you can provide the configuration as an object:
|
|
408
|
+
|
|
409
|
+
```ts
|
|
410
|
+
export default defineNuxtConfig({
|
|
411
|
+
ogImage: {
|
|
412
|
+
fonts: [
|
|
413
|
+
{
|
|
414
|
+
name: 'optieinstein',
|
|
415
|
+
weight: 800,
|
|
416
|
+
// path must point to a public font file
|
|
417
|
+
path: '/OPTIEinstein-Black.otf',
|
|
418
|
+
}
|
|
419
|
+
],
|
|
420
|
+
}
|
|
421
|
+
})
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
Make sure to set the font family in your component to match the font name.
|
|
425
|
+
|
|
426
|
+
```vue
|
|
427
|
+
<template>
|
|
428
|
+
<div :style="{ fontFamily: 'optieinstein' }">
|
|
429
|
+
<!-- Your component -->
|
|
430
|
+
</div>
|
|
431
|
+
</template>
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
## Runtime Caching
|
|
435
|
+
|
|
436
|
+
When images are generated at runtime, caching is enabled by default to reduce the load on your server.
|
|
437
|
+
|
|
438
|
+
By default, it will use the default storage engine for your Nitro preset.
|
|
439
|
+
You can customise the storage engine by providing a `runtimeCacheStorage` option to the `ogImage` config.
|
|
440
|
+
|
|
441
|
+
The option takes the same configuration as the Nuxt `nitro.storage` option.
|
|
442
|
+
See the [Nitro Storage Layer](https://nitro.unjs.io/guide/storage) documentation for more details.
|
|
443
|
+
|
|
444
|
+
For example:
|
|
445
|
+
|
|
446
|
+
```ts
|
|
447
|
+
export default defineNuxtConfig({
|
|
448
|
+
ogImage: {
|
|
449
|
+
// cloudflare kv binding example, set your own config
|
|
450
|
+
runtimeCacheStorage: {
|
|
451
|
+
driver: 'cloudflare-kv-binding',
|
|
452
|
+
binding: 'OG_IMAGE_CACHE'
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
})
|
|
456
|
+
````
|
|
457
|
+
|
|
458
|
+
By default, static images will be cached for 24 hours. You can change the image TTL by providing `cacheTtl` when defining the image.
|
|
459
|
+
|
|
460
|
+
```ts
|
|
461
|
+
defineOgImage({
|
|
462
|
+
// ...
|
|
463
|
+
cacheTtl: 60 * 60 * 24 * 7 // 7 days
|
|
464
|
+
})
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
Alternatively, you can change the default cacheTtl time in your nuxt.config.
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
```ts
|
|
471
|
+
export default defineNuxtConfig({
|
|
472
|
+
ogImage: {
|
|
473
|
+
defaults: {
|
|
474
|
+
cacheTtl: 60 * 60 * 24 * 7 // 7 days
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
})
|
|
478
|
+
````
|
|
479
|
+
|
|
480
|
+
You can also provide a configuration for the `cacheKey`. This gives you control over the cache bursting of the images.
|
|
481
|
+
|
|
482
|
+
```vue
|
|
483
|
+
<script lang="ts" setup>
|
|
484
|
+
defineOgImage({
|
|
485
|
+
cacheKey: `${myData.id}:${myData.updatedAt}`,
|
|
486
|
+
})
|
|
487
|
+
</script>
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
If you prefer not to cache your images you can always disable them by providing a `false` value.
|
|
491
|
+
|
|
492
|
+
```ts
|
|
493
|
+
export default defineNuxtConfig({
|
|
494
|
+
ogImage: {
|
|
495
|
+
// no runtime cache
|
|
496
|
+
runtimeCacheStorage: false
|
|
497
|
+
}
|
|
498
|
+
})
|
|
499
|
+
````
|
|
500
|
+
|
|
285
501
|
# API
|
|
286
502
|
|
|
287
503
|
The module exposes a composition and component API to implement your `og:image` generation. You should pick
|
|
288
504
|
whichever one you prefer using.
|
|
289
505
|
|
|
290
|
-
##
|
|
506
|
+
## OgImage / defineOgImage
|
|
291
507
|
|
|
292
|
-
The `
|
|
293
|
-
that will be
|
|
508
|
+
The `OgImage` component and the `defineOgImage` composable creates a static image
|
|
509
|
+
that will be prerendered.
|
|
294
510
|
|
|
295
511
|
The options follow the [OgImageOptions](#OgImageOptions) interface,
|
|
296
512
|
any additional options will be passed to the `component` as props.
|
|
@@ -302,7 +518,7 @@ It is useful for images that do not change at runtime.
|
|
|
302
518
|
```vue
|
|
303
519
|
<script setup lang="ts">
|
|
304
520
|
// a. Composition API
|
|
305
|
-
|
|
521
|
+
defineOgImage({
|
|
306
522
|
component: 'MyOgImageTemplate',
|
|
307
523
|
title: 'Hello world',
|
|
308
524
|
theme: 'dark'
|
|
@@ -311,7 +527,7 @@ defineOgImageStatic({
|
|
|
311
527
|
|
|
312
528
|
<template>
|
|
313
529
|
<!-- b. Component API -->
|
|
314
|
-
<
|
|
530
|
+
<OgImage
|
|
315
531
|
component="MyOgImageTemplate"
|
|
316
532
|
title="Hello world"
|
|
317
533
|
theme="dark"
|
|
@@ -320,9 +536,9 @@ defineOgImageStatic({
|
|
|
320
536
|
```
|
|
321
537
|
|
|
322
538
|
|
|
323
|
-
##
|
|
539
|
+
## OgImageWithoutCache / defineOgImageWithoutCache
|
|
324
540
|
|
|
325
|
-
The `
|
|
541
|
+
The `OgImageWithoutCache` component and the `defineOgImageWithoutCache` composable creates a dynamic image. They are not prerendered and will
|
|
326
542
|
be generated at runtime.
|
|
327
543
|
|
|
328
544
|
The options follow the [OgImageOptions](#OgImageOptions) interface,
|
|
@@ -337,19 +553,19 @@ This feature is not compatible with static sites built using `nuxi generate`.
|
|
|
337
553
|
const dynamicData = await fetch('https://example.com/api')
|
|
338
554
|
|
|
339
555
|
// a. Composition API
|
|
340
|
-
|
|
556
|
+
defineOgImageWithoutCache({
|
|
341
557
|
component: 'MyOgImageTemplate',
|
|
342
558
|
title: 'Hello world',
|
|
343
|
-
dynamicData,
|
|
559
|
+
...dynamicData,
|
|
344
560
|
})
|
|
345
561
|
</script>
|
|
346
562
|
|
|
347
563
|
<template>
|
|
348
564
|
<!-- b. Component API -->
|
|
349
|
-
<
|
|
565
|
+
<OgImageWithoutCache
|
|
350
566
|
component="MyOgImageTemplate"
|
|
351
567
|
title="Hello world"
|
|
352
|
-
|
|
568
|
+
v-bind="dynamicData"
|
|
353
569
|
/>
|
|
354
570
|
</template>
|
|
355
571
|
```
|
|
@@ -396,12 +612,14 @@ The name of the component to use as the template. By default, it uses OgImageBas
|
|
|
396
612
|
- Required: `false`
|
|
397
613
|
|
|
398
614
|
The provider to use to generate the image. The default provider is `satori`.
|
|
399
|
-
When you use `browser` it will use
|
|
615
|
+
When you use `browser` it will use Playwright to generate the image.
|
|
400
616
|
|
|
401
|
-
### `
|
|
617
|
+
### `cache`
|
|
402
618
|
|
|
403
619
|
- Type: `boolean`
|
|
404
|
-
- Default: `true` when
|
|
620
|
+
- Default: `true` when using `defineOgImage`, `false` when dynamic
|
|
621
|
+
|
|
622
|
+
Controls the prerendering of the image. A non-static image is one that will be generated at runtime and not cached.
|
|
405
623
|
|
|
406
624
|
|
|
407
625
|
## OgImageScreenshot / defineOgImageScreenshot
|
|
@@ -495,13 +713,13 @@ defineOgImageScreenshot({
|
|
|
495
713
|
|
|
496
714
|
## Module Config
|
|
497
715
|
|
|
498
|
-
### `
|
|
716
|
+
### `siteUrl`
|
|
499
717
|
|
|
500
718
|
- Type: `string`
|
|
501
719
|
- Default: `undefined`
|
|
502
720
|
- Required: `true`
|
|
503
721
|
|
|
504
|
-
The
|
|
722
|
+
The site URL of your site. This is required when prerendering to generate the absolute path of the `og:image`.
|
|
505
723
|
|
|
506
724
|
### `defaults`
|
|
507
725
|
|
|
@@ -511,15 +729,6 @@ The host of your site. This is required to generate the absolute path of the `og
|
|
|
511
729
|
|
|
512
730
|
The default options to use when generating images.
|
|
513
731
|
|
|
514
|
-
### `forcePrerender`
|
|
515
|
-
|
|
516
|
-
- Type: `boolean`
|
|
517
|
-
- Default: `false`
|
|
518
|
-
- Required: `false`
|
|
519
|
-
|
|
520
|
-
This is enabled when you run `nuxi generate`. It forces all OG images to be pre-rendered as the server is not available to generate
|
|
521
|
-
runtime images.
|
|
522
|
-
|
|
523
732
|
### `fonts`
|
|
524
733
|
|
|
525
734
|
- Type: ``${string}:${number}`[]`
|
|
@@ -546,16 +755,21 @@ export default defineNuxtConfig({
|
|
|
546
755
|
|
|
547
756
|
Options to pass to Satori when generating images. See the [Satori docs](https://github.com/vercel/satori).
|
|
548
757
|
|
|
549
|
-
### `
|
|
758
|
+
### `runtimeSatori`
|
|
550
759
|
|
|
551
760
|
- Type: `boolean`
|
|
552
|
-
- Default: `
|
|
553
|
-
|
|
761
|
+
- Default: `true`
|
|
762
|
+
|
|
763
|
+
Whether to use Satori at runtime. This is useful to disable if you're prerendering all your images.
|
|
764
|
+
|
|
765
|
+
### `runtimeBrowser`
|
|
766
|
+
|
|
767
|
+
- Type: `boolean`
|
|
768
|
+
- Default: `process.dev`
|
|
554
769
|
|
|
555
|
-
|
|
556
|
-
|
|
770
|
+
Whether to use Playwright at runtime. You will need to enable this for production environments and ensure you are using
|
|
771
|
+
a supported nitro preset and have the required dependencies.
|
|
557
772
|
|
|
558
|
-
This is experimental and may not work in all environments.
|
|
559
773
|
|
|
560
774
|
## Examples
|
|
561
775
|
|
package/dist/client/200.html
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html >
|
|
3
3
|
<head><meta charset="utf-8">
|
|
4
|
-
<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="modulepreload" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/entry.
|
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="modulepreload" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/entry.f51ac6f7.js"><link rel="preload" as="style" href="/__nuxt_og_image__/client/_nuxt/entry.862302d7.css"><link rel="prefetch" as="style" href="/__nuxt_og_image__/client/_nuxt/error-404.f3dd5020.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/error-404.a94c6c21.js"><link rel="prefetch" as="style" href="/__nuxt_og_image__/client/_nuxt/error-500.06915589.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/error-500.3955092a.js"><link rel="stylesheet" href="/__nuxt_og_image__/client/_nuxt/entry.862302d7.css"><script>"use strict";(()=>{const a=window,e=document.documentElement,m=["dark","light"],c=window.localStorage.getItem("nuxt-color-mode")||"system";let n=c==="system"?f():c;const l=e.getAttribute("data-color-mode-forced");l&&(n=l),i(n),a["__NUXT_COLOR_MODE__"]={preference:c,value:n,getColorScheme:f,addColorScheme:i,removeColorScheme:d};function i(o){const t=""+o+"",s="";e.classList?e.classList.add(t):e.className+=" "+t,s&&e.setAttribute("data-"+s,o)}function d(o){const t=""+o+"",s="";e.classList?e.classList.remove(t):e.className=e.className.replace(new RegExp(t,"g"),""),s&&e.removeAttribute("data-"+s)}function r(o){return a.matchMedia("(prefers-color-scheme"+o+")")}function f(){if(a.matchMedia&&r("").media!=="not all"){for(const o of m)if(r(":"+o).matches)return o}return"light"}})();
|
|
5
5
|
</script></head>
|
|
6
|
-
<body ><div id="__nuxt"></div><script>window.__NUXT__={
|
|
6
|
+
<body ><div id="__nuxt"><svg class="nuxt-spa-loading" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 37 25" fill="none" width="80"><path d="M24.236 22.006h10.742L25.563 5.822l-8.979 14.31a4 4 0 0 1-3.388 1.874H2.978l11.631-20 5.897 10.567"></path></svg><style>.nuxt-spa-loading{position:fixed;top:50%;left:50%;transform:translate(-50%, -50%)}.nuxt-spa-loading>path{fill:none;stroke:#00DC82;stroke-width:4px;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:128;stroke-dashoffset:128;animation:nuxt-spa-loading-move 3s linear infinite}@keyframes nuxt-spa-loading-move{100%{stroke-dashoffset:-128}}</style></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"_errors":1,"serverRendered":2,"data":3,"state":4},{},false,{},{}]</script><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt_og_image__/client",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="module" src="/__nuxt_og_image__/client/_nuxt/entry.f51ac6f7.js" crossorigin></script></body>
|
|
7
7
|
</html>
|
package/dist/client/404.html
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html >
|
|
3
3
|
<head><meta charset="utf-8">
|
|
4
|
-
<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="modulepreload" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/entry.
|
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="modulepreload" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/entry.f51ac6f7.js"><link rel="preload" as="style" href="/__nuxt_og_image__/client/_nuxt/entry.862302d7.css"><link rel="prefetch" as="style" href="/__nuxt_og_image__/client/_nuxt/error-404.f3dd5020.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/error-404.a94c6c21.js"><link rel="prefetch" as="style" href="/__nuxt_og_image__/client/_nuxt/error-500.06915589.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/error-500.3955092a.js"><link rel="stylesheet" href="/__nuxt_og_image__/client/_nuxt/entry.862302d7.css"><script>"use strict";(()=>{const a=window,e=document.documentElement,m=["dark","light"],c=window.localStorage.getItem("nuxt-color-mode")||"system";let n=c==="system"?f():c;const l=e.getAttribute("data-color-mode-forced");l&&(n=l),i(n),a["__NUXT_COLOR_MODE__"]={preference:c,value:n,getColorScheme:f,addColorScheme:i,removeColorScheme:d};function i(o){const t=""+o+"",s="";e.classList?e.classList.add(t):e.className+=" "+t,s&&e.setAttribute("data-"+s,o)}function d(o){const t=""+o+"",s="";e.classList?e.classList.remove(t):e.className=e.className.replace(new RegExp(t,"g"),""),s&&e.removeAttribute("data-"+s)}function r(o){return a.matchMedia("(prefers-color-scheme"+o+")")}function f(){if(a.matchMedia&&r("").media!=="not all"){for(const o of m)if(r(":"+o).matches)return o}return"light"}})();
|
|
5
5
|
</script></head>
|
|
6
|
-
<body ><div id="__nuxt"></div><script>window.__NUXT__={
|
|
6
|
+
<body ><div id="__nuxt"><svg class="nuxt-spa-loading" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 37 25" fill="none" width="80"><path d="M24.236 22.006h10.742L25.563 5.822l-8.979 14.31a4 4 0 0 1-3.388 1.874H2.978l11.631-20 5.897 10.567"></path></svg><style>.nuxt-spa-loading{position:fixed;top:50%;left:50%;transform:translate(-50%, -50%)}.nuxt-spa-loading>path{fill:none;stroke:#00DC82;stroke-width:4px;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:128;stroke-dashoffset:128;animation:nuxt-spa-loading-move 3s linear infinite}@keyframes nuxt-spa-loading-move{100%{stroke-dashoffset:-128}}</style></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"_errors":1,"serverRendered":2,"data":3,"state":4},{},false,{},{}]</script><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt_og_image__/client",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="module" src="/__nuxt_og_image__/client/_nuxt/entry.f51ac6f7.js" crossorigin></script></body>
|
|
7
7
|
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
span[data-v-1172c8f8]{background-color:currentColor;display:inline-block;-webkit-mask-image:var(--193e663e);mask-image:var(--193e663e);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;vertical-align:middle}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{g as r,G as u,H as p,m as t,o as l,c as _,q as m,_ as f}from"./entry.f51ac6f7.js";const d=r({__name:"IconCSS",props:{name:{type:String,required:!0},size:{type:String,default:""}},setup(a){const s=a;u(e=>({"193e663e":i.value}));const n=p();n?.nuxtIcon?.aliases;const c=t(()=>(n?.nuxtIcon?.aliases||{})[s.name]||s.name),i=t(()=>`url('https://api.iconify.design/${c.value.replace(":","/")}.svg')`),o=t(()=>{if(!s.size&&typeof n.nuxtIcon?.size=="boolean"&&!n.nuxtIcon?.size)return;const e=s.size||n.nuxtIcon?.size||"1em";return String(Number(e))===e?`${e}px`:e});return(e,x)=>(l(),_("span",{style:m({width:o.value,height:o.value})},null,4))}});const g=f(d,[["__scopeId","data-v-1172c8f8"]]);export{g as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
img[data-v-23ec6856]{height:auto!important;margin:0 auto;max-width:100%;transition:.4s ease-in-out;width:auto!important}
|