Code Monkey home page Code Monkey logo

neg4n / next-api-og-image Goto Github PK

View Code? Open in Web Editor NEW
216.0 1.0 18.0 1.11 MB

:bowtie: Easy way to generate open-graph images dynamically in HTML or React using Next.js API Routes. Suitable for serverless environment.

Home Page: https://www.npmjs.com/package/next-api-og-image

License: MIT License

TypeScript 84.31% JavaScript 15.69%
nextjs nextjs-plugin react nextjs-serverless nextjs-api-routes nextjs-middleware next serverless hacktoberfest vercel

next-api-og-image's People

Contributors

bmstefanski avatar neg4n avatar snelsi avatar transitive-bullshit avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

next-api-og-image's Issues

Suggestion: move chrome-aws-lambda to peer dependency

Since the most recent version of chrome-aws-lambda is 49.7 MB, it leaves almost no room for additional client libs in the vercel lambda.

I've been running into this issue and it's really frustrating.

So my proposal is to switch chrome-aws-lambda to be a peer dependency and allow the user of this library to choose which chrome version they want to use.

See my other comment here for the savings we're talking about: #23 (comment)

This would require also making puppeteer-core a peer dependency, since the two versions need to match up.

using react templates outputs a string, not an image

Template type produces different outputs when hitting the API.

export default withOGImage({
  template: {
    html: ({ id }) => `
      <html>
        <head>
          <link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
        </head>
        <body>
        <Sigil patp=${id} size={100}/>
          <h1 class="flex flex-row text-6xl text-blue-300">${id}<span>💻</span></h1>
        </body>
      </html>
    `,
  },
});

Produces an image.

export default withOGImage({
  template: {
    react: ({ myQueryParam }) => <div>🔥 {myQueryParam}</div>,
  },
});

Produces a text document. <div style={{color: 'blue'}}> for example produces blue text, so it isn't source code necessarily.

Live example

Hi, is there a live example I could visit to check how the library works?
Also, it would prove the fact that this library can be deployed on Vercel without exceeding their quota :D
Let me know what you think and if I can help with something 😄

Change image resolution / page viewport

Hi 👋

I just came across this lib, which is just a better implementation of the one I had 😄
I think it would be useful to have a width and height option, to specify the image resolution, no? Just an idea!

Failed to launch browser process

My version is already "next-api-og-image": "^4.3.0". It runs fine locally, but it gives an error on Vercel. I've seen many comments suggesting that downgrading the node version is a good solution. However, Vercel no longer supports Node 14.

[GET] /api/ogImage?name=rotterdame&creator=schwarzskra 17:16:38:27 2022-08-07T14:16:42.986ZERROR Error: Failed to launch the browser process! /tmp/chromium: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory

Contributing guidelines

Create contribution guidelines for fellow open sourcerers that want to take part in next-api-og-image development 🔥

Add option to override default chrome executable and arguments

I'm trying to use this package in production, but I have an issue with setting up the environment:

Error: Failed to launch the browser process!
[0914/172601.987555:ERROR:zygote_host_impl_linux.cc(90)] Running as root without --no-sandbox is not supported. See https://crbug.com/638180.
ROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md

Sadly, there's no way to specify chrome executable arguments. It would be nice if there was some option for it. It is also not hard to imagine that someone might need to override default executable (for example if someone runs multiple versions of chrome on same machine), so there could be also option for that.

Simplify source code

The source code of next-api-og-image is needlessly complicated in many places. The goal is to make it simple without modifying the library's API.

Failed to launch browser process

My version is already "next-api-og-image": "^4.2.1", in local running fine but in Vercel gives error

[GET] /api/ogImage?name=rotterdame&creator=schwarzskra
17:16:38:27
2022-08-07T14:16:42.986ZERROR	Error: Failed to launch the browser process!
/tmp/chromium: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory

Failed to launch the browser process

image
Getting this error

Code Snippet

// ./api/og.js

import { withOGImage } from 'next-api-og-image';

