Choose your stack and follow these simple steps to start generating og images.
Add the HeadShard script to your document's head or layout.
import Script from "next/script";
const Layout = ({ children }: { children: React.ReactNode }) => (
<>
{/* there is not really a point in loading the script in production */}
{process.env.NODE_ENV === "development" && (
<Script src="https://magic.headshard.com/latest.js" async />
)}
{children}
</>
);
export default Layout;
Add the data-og-template attribute to any HTML element you want to capture.
// convenience component
const Template = async ({
children,
...props
}: { children: React.ReactNode } & React.ComponentPropsWithoutRef<"template">) => {
// https://github.com/vercel/next.js/issues/43810
// https://github.com/vercel/next.js/discussions/69244
const ReactDOMServer = (await import("react-dom/server")).default;
// https://stackoverflow.com/questions/42845195/how-can-i-render-a-template-tag-with-react
return (
<template
{...props}
dangerouslySetInnerHTML={{ __html: ReactDOMServer.renderToString(children) }}
></template>
);
};
const Page = () => (
<>
<Template data-og-template>
<div className="flex items-center justify-center size-full">
<h1 className="text-4xl font-bold">Hello World</h1>
</div>
</Template>
{/* your page content */}
</>
);
export default Page;
Visit your page with the query parameter to see the magic happen. Design your OG image in real-time with HOT-reloading until you are happy with the result.
Pass the URL of the page you want to render the OG image for to the HeadShard endpoint and you will get the exact image as in the preview.
export const generateMetadata = async () => {
return {
// title: product.title,
// ...
openGraph: {
images: [
`https://magic.headshard.com/img/${process.env.HEADSHARD_PUBLISHABLE_API_KEY}.webp?url=https://your-domain.com/path/to/page`,
],
},
};
};