nuxt-og-image 1.0.0-beta.9 → 1.1.1

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 CHANGED
@@ -20,7 +20,7 @@ Enlightened OG Image generation for Nuxt 3.
20
20
  <tbody>
21
21
  <td align="center">
22
22
  <img width="800" height="0" /><br>
23
- <i>Status:</i> v1 Released</b> <br>
23
+ <i>Status:</i> <a href="https://github.com/harlan-zw/nuxt-og-image/releases/tag/v1.0.0">v1 Released</a></b> <br>
24
24
  <sup> Please report any issues 🐛</sup><br>
25
25
  <sub>Made possible by my <a href="https://github.com/sponsors/harlan-zw">Sponsor Program 💖</a><br> Follow me <a href="https://twitter.com/harlan_zw">@harlan_zw</a> 🐦 • Join <a href="https://discord.gg/275MBUBvgP">Discord</a> for help</sub><br>
26
26
  <img width="800" height="0" />
@@ -29,22 +29,16 @@ Enlightened OG Image generation for Nuxt 3.
29
29
  </table>
30
30
  </p>
31
31
 
32
- ℹ️ Looking for a complete SEO solution? Check out [nuxt-seo-kit](https://github.com/harlan-zw/nuxt-seo-kit).
32
+ ℹ️ Looking for a complete SEO solution? Check out [Nuxt SEO Kit](https://github.com/harlan-zw/nuxt-seo-kit).
33
33
 
34
34
 
35
35
  ## Features
36
36
 
37
- ## 🎨 Designer - Satori & Browser
38
-
39
- - 🎨 Design your `og:image` in the Og Image Playground with full HMR
40
- - Dynamically serve on the edge using Satori
41
- - Prerender static images using Satori or the browser
42
-
43
- ## Screenshots - Browser
44
-
45
- - 📸 OR just generate screenshots
46
- - ⚙️ Screenshot options to hide elements, wait for animations, and more
47
-
37
+ - 🎨 Design your `og:image` in the OG Image Playground with full HMR
38
+ - ▲ Blazing fast [Satori](https://github.com/vercel/satori) provider: Tailwind classes, Google fonts, emoji support and more!
39
+ - 🤖 Browser provider: Supporting painless, complex templates
40
+ - Prerendering enabled for static images
41
+ - 📸 Feeling lazy? Just generate screenshots with options for hiding elements, waiting for animations, and more
48
42
 
49
43
  ## Install
50
44
 
@@ -67,6 +61,10 @@ export default defineNuxtConfig({
67
61
  })
68
62
  ```
69
63
 
64
+ #### Requirements
65
+
66
+ This feature uses Nuxt Islands, which requires Nuxt 3.1.
67
+
70
68
  ### Add your host name
71
69
 
72
70
  The `og:image` meta tag requires the full URL, so you must provide your site host.
@@ -86,204 +84,349 @@ export default defineNuxtConfig({
86
84
  })
87
85
  ```
88
86
 
89
- ## Guides
87
+ # Guides
88
+
89
+ ## Your first Satori `og:image`
90
90
 
91
- ### Create your first og:image
91
+ For this guide, you will create your Satori OG image using the default component for your home page.
92
92
 
93
+ ### 1. Define a static OG Image
93
94
 
94
- ## Generating Screenshots
95
+ Within your `pages/index.vue`, use `defineOgImageStatic` or `OgImageStatic` to define your `og:image` component.
95
96
 
96
- _Your page / app.vue / layout_
97
+ Make sure you have defined some metadata for your page with `useHead` as props will be inferred from it.
97
98
 
98
99
  ```vue
99
100
  <script lang="ts" setup>
100
- // Choose either Composition API
101
- defineOgImageScreenshot()
101
+ // 1. make sure you have some meta
102
+ useHead({
103
+ title: 'Home',
104
+ meta: [
105
+ { name: 'description', content: 'My awesome home page.' },
106
+ ],
107
+ })
108
+ // 2a. Use the Composition API
109
+ defineOgImageStatic()
102
110
  </script>
103
111
  <template>
104
112
  <div>
105
- <!-- OR Component API -->
106
- <OgImageScreenshot />
113
+ <!-- 2b. OR Component API -->
114
+ <OgImageStatic />
107
115
  </div>
108
116
  </template>
109
117
  ```
110
118
 
119
+ ### 2. View your `og:image`
111
120
 
112
- If you don't have a chromium binary installed on your system, run `npx playwright install`.
121
+ Appending `/__og_image__` to the end of the URL will show you the playground for that pages `og:image`. This provides
122
+ a live preview of your `og:image` and allows you to edit it in real-time.
113
123
 
114
- ### CI Build
124
+ For example, if your local site is hosted at `https://localhost:3000`, you can view your `og:image` at `https://localhost:3000/__og_image__`.
115
125
 
116
- If you are using this module in a CI context and the images aren't being generated,
117
- you should may need to install a chromium binary. You can do this by running `npx playwright install` or
118
- `npm install playwright`.
126
+ You should see something like the following:
119
127
 
120
- _package.json_
128
+ <img src="https://repository-images.githubusercontent.com/578125755/59ca1ac4-f032-4576-8179-d968a1631f1e">
121
129
 
122
- ```json
123
- {
124
- "scripts": {
125
- "build": "npx playwright install && nuxt build"
126
- }
127
- }
130
+ ### 3. Customize your `og:image`
131
+
132
+ While you have the playground open, start customising the OG Image by providing options to the `defineOgImageStatic` function.
133
+
134
+ ```vue
135
+ <script lang="ts" setup>
136
+ defineOgImageStatic({
137
+ title: 'Welcome to my site!'
138
+ })
139
+ </script>
128
140
  ```
129
141
 
142
+ Congrats, you've set up your first Satori `og:image`!
143
+
144
+ ## Making your own Satori template
130
145
 
131
- ## Generating Template Images
146
+ Templates for OG images are powered by Nuxt Islands, which are just Vue components. In this guide we'll create a new
147
+ template and use it for our `og:image`.
132
148
 
133
- The template image generator is powered by Nuxt Islands. This means that you can use any Vue
134
- component you want to generate your images.
149
+ ### 1. Create an island component
135
150
 
136
- _Your page / app.vue / layout_
151
+ Make a folder in your components directory called `islands`.
152
+
153
+ Within this directory make a new component called `MyOgImage.vue`,
154
+ you can use the following template to begin:
137
155
 
138
156
  ```vue
139
- <script lang="ts" setup>
140
- // Choose either Composition API
141
- defineOgImage({
142
- component: 'OgImageTemplate', // Nuxt Island component
143
- alt: 'My awesome image', // alt text for image
144
- // pass in any custom props
145
- myCustomTitle: 'My Title'
157
+ <script setup lang="ts">
158
+ const props = defineProps({
159
+ title: String,
146
160
  })
147
161
  </script>
148
162
  <template>
149
- <div>
150
- <!-- OR Component API -->
151
- <OgImage component="OgImageTemplate" my-custom-title="My Title" />
152
- </div>
163
+ <div class="w-full h-full flex text-white bg-blue-500 items-center justify-center">
164
+ <h1 :style="{ fontSize: '70px' }">{{ title }} 👋</h1>
165
+ </div>
153
166
  </template>
154
167
  ```
155
168
 
156
- ### Requirements
157
-
158
- To be able to preview the image in development and generate template images, you'll need
159
- to enable Nuxt Islands.
160
-
161
- If you're using Nuxt 3.0.0, you will need to switch to the [edge-release channel](https://nuxt.com/docs/guide/going-further/edge-channel#edge-release-channel).
169
+ ### 2. Use the new template
162
170
 
163
- Once that's done, you can enable the flag for islands.
171
+ Now that you have your template, you can use it in for your `defineOgImageStatic` function.
164
172
 
165
- _nuxt.config.ts_
166
-
167
- ```ts
168
- export default defineNuxtConfig({
169
- experimental: {
170
- componentIslands: true
171
- },
173
+ ```vue
174
+ <script lang="ts" setup>
175
+ defineOgImageStatic({
176
+ component: 'MyOgImage',
177
+ title: 'Welcome to my site!'
172
178
  })
179
+ </script>
173
180
  ```
174
181
 
175
- ### Creating your own template
182
+ View this image in your browser by appending `/__og_image__` to the end of the URL.
183
+
184
+ ### 3. Customize your template
176
185
 
177
- Create a new component with `.island.vue` as the suffix, such as `components/Banner.island.vue`.
186
+ Now that you have your template, you can start customizing it.
178
187
 
179
- Use the below template to test it works, then modify it how you like.
188
+ Any options you pass to the `defineOgImageStatic` composable will be available in the component. With this in mind, we can
189
+ add support for changing the background color.
180
190
 
181
191
  ```vue
182
192
  <script setup lang="ts">
183
193
  const props = defineProps({
184
- // these will always be provided
185
- path: String,
186
194
  title: String,
187
- description: String,
188
- // anything custom comes here
189
- backgroundImage: String
195
+ backgroundColor: String
190
196
  })
191
197
  </script>
192
-
193
198
  <template>
194
- <div class="wrap">
195
- <div>
196
- <h1>
197
- {{ title }}
198
- </h1>
199
- <p>{{ description }}</p>
200
- </div>
201
- </div>
199
+ <div :class="[backgroundColor]" class="w-full h-full flex text-white items-center justify-center">
200
+ <h1 :style="{ fontSize: '70px' }">{{ title }} 👋</h1>
201
+ </div>
202
202
  </template>
203
+ ```
203
204
 
204
- <style scoped>
205
- .wrap {
206
- width: 100%;
207
- height: 100%;
208
- display: flex;
209
- align-items: center;
210
- justify-content: center;
211
- color: white;
212
- background: linear-gradient(to bottom, #30e8bf, #ff8235);
213
- }
205
+ Now let's customise the background to be green instead.
214
206
 
215
- h1 {
216
- font-size: 4rem;
217
- }
218
- </style>
207
+ ```vue
208
+ <script lang="ts" setup>
209
+ defineOgImageStatic({
210
+ component: 'MyOgImage',
211
+ title: 'Welcome to my site!',
212
+ backgroundColor: 'bg-green-500'
213
+ })
214
+ </script>
215
+ ```
216
+
217
+ Within the playground, you should now see the background color change to green.
218
+
219
+ ## Using Satori
220
+
221
+ It's important to familiarize yourself with [Satori](https://github.com/vercel/satori) before you make more complex templates.
222
+
223
+ Satori has limited capacity for rendering styles;
224
+ you should reference which ones are available within their documentation.
225
+
226
+ Out of the box, this module provides support for the following:
227
+ - Tailwind classes
228
+ - Google Fonts, default is Inter
229
+ - Emoji support with [Twemoji](https://github.com/twitter/twemoji)
230
+ - Relative image support (you should link images from your public directory `/my-image.png`)
231
+
232
+ If you find Satori is too limiting for your needs, you can always use the `browser` provider to capture browser screenshots instead.
233
+
234
+ ## Taking screenshots
235
+
236
+ If you want to simply take a screenshot of your page, you can use the `OgImageScreenshot` component or `defineOgImageScreenshot` composable.
237
+
238
+ ```vue
239
+ <script lang="ts" setup>
240
+ defineOgImageScreenshot()
241
+ </script>
219
242
  ```
220
243
 
221
- Make sure you reference this component when using `defineOgImage` and any props to pass.
244
+ Alternatively you can pass the `{ provider: 'browser' }` option to `defineOgImageStatic`.
222
245
 
223
246
  ```vue
224
247
  <script lang="ts" setup>
225
- defineOgImage({
226
- component: 'Banner',
227
- backgroundImage: 'https://example.com/my-background-image.jpg',
248
+ defineOgImageStatic({
249
+ component: 'MyAwesomeOgImage',
250
+ // this will take a browser screenshot
251
+ provider: 'browser'
228
252
  })
229
253
  </script>
230
254
  ```
231
255
 
232
- ## Previewing Images
256
+ ### Requirements
233
257
 
234
- Once you have defined the og:image using the composable, you can preview the image by visiting
235
- the following URLs:
236
- - `/your-path/__og-image` Renders the HTML output
237
- - `/your-path/og-image.png` Renders the og:image
258
+ If you don't have a chromium binary installed on your system, run `npx playwright install`.
238
259
 
239
- ### Prerender routes
260
+ If you are using this module in a CI context and the images aren't being generated,
261
+ you may need to install a chromium binary.
240
262
 
241
- While the module is in early access, only pre-rendered routes are supported.
263
+ You can do this by running `npx playwright install` within your build command.
242
264
 
243
- ```ts
244
- export default defineNuxtConfig({
245
- nitro: {
246
- prerender: {
247
- crawlLinks: true,
248
- routes: [
249
- '/',
250
- // any URLs that can't be discovered by crawler
251
- '/my-hidden-url'
252
- ]
253
- }
265
+ _package.json_
266
+
267
+ ```json
268
+ {
269
+ "scripts": {
270
+ "build": "npx playwright install && nuxt build"
254
271
  }
272
+ }
273
+ ```
274
+
275
+ # API
276
+
277
+ The module exposes a composition and component API to implement your `og:image` generation. You should pick
278
+ whichever one you prefer using.
279
+
280
+ ## OgImageStatic / defineOgImageStatic
281
+
282
+ The `OgImageStatic` component and the `defineOgImageStatic` composable creates a static image
283
+ that will be pre-rendered.
284
+
285
+ The options follow the [OgImageOptions](#OgImageOptions) interface,
286
+ any additional options will be passed to the `component` as props.
287
+
288
+ It is useful for images that do not change at runtime.
289
+
290
+ ### Example
291
+
292
+ ```vue
293
+ <script setup lang="ts">
294
+ // a. Composition API
295
+ defineOgImageStatic({
296
+ component: 'MyOgImageTemplate',
297
+ title: 'Hello world',
298
+ theme: 'dark'
255
299
  })
256
- ```
300
+ </script>
301
+ <template>
302
+ <!-- b. Component API -->
303
+ <OgImageStatic
304
+ component="MyOgImageTemplate"
305
+ title="Hello world"
306
+ theme="dark"
307
+ />
308
+ </template>
309
+ ```
257
310
 
258
- ## Module Config
259
311
 
260
- ### `host`
312
+ ## OgImageDynamic / defineOgImageDynamic
313
+
314
+ The `OgImageDynamic` component and the `defineOgImageDynamic` composable creates a dynamic image. They are not pre-rendered and will
315
+ be generated at runtime.
316
+
317
+ The options follow the [OgImageOptions](#OgImageOptions) interface,
318
+ any additional options will be passed to the `component` as props.
319
+
320
+ This feature is not compatible with static sites built using `nuxi generate`.
321
+
322
+ ### Example
323
+
324
+ ```vue
325
+ <script setup lang="ts">
326
+ const dynamicData = await fetch('https://example.com/api')
327
+
328
+ // a. Composition API
329
+ defineOgImageDynamic({
330
+ component: 'MyOgImageTemplate',
331
+ title: 'Hello world',
332
+ dynamicData,
333
+ })
334
+ </script>
335
+ <template>
336
+ <!-- b. Component API -->
337
+ <OgImageDynamic
338
+ component="MyOgImageTemplate"
339
+ title="Hello world"
340
+ :dynamicData="dynamicData"
341
+ />
342
+ </template>
343
+ ```
344
+
345
+
346
+ ## OgImageOptions
347
+
348
+ ### `alt`
261
349
 
262
350
  - Type: `string`
263
- - Default: `undefined`
351
+ - Default: `''`
352
+ - Required: `false`
353
+
354
+ The `og:image:alt` attribute for the image. It should describe the contents of the image.
355
+
356
+ ### `height`
357
+
358
+ - Type: `number`
359
+ - Default: `630`
264
360
  - Required: `true`
265
361
 
266
- The host of your site. This is required to generate the absolute path of the og:image.
362
+ The height of the screenshot. Will be used to generate the `og:image:height` meta tag.
267
363
 
268
- ## Screenshot Options
364
+ ### `width`
269
365
 
270
- These can be provided as module options to set defaults
271
- or set individually on the `OgImageScreenshot` or `OgImage` components or the `defineOgImage` or `defineOgImageScreenshot` composables.
366
+ - Type: `number`
367
+ - Default: `1200`
368
+ - Required: `true`
272
369
 
273
- ```ts
274
- // optionally set defaults globally
275
- export default defineNuxtConfig({
276
- ogImage: {
277
- colorScheme: 'dark',
278
- mask: '.screenshot-hidden'
279
- }
370
+ The width of the screenshot. Will be used to generate the `og:image:width` meta tag.
371
+
372
+ ### `component`
373
+
374
+ - Type: `string`
375
+ - Default: `OgImageBasic`
376
+ - Required: `true`
377
+
378
+ The name of the component to use as the template. By default, it uses OgImageBasic provided by the module.
379
+
380
+ ### `provider`
381
+
382
+ - Type: `string`
383
+ - Default: `satori`
384
+ - Required: `false`
385
+
386
+ The provider to use to generate the image. The default provider is `satori`.
387
+ When you use `browser` it will use Puppeteer to generate the image.
388
+
389
+ ### `prerender`
390
+
391
+ - Type: `boolean`
392
+ - Default: `true` when static, `false` when dynamic
393
+
394
+
395
+ ## OgImageScreenshot / defineOgImageScreenshot
396
+
397
+ The `OgImageScreenshot` component and the `defineOgImageScreenshot` composable creates a screenshot of a page using a browser.
398
+
399
+ The options follow the [ScreenshotsOptions](#ScreenshotsOptions) interface.
400
+
401
+
402
+ ### Example
403
+
404
+ ```vue
405
+ <script setup lang="ts">
406
+ // a. Composition API
407
+ defineOgImageScreenshot({
408
+ // wait for animations
409
+ delay: 1000,
280
410
  })
411
+ </script>
412
+ <template>
413
+ <!-- b. Component API -->
414
+ <OgImageScreenshot
415
+ url="https://example.com"
416
+ title="Hello world"
417
+ theme="dark"
418
+ />
419
+ </template>
281
420
  ```
282
421
 
283
- ### `colorScheme`
422
+ ### ScreenshotsOptions
423
+
424
+ This interface extends the [OgImageOptions](#OgImageOptions).
425
+
426
+ #### `colorScheme`
284
427
 
285
428
  - Type: `'dark' | 'light'`
286
- - Default: `undefined`
429
+ - Default: `light`
287
430
  - Required: `false`
288
431
 
289
432
  The color scheme to use when generating the image. This is useful for generating dark mode images.
@@ -294,27 +437,28 @@ defineOgImageScreenshot({
294
437
  })
295
438
  ```
296
439
 
297
- ### `selector`
440
+ #### `delay`
298
441
 
299
- - Type: `string`
300
- - Default: `undefined`
442
+ - Type: `number`
443
+ - Default: `0`
301
444
  - Required: `false`
302
445
 
303
- The selector to take a screenshot of. This is useful if you want to exclude header / footer elements.
446
+ The delay to wait before taking the screenshot. This is useful if you want to wait for animations to complete.
304
447
 
305
448
  ```ts
306
449
  defineOgImageScreenshot({
307
- mask: '.page-content'
450
+ // wait 2 seconds
451
+ delay: 2000
308
452
  })
309
453
  ```
310
454
 
311
- ### `mask`
455
+ #### `mask`
312
456
 
313
457
  - Type: `string`
314
458
  - Default: `undefined`
315
459
  - Required: `false`
316
460
 
317
- HTML selectors that should be removed from the image. Useful for removing popup banners or other elements that may be in the way.
461
+ HTML selectors that should be removed from the image. Useful for removing popup banners or other elements that may be in the way.
318
462
 
319
463
  ```ts
320
464
  defineOgImageScreenshot({
@@ -322,60 +466,88 @@ defineOgImageScreenshot({
322
466
  })
323
467
  ```
324
468
 
325
- ### `delay`
469
+ #### `selector`
326
470
 
327
- - Type: `number`
471
+ - Type: `string`
328
472
  - Default: `undefined`
329
473
  - Required: `false`
330
474
 
331
- The delay to wait before taking the screenshot. This is useful if you want to wait for animations to complete.
475
+ The selector to take a screenshot of. This is useful if you want to exclude header / footer elements.
332
476
 
333
477
  ```ts
334
478
  defineOgImageScreenshot({
335
- // wait 2 seconds
336
- delay: 2000
479
+ mask: '.page-content'
337
480
  })
338
481
  ```
339
482
 
340
- ### `alt`
483
+ ## Module Config
484
+
485
+ ### `host`
341
486
 
342
487
  - Type: `string`
343
- - Default: `Web page screenshot of {route}.`
488
+ - Default: `undefined`
489
+ - Required: `true`
490
+
491
+ The host of your site. This is required to generate the absolute path of the `og:image`.
492
+
493
+ ### `defaults`
494
+
495
+ - Type: `OgImageOptions`
496
+ - Default: `{ component: 'OgImageBasic', width: 1200, height: 630, }`
344
497
  - Required: `false`
345
498
 
346
- Used to generate the `og:image:alt` meta.
499
+ The default options to use when generating images.
347
500
 
348
- ### `width`
501
+ ### `forcePrerender`
349
502
 
350
- - Type: `number`
351
- - Default: `1200`
352
- - Required: `true`
503
+ - Type: `boolean`
504
+ - Default: `false`
505
+ - Required: `false`
353
506
 
354
- The default width of the image. This is useful if you want to generate a specific size image.
507
+ 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
508
+ runtime images.
355
509
 
356
- ```ts
357
- defineOgImageScreenshot({
358
- width: 1500
359
- })
360
- ```
510
+ ### `fonts`
361
511
 
362
- ### `height`
512
+ - Type: ``${string}:${number}`[]`
513
+ - Default: `['Inter:400', 'Inter:700']`
514
+ - Required: `false`
363
515
 
364
- - Type: `number`
365
- - Default: `630`
366
- - Required: `true`
516
+ Fonts families to use when generating images with Satori. When not using Inter it will automatically fetch the font from Google Fonts.
367
517
 
368
- The default height of the image. This is useful if you want to generate a specific size image.
518
+ For example, if you wanted to add the Roboto font, you would add the following:
369
519
 
370
520
  ```ts
371
- defineOgImageScreenshot({
372
- height: 700
521
+ export default defineNuxtConfig({
522
+ ogImage: {
523
+ fonts: ['Roboto:400', 'Roboto:700']
524
+ }
373
525
  })
374
526
  ```
375
527
 
528
+ ### `satoriOptions`
529
+
530
+ - Type: `SatoriOptions`
531
+ - Default: `{}`
532
+ - Required: `false`
533
+
534
+ Options to pass to Satori when generating images. See the [Satori docs](https://github.com/vercel/satori).
535
+
536
+ ### `experimentalNitroBrowser` (experimental)
537
+
538
+ - Type: `boolean`
539
+ - Default: `false`
540
+ - Required: `false`
541
+
542
+ In a server runtime, the default behaviour is to generate images using Satori. If you'd like to generate runtime images using the a browser instance
543
+ for screenshots, you can enable this setting.
544
+
545
+ This is experimental and may not work in all environments.
546
+
376
547
  ## Examples
377
548
 
378
549
  - [Unhead Docs](https://github.com/unjs/unhead/tree/main/docs)
550
+ - [harlanzw.com](https://github.com/harlan-zw/harlanzw.com)
379
551
 
380
552
  ## Sponsors
381
553