{"id":13761842,"url":"https://github.com/neg4n/next-api-og-image","last_synced_at":"2025-04-05T21:07:51.134Z","repository":{"id":38403533,"uuid":"412505357","full_name":"neg4n/next-api-og-image","owner":"neg4n","description":":bowtie: Easy way to generate open-graph images dynamically  in HTML or React using Next.js API Routes. Suitable for serverless environment.","archived":false,"fork":false,"pushed_at":"2022-09-24T15:03:51.000Z","size":1137,"stargazers_count":216,"open_issues_count":10,"forks_count":18,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-02T02:41:52.643Z","etag":null,"topics":["hacktoberfest","html","html-templates","html5","jsx","jsx-syntax","next","nextjs","nextjs-api-routes","nextjs-middleware","nextjs-plugin","nextjs-serverless","react","react-hooks","reactjs","serverless","typescript","vercel"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/next-api-og-image","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/neg4n.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-10-01T14:45:26.000Z","updated_at":"2025-01-04T02:37:08.000Z","dependencies_parsed_at":"2022-08-09T03:16:40.127Z","dependency_job_id":null,"html_url":"https://github.com/neg4n/next-api-og-image","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neg4n%2Fnext-api-og-image","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neg4n%2Fnext-api-og-image/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neg4n%2Fnext-api-og-image/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neg4n%2Fnext-api-og-image/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/neg4n","download_url":"https://codeload.github.com/neg4n/next-api-og-image/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247399877,"owners_count":20932876,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","html","html-templates","html5","jsx","jsx-syntax","next","nextjs","nextjs-api-routes","nextjs-middleware","nextjs-plugin","nextjs-serverless","react","react-hooks","reactjs","serverless","typescript","vercel"],"created_at":"2024-08-03T14:00:30.207Z","updated_at":"2025-04-05T21:07:51.118Z","avatar_url":"https://github.com/neg4n.png","language":"TypeScript","funding_links":[],"categories":["Nextjs Plugins","TypeScript"],"sub_categories":[],"readme":"# Next.js API OG Image \u0026middot; [![version](https://badgen.net/npm/v/next-api-og-image)](https://www.npmjs.com/package/next-api-og-image) [![types](https://badgen.net/npm/types/next-api-og-image)](https://www.npmjs.com/package/next-api-og-image) [![license](https://badgen.net/npm/license/next-api-og-image)](https://github.com/neg4n/next-api-og-image/blob/main/LICENSE)\n\nSimple library with purpose of providing easy way to dynamically  \ngenerate open-graph images using [Next.js API routes][next-api-routes].\n\nIf you're not familiar with dynamic open-graph images concept - please see [vercel/og-image repository's README][vercel-og-image] for very detailed explaination.\n\n_you can treat this project as simpler and configurable version of mentioned earlier [vercel][vercel] repository_\n\n## Features\n\n- [x] 🐄 Super easy usage\n- [x] 🌐 Suitable for [serverless][vercel-serverless] environment\n- [x] :bowtie: Elegant way for defining templates both in [React][react] and [HTML][html]\n- [x] 📬 Multiple strategies - pass values by GET and query params or POST and JSON body\n- [x] 🥷 TypeScript compatible\n\n## Installing\n\nIn your [Next.js][next-homepage] project, execute:\n\n```sh\nnpm i next-api-og-image chrome-aws-lambda\n# or\nyarn add next-api-og-image chrome-aws-lambda\n```\n\n### Short note about the peer dependencies\n\n\u003e ℹ️ If your serverless function does not fit in the allowed size frames on [Vercel][vercel] **(50MB)**, you may want to install older versions of `chrome-aws-lambda`\n\nIn order to do so, replace `chrome-aws-lambda` _(while adding the dependencies)_ with `chrome-aws-lambda@6.0.0` **(47.6 MB)**\n\nPlease, refer to https://github.com/neg4n/next-api-og-image/issues/23#issuecomment-1090319079 for more info 🙏\n\n## Examples\n\nYou can find more examples here:\n\n- JavaScript\n  - [Basic usage with JavaScript][basic]\n  - [Basic usage with Styled Components][basic-styled]\n  - [Basic usage with TailwindCSS][basic-tailwind]\n  - [Basic usage with React template provided][basic-react]\n  - [Basic usage with loading custom local fonts][basic-fonts-local]\n- TypeScript\n  - [Basic usage with TypeScript][basic-typescript]\n  - [Basic usage with TypeScript and React using query strategy][basic-typescript-react-query]\n  - [Basic usage with TypeScript and React using body strategy][basic-typescript-react-json] (JSON)\n  - [Advanced usage with TypeScript, React template and custom local fonts][advanced-typescript-react]\n\n_the `example/` directory contains simple [Next.js][next-homepage] application implementing `next-api-og-image` . To fully explore examples implemented in it by yourself - simply do `npm link \u0026\u0026 cd example \u0026\u0026 npm i \u0026\u0026 npm run dev` then navigate to http://localhost:3000/_\n\n## Basic usage and explaination\n\n##### HTML template\n\n```js\nimport { withOGImage } from 'next-api-og-image'\n\nexport default withOGImage({ template: { html: ({ myQueryParam }) =\u003e `\u003ch1\u003e${myQueryParam}\u003c/h1\u003e` } })\n```\n\n##### React template\n\n```js\nimport { withOGImage } from 'next-api-og-image'\n\nexport default withOGImage({ template: { react: ({ myQueryParam }) =\u003e \u003ch1\u003e{myQueryParam}\u003c/h1\u003e } })\n```\n\n## Creating template\n\nYou've may noticed the `html` and `react` properties in configuration. Their responsibility is to provide HTML document to image creator _(browser screenshot)_, filled with your values.\n\n\u003e **⚠️ NOTE**  \n\u003e Template **cannot be ambigious**. You must either  \n\u003e define `react` or `html`. Never both at once\n\n### Specification\n\nThe `html` and `react` properties are template providers functions. Each function's first (and only) parameter is nothing else but [HTTP request's query params][query-params] converted to object notation.\n\nThis allows you to create fully customized HTML templates by simply accessing these parameters. The preferred way to do that is [object destructuring][object-destructuring].\n\n\u003e **⚠️ NOTE**  \n\u003e `html` and `react` template provider functions  \n\u003e **can be defined as asynchronous**\n\n#### Examples\n\n##### HTML template\n\n```js\nimport { withOGImage } from 'next-api-og-image'\n\nexport default withOGImage({ template: { html: ({ myQueryParam }) =\u003e `\u003ch1\u003e${myQueryParam}\u003c/h1\u003e` } })\n```\n\n##### React template\n\n```js\nimport { withOGImage } from 'next-api-og-image'\n\nexport default withOGImage({ template: { react: ({ myQueryParam }) =\u003e \u003ch1\u003e{myQueryParam}\u003c/h1\u003e } })\n```\n\n_if you send GET HTTP request to [api route][next-api-routes] with code presented above e.g. `localhost:3000/api/foo?myQueryParam=hello` - it will render heading with content equal to 'hello'_\n\n### Strategies\n\n`next-api-og-image` allows you to choose strategy for providing values to the template. The available strategies are:\n\n1. `query` _(default)_ - values are passed by query params and GET HTTP request.  \n   **These values ⛔️ cannot be nested nor accessed by nested destructuring in template provider function**.\n\n2. `body` - values are passed by POST HTTP request and JSON body.  \n   These values ✅ can be nested and accessed by nested destructuring in template provider function.\n\nThe strategies are determined by `strategy` prop in the configuration. Default strategy is `query`.\n\n\u003e **⚠️ NOTE**  \n\u003e Regardless of the strategy - all properties (every single one)  \n\u003e **are implicitly casted to string, even very long JSON's nested values**\n\n#### Types in template provider function\n\nIf you're using TypeScript, you probably want to have these things\ntyped. Well... its actually super easy! Simply add generic types to `withOGImage` function.\n\n1. typed `query` strategy with query params `?foo=hello\u0026bar=friend` will look like this:\n   ```js\n   export default withOGImage\u003c'query', 'foo' | 'bar'\u003e(/* ... */)\n   ```\n2. typed `body` strategy with JSON payload `{ \"foo\": \"hello\", \"imNested\": { \"bar\": \"friend\" }}` will look like this:\n   ```js\n   export default withOGImage\u003c'body', { foo: string, imNested: { bar: string } }\u003e({ strategy: 'body', /* ... */ })\n   ```\n\n#### Errors\n\nWhen strategy is set to `query` and you're sending POST HTTP request with JSON body or when strategy is set to `body` and you're sending GET HTTP request with query params - `next-api-og-image` will:\n\n1. Will throw an runtime error\n2. Set appropiate response message to the client\n   You can disable this behaviour by setting `dev: { errorsInResponse: false }` in the configuration\n\n### Hooking the post-generate process\n\nIn some scenarios you may want to do something _(in other words - execute some logic)_ **after generation of the image**.\nThis can be easily done by providing function to `hook` configuration property. The only parameter is `NextApiRequest` object with `image` attached to it.\n\nexample (JavaScript):\n\n```js\nimport { withOGImage } from 'next-api-og-image'\n\nexport default withOGImage({\n  template: {\n    react: ({ myQueryParam }) =\u003e \u003cdiv\u003e🔥 {myQueryParam}\u003c/div\u003e,\n  },\n  dev: {\n    inspectHtml: false,\n  },\n  hook: (innerRequest) =\u003e {\n    console.log(innerRequest.image)\n    // will print the generated image on the server as Buffer\n  },\n})\n```\n\n### Splitting files\n\nKeeping all the templates inline within [Next.js API route][next-api-routes] should not be problematic, but if you prefer keeping things in separate files you can follow the common pattern of creating files like `my-template.html.js` or `my-template.js` when you define template as react _(naming convention is fully up to you)_ with code e.g.\n\n```js\nexport default function myTemplate({ myQueryParam }) {\n  return `\u003ch1\u003e${myQueryParam}\u003c/h1\u003e`\n}\n```\n\n...or in TypeScript\n\n```ts\nimport type { NextApiOgImageQuery } from 'next-api-og-image'\n\ntype QueryParams = 'myQueryParam'\nexport default function myTemplate({ myQueryParam }: Record\u003cQueryParams, string\u003e) {\n  return `\u003ch1\u003e${myQueryParam}\u003c/h1\u003e`\n}\n```\n\nthen importing it and embedding in the `withOGImage`.\n\n### Loading custom local fonts\n\nIn order to load custom fonts from the project source, you need to create source file with your font in **base64** format or simply bind the font file content to the variable in your [Next.js API route][next-api-routes]\n\n## Configuration\n\nApart from `html` and `react` configuration property (in `template`) _(whose are required)_, you can specify additional info about how `next-api-og-image` should behave.\n\nExample configuration with **default values** _(apart from template.html or template.react prop)_:\n\n```js\nconst nextApiOgImageConfig = {\n  // Values passing strategy\n  strategy: 'query',\n  // Response's 'Content-Type' HTTP header and browser screenshot type.\n  type: 'png',\n  // Screenshot's quality. WORKS ONLY IF 'type' IS SET TO 'jpeg'\n  quality: 90,\n  // Width of the image in pixels\n  width: 1200,\n  // Height of the image in pixels\n  height: 630,\n  // 'Cache-Control' HTTP header\n  cacheControl: 'max-age 3600, must-revalidate',\n  // Hook function that allows to intercept inner NextApiRequest with `ogImage` prop attached.\n  // useful for e.g. saving image in the database after the generation.\n  // The hook function return is Map containing custom headers that will be set BEFORE sending\n  // response to the client.\n  hook: null,\n  // NOTE: Options within 'chrome' object only works when next-api-og-image is run in server (not serverless!!) environment.\n  chrome: {\n    // Custom command-line args passed to the browser start command\n    // by default, no arguments are provided.\n    args: null,\n    // Custom executable provided. Useful when you e.g. have to run Chromium instead of Google Chrome\n    // by default, executable is retrieved automatically (it looks for Google Chrome in the filesystem)\n    executable: null,\n  }\n  // NOTE: Options within 'dev' object works only when process.env.NODE_ENV === 'development'\n  dev: {\n    // Whether to replace binary data (image/screenshot) with HTML\n    // that can be debugged in Developer Tools\n    inspectHtml: true,\n    // Whether to set error message in response\n    // if there are strategy related errors\n    errorsInResponse: true,\n  },\n}\n```\n\n## License\n\nThis project is licensed under the MIT license.  \nAll contributions are welcome.\n\n[next-homepage]: https://nextjs.org/\n[react]: https://reactjs.org\n[html]: https://en.wikipedia.org/wiki/HTML\n[object-destructuring]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#object_destructuring\n[query-params]: https://en.wikipedia.org/wiki/Query_string\n[vercel-serverless]: https://vercel.com/docs/concepts/functions/introduction\n[vercel]: https://vercel.com/\n[vercel-og-image]: https://github.com/vercel/og-image#readme\n[next-api-routes]: https://nextjs.org/docs/api-routes/introduction\n[content-type]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type\n[cache-control]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control\n[basic-typescript]: https://github.com/neg4n/next-api-og-image/tree/main/example/pages/api/basic-typescript.ts\n[basic-tailwind]: https://github.com/neg4n/next-api-og-image/tree/main/example/pages/api/basic-tailwind.js\n[basic-styled]: https://github.com/neg4n/next-api-og-image/tree/main/example/pages/api/basic-styled-components.js\n[basic-react]: https://github.com/neg4n/next-api-og-image/tree/main/example/pages/api/basic-react.js\n[basic]: https://github.com/neg4n/next-api-og-image/tree/main/example/pages/api/basic.js\n[basic-fonts-local]: https://github.com/neg4n/next-api-og-image/tree/main/example/pages/api/basic-custom-fonts-local.js\n[advanced-typescript-react]: https://github.com/neg4n/next-api-og-image/tree/main/example/pages/api/advanced-typescript-react.tsx\n[basic-typescript-react-query]: https://github.com/neg4n/next-api-og-image/tree/main/example/pages/api/basic-typescript-react-query.tsx\n[basic-typescript-react-json]: https://github.com/neg4n/next-api-og-image/tree/main/example/pages/api/basic-typescript-react-json.tsx\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneg4n%2Fnext-api-og-image","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneg4n%2Fnext-api-og-image","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneg4n%2Fnext-api-og-image/lists"}