export default withOGImage({
  template: { react: ({ title }) => <h1>{title}</h1> },
  dev: {
    inspectHtml: true,
  },
});

Happens when I enter /api/og?title=Hi

Running in Brave Browser
I have installed chrome as well but the path is different.

Wait for webfont load?

This thing is amazing.

Is it possible to have it wait for webfonts or should I strictly embed them?

Add example with React component

As I mentioned in my previous comment, I've seen many implementations of og-image in Next.js & kept a bookmark. Before this, I was gonna go with https://dominik.sumer.dev/blog/how-to-use-react-to-generate-og-images

It has a section where the author uses a React component. I think a React.js component would be more ideal as we are working with Next.js.

This would also allow for an easier preview with HMR. I am assuming the new dev mode doesn't allow HMR. Lmk if I'm wrong about that :)

Error 500 & Content Blocker Issue

Hey there,

I'm using the basic JS example (placed in the Next.JS API route). In both Chrome and Safari, I get a content block error. This only occurs in production (hosted on Vercel), localhost loads fine.

Chrome Error: Failed to load resource: net::ERR_BLOCKED_BY_CLIENT

Safari Error: Content blocker prevented frame displaying ... from loading a resource from https://p.typekit.net/p.css?s=1&...

Code I'm using:

import { withOGImage } from 'next-api-og-image'

export default withOGImage({
  template: {
    react: ({ title }) => <div>🔥 {title}</div>,
  },
})

Dependencies in package.json:

"dependencies": {
    "mongodb": "^4.9.0",
    "next": "12.2.3",
    "next-api-og-image": "^4.3.0",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-markdown": "^8.0.3",
    "react-query": "^3.39.2",
    "socket.io-client": "^4.5.1"
  },
  "devDependencies": {
    "@types/socket.io": "^3.0.2",
    "autoprefixer": "^10.4.8",
    "eslint": "8.21.0",
    "eslint-config-next": "12.2.3",
    "postcss": "^8.4.14",
    "sass": "^1.54.5",
    "tailwindcss": "^3.1.7"
  }

Thank you in advance!

Download the image

I've been trying to get it to work but having unfortunate errors.

My api/og-image.ts looks like:

import React from 'react'
import ReactDOM from 'react-dom/server'
import { withOGImage } from 'next-api-og-image'

import OGImagePreview from '@/pages/og-image-preview'
import { OGImage, Author } from '@/types/index'

const html = async ({
	title,
	description,
	date,
	readingTime,
	slug,
	authors,
}: Record<keyof OGImage, string | string[] | any[]>): Promise<string> => {
	const el = React.createElement(OGImagePreview, {
		title: title as string,
		description: description as string,
		date: date as string,
		readingTime: readingTime as string,
		slug: slug as string,
		authors: authors as Author[],
	})

	const body = ReactDOM.renderToStaticMarkup(el)

	const baseCSS = `
		.font-alegreya {
			font-family: Alegreya;
		}
		.font-jetbrains {
			font-family: 'JetBrains Mono';
		}
	`

	return `
		<html>
			<head>
				<meta charset="utf-8" />
				<link rel="preconnect" href="https://fonts.googleapis.com" />
				<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="true" />
				<link
					href="https://fonts.googleapis.com/css2?family=Alegreya:wght@800&display=swap"
					rel="stylesheet"
				/>
				<link
					href="https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap"
					rel="stylesheet"
				/>
				<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet" />
				<style>${baseCSS}</style>
			</head>
			<body>
				${body}
			</body>
			<script src="https://unpkg.com/tailwindcss-jit-cdn"></script>
		</html>
	`
}

const nextApiOgImageConfig = {
	// 'Content-Type' HTTP header
	contentType: 'image/png',
	// 'Cache-Control' HTTP header
	cacheControl: 'max-age 3600, must-revalidate',
	// NOTE: Options within 'dev' object works only when process.env.NODE_ENV === 'development'
	dev: {
		// Whether to replace binary data (image/screenshot) with HTML
		// that can be debugged in Developer Tools
		inspectHtml: true,
	},
	html,
}

