UNPKG

next-banner

Version:

Generate Open Graph images for Next.js on build

198 lines (135 loc) 5.29 kB
![Logo](banner.png) # Next Banner Generate Open Graph images (og:image) at build using Puppeteer. ## What is an Open Graph image? Open Graph is a protocol for structured metadata for websites. Part of that is a specification for preview images referred to as "og:image". When using that, your website gets a nice preview in social media and messaging apps. For an example, check out [ogimage.gallery](https://www.ogimage.gallery/). ## Why this library? You might just design images in Figma. This is doable, but quickly becomes tedious if you have a lot of pages (like blog posts) or want to change the design. Generating images is much more effective. Most currently existing solutions run on-demand either in a serverless function or in a service. This is wasteful and could be expensive if demand is high. For example, cold starting Puppeteer to take a screenshot of the page can take 8s per visitor. To counteract this, a CDN can be used, which further increases the amount of things needing setup. With next-banner, none of that is needed. In true Jamstack fashion, this library generates images at build, using existing infrastructure that you already have. ## Features - **Speed.** It uses Puppeteer to render pages, but only on instance, meaning there is only one cold start. On an M1, 100 pages are rendered and captured in 18s. - **Simple setup.** Does not require you to touch Puppeteer, CDNs, or serverless functions. - **Render using React.** Your images are captured pages that you code in React just like you are used to. No SVGs or special template languages. - **Multiple layouts.** You could have one layout for a start page and another for blog posts. - **Pass any data.** Page title and meta description is passed to the layout pages by default, but you can include any data in any structure you want. ## Usage ### Installation Use npm or yarn ```bash npm install next-banner yarn add next-banner ``` Add this to your scripts in package.json ```json "postbuild": "next-banner", ``` ### Configuration Edit `next.config.js` to wrap wrap the config with `withNextBanner`. The domain property is needed for some social media sites to render the images. ```js const { withNextBanner } = require("next-banner"); module.exports = withNextBanner({ nextBanner: { domain: "example.com", }, // ... normal Next.js config here. }); ``` ### Meta provider You also need to wrap your `_app` with `<NextBannerMeta>` like below. This ads `og:image` tags to every page and automatically points them to the generated images. ```jsx import { NextBannerMeta } from "next-banner"; function MyApp({ Component, pageProps }: AppProps) { return ( <NextBannerMeta> <Component {...pageProps} /> </NextBannerMeta> ); } ``` ### Layout files Create a folder called `next-banner-layouts/` in your `pages/` folder. Then create a file called `default.js` there and add the following code: ```js import { Template } from "next-banner"; export default Template; ``` ### Custom layouts To use a custom layout you first need to declare that a page should render another layout using hte `setBannerData` hook. pages/post.jsx ```jsx import { setBannerData } from "next-banner"; function PostPage() { setBannerData({ layout: "post" // This is the name of the layout file. }) return ( ... ) } ``` Then you need a layout file. Notice the default (`=`) parameters in the destructuring. This helps during local development. In production, the hook will return the real data. But locally, data has not been extracted from the pages. pages/next-banner-layouts/post.jsx ```jsx export default function PostLayout() { const { meta: { title = "Placeholder title", description = "Placeholder description" } } = useBannerData(); return ( <ScreenshotCanvas> <div style={{ display: "flex", flexDirection: "row", alignItems: "center", gap: "20px", marginBlockEnd: "30px", }} > <img src="/favicon.ico" alt="" style={{ marginBottom: "70px" }} /> <div> <h1 style={{ fontSize: "5em" }}>{title}</h1> <h2 style={{ fontSize: "2em" }}>{description}</h2> </div> </div> </ScreenshotCanvas> ); } ``` ### Custom data If you want to add any extra data besides the meta title and description, you can do so with a the `setBannerData` on the normal (non-layout) page. ```jsx import { setBannerData } from "next-banner"; function ImagePage() { setBannerData({ custom: { image: "https://example.com/image.jpg" } }) } ``` It can then be accessed in layout files using `useBannerData`. ```jsx import { useBannerData } from "next-banner" function ImageLayout() { const { custom: { image } } = useBannerData() return ( ... // Your layout here. ) } ``` ## Example There is an example showcasing usage [here](/example) ## License [MIT](LICENSE) ## Contributing Contributions are always welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for ways to get started. ## Feedback If you have any feedback, please [create an issue](https://github.com/alvarlagerlof/next-banner/issues/new) reach me on [twitter](https://twitter.com/alvarlagerlof).