export default withOGImage<keyof OGImage>(nextApiOgImageConfig)

How do I download the image itself?

I was trying to use simple fetch & also ky but not sure how to download it:

import ky from 'ky'

import {
	getAllEssays,
	getAllTutorials,
	getAllSnippets,
	getAllTips,
	getEssayBySlug,
	getTutorialBySlug,
	getSnippetBySlug,
	getTipBySlug,
} from '@/utils/mdx'
import { siteMetadata } from '@/_data/index'

const { siteUrl } = siteMetadata

export const generateOGImage = () => {
	try {
		const essays = getAllEssays()
		const tutorials = getAllTutorials()
		const snippets = getAllSnippets()
		const tips = getAllTips()

		essays.forEach(async ({ slug }) => {
			const { meta, code } = await getEssayBySlug(slug)
			const { title, description = '', date, readingTime, authors } = meta
			let data = new URLSearchParams()
			data.append('title', title)
			data.append('description', description)
			data.append('date', JSON.stringify(date))
			data.append('readingTime', JSON.stringify(readingTime))
			data.append('slug', slug)
			data.append('authors', JSON.stringify(authors))

			const options = {
				method: `POST`,
				body: data,
			}

			fetch(`${siteUrl}/api/og-image`, options)
				.then((data) => {
					if (!data.ok) throw data

					console.log(data.body)
				})
				.catch((error) => {
					console.error(error)
				})

			const json = await ky
				.post('api/og-image', {
					prefixUrl: siteUrl,
					json: {
						title: meta.title,
						description: meta.description,
						date: meta.date,
						readingTime: meta.readingTime,
					},
				})
				.json()
			console.log(json)
		})
	} catch (e) {
		console.error(e)
	} finally {
	}
}

I want the image from this API to be downloaded. How do I do it?

Failed to launch the browser process!

I get this error when I start my next app with yarn dev

error - Error: Failed to launch the browser process! spawn C:\Program Files (x86)\Google\Chrome\Application\chrome.exe ENOENT

I have chrome installed on my system but its, not in the path printed in the error. It is in the 64bit folder. C:\Program Files\Google\Chrome\Application

My ENV

  • Node 16.1.0.0
  • Next 12.1.0
  • chrome-aws-lambda 1.6.3
  • Windows

Add example with Tailwind

Awesome work! Love how simple it is. I've checked every existing solution & this feels simplest.

I would love to have something like Bannerbear which creates dynamic previews & I love to style in Tailwind so would love it if I can get a template like Tailwind.

Query type for defining templates outside the withOGImage

Yeah. Thats probably because of noImplicitAny. By the way there should be query type exported from next-api-og-image since now it is not possible to have function outside withOGImage call scope with types, because inferring does not work and results in error that you had - implicit any.

Originally posted by @neg4n in #7 (comment)

TypeScript example not working

I modified the TypeScript example a little bit like this:

import { withOGImage, NextApiOgImageConfig } from 'next-api-og-image'

interface IHTML {
	heading: NextApiOgImageConfig<'heading'>
}

const html = async ({ heading }: IHTML) => {
	return `
		<html>
			<head>
				<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
			</head>
			<body>
				<h1>${heading}</h1>
			</body>
		</html>
	`
}

const nextApiOgImageConfig = {
	// 'Content-Type' HTTP header
	contentType: 'image/png',
	// 'Cache-Control' HTTP header
	cacheControl: 'max-age 3600, must-revalidate',
	// NOTE: Options within 'dev' object works only when process.env.NODE_ENV === 'development'
	dev: {
		// Whether to replace binary data (image/screenshot) with HTML
		// that can be debugged in Developer Tools
		inspectHtml: true,
	},
	html,
}

export default withOGImage<'heading'>(nextApiOgImageConfig)

And it's not working. I get an error on the last line on nextApiOgImageConfig saying:

Argument of type '{ contentType: string; cacheControl: string; dev: { inspectHtml: boolean; }; html: ({ heading }: IHTML) => Promise<string>; }' is not assignable to parameter of type 'NextApiOgImageConfig<"heading">'.
  Types of property 'html' are incompatible.
    Type '({ heading }: IHTML) => Promise<string>' is not assignable to type '(...queryParams: Record<"heading", string | string[]>[]) => string | Promise<string>'.
      Types of parameters '__0' and 'queryParams' are incompatible.
        Type 'Record<"heading", string | string[]>' is not assignable to type 'IHTML'.
          Types of property 'heading' are incompatible.
            Type 'string | string[]' is not assignable to type 'NextApiOgImageConfig<"heading">'.
              Type 'string' is not assignable to type 'NextApiOgImageConfig<"heading">'.ts(2345)

How do I fix that?

Unit tests

It would be great if next-api-og-image had 100% test coverage.

Some notes about tests:

  • We should use jest
  • There should be previously generated images in __stubs__ directory
    in order to set up further binary image output assertions
  • We should probably use supertest

Error: Could not find expected browser (chrome) locally. Run `npm install` to download the correct Chromium revision (901912).

Error: Could not find expected browser (chrome) locally. Run npm install to download the correct Chromium revision (901912).

when build example and start, errors are occurred.
'npm run dev' is ok, but 'npm run build' and 'npm run start' has problem.

reproduce steps

  1. clone this project
  2. npm install
  3. cd example && npm install

after I encountered errors bellow
`It looks like you're trying to use TypeScript but do not have the required package(s) installed.

Please install @types/react by running:`

so i installed @types/react and upgrade next, react
4. npm install --save-dev @types/react && npm install next@latest && npm upgrade react@latest react-dom@latest

  1. npm build && npm start
  2. browser open and go to url http://localhost:3000/api/basic?myQueryParam=asdf

[Bug] Could not find expected browser (chrome) locally after `next start`

Environment

next-api-og-image: 2.1.1
next: 11.1.2 / 12.0.4
node: 16.13.0

MacOS 12.0.1 (M1 Chip)
VS Code

Bug Description

This package works fine in dev mode when using next dev. But if I try to run next build & next start I'm getting this error when trying to access the API route:

Error: Could not find expected browser (chrome) locally. Run `npm install` to download the correct Chromium revision (901912).
    at ChromeLauncher.launch (/Users/romanzhuravlov/Documents/GitHub/next-api-og-image/example/node_modules/puppeteer-core/lib/cjs/puppeteer/node/Launcher.js:88:27)
    at async Object.apiResolver (/Users/romanzhuravlov/Documents/GitHub/next-api-og-image/example/node_modules/next/dist/server/api-utils.js:101:9)
    at async Server.handleApiRequest (/Users/romanzhuravlov/Documents/GitHub/next-api-og-image/example/node_modules/next/dist/server/next-server.js:770:9)
    at async Object.fn (/Users/romanzhuravlov/Documents/GitHub/next-api-og-image/example/node_modules/next/dist/server/next-server.js:661:37)
    at async Router.execute (/Users/romanzhuravlov/Documents/GitHub/next-api-og-image/example/node_modules/next/dist/server/router.js:205:32)
    at async Server.run (/Users/romanzhuravlov/Documents/GitHub/next-api-og-image/example/node_modules/next/dist/server/next-server.js:841:29)
    at async Server.handleRequest (/Users/romanzhuravlov/Documents/GitHub/next-api-og-image/example/node_modules/next/dist/server/next-server.js:292:20)

Tried both with my own project and examples from the repo example folder.

npm install doesn't help:

Снимок экрана 2021-11-24 в 16 00 45

Fix behaviour of checkStrategy()

Currently the checkStrategy() function throws error if no query is provided. This should not happen since its not really an error behavior

Also there seems to be bug in here:

response.json({ message })

because it clearly ignores the errorsInResponse configuration property

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.