Hono Open Graph Meta Tags: Add OG to Your Hono App

How to add og:title, og:image, og:description, and Twitter card meta tags in a Hono app — deployed on Cloudflare Workers, Bun, Node.js, or any edge runtime.

Basic HTML response with OG meta tags

Hono's html helper makes it easy to return server-rendered HTML with OG meta tags embedded directly in the <head>:

// src/index.ts
import { Hono } from 'hono';
import { html } from 'hono/html';

const app = new Hono();

app.get('/blog/:slug', async (c) => {
  const slug = c.req.param('slug');
  const post = await getPost(slug); // your data source

  return c.html(html`<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>${post.title}</title>
  <meta name="description" content="${post.excerpt}" />

  <meta property="og:title"       content="${post.title}" />
  <meta property="og:description" content="${post.excerpt}" />
  <meta property="og:image"       content="https://yourdomain.com/og/${slug}.png" />
  <meta property="og:url"         content="https://yourdomain.com/blog/${slug}" />
  <meta property="og:type"        content="article" />

  <meta name="twitter:card"        content="summary_large_image" />
  <meta name="twitter:title"       content="${post.title}" />
  <meta name="twitter:description" content="${post.excerpt}" />
  <meta name="twitter:image"       content="https://yourdomain.com/og/${slug}.png" />

  <link rel="canonical" href="https://yourdomain.com/blog/${slug}" />
</head>
<body>
  <h1>${post.title}</h1>
</body>
</html>`);
});

export default app;

Hono JSX renderer with OG tags

Hono supports JSX rendering via the hono/jsx renderer middleware. Inject OG meta tags in your layout component:

// src/index.tsx
import { Hono } from 'hono';
import { jsxRenderer, useRequestContext } from 'hono/jsx-renderer';

const app = new Hono();

app.use(jsxRenderer(({ children, title, description, ogImage, canonicalUrl }) => {
  return (
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <title>{title}</title>
        <meta name="description" content={description} />
        <meta property="og:title" content={title} />
        <meta property="og:description" content={description} />
        <meta property="og:image" content={ogImage} />
        <meta property="og:url" content={canonicalUrl} />
        <meta property="og:type" content="article" />
        <meta name="twitter:card" content="summary_large_image" />
        <meta name="twitter:title" content={title} />
        <meta name="twitter:image" content={ogImage} />
        <link rel="canonical" href={canonicalUrl} />
      </head>
      <body>{children}</body>
    </html>
  );
}));

app.get('/blog/:slug', async (c) => {
  const slug = c.req.param('slug');
  const post = await getPost(slug);

  return c.render(
    <main>
      <h1>{post.title}</h1>
      <p>{post.excerpt}</p>
    </main>,
    {
      title: post.title,
      description: post.excerpt,
      ogImage: `https://yourdomain.com/og/${slug}.png`,
      canonicalUrl: `https://yourdomain.com/blog/${slug}`,
    }
  );
});

export default app;

Dynamic OG image endpoint in Hono

Generate OG images on-demand with a dedicated Hono route that returns a PNG. On Cloudflare Workers, use @vercel/og or the Resvg-js WASM library:

// src/index.ts — OG image endpoint
import { Hono } from 'hono';

const app = new Hono();

app.get('/og/image', async (c) => {
  const title = c.req.query('title') ?? 'My Page';
  const desc = c.req.query('desc') ?? '';

  // Generate SVG and convert to PNG (example using a simple SVG)
  const svg = `<svg width="1200" height="630" xmlns="http://www.w3.org/2000/svg">
    <rect width="1200" height="630" fill="#111827"/>
    <text x="60" y="260" font-size="56" font-family="sans-serif" fill="white">${title}</text>
    <text x="60" y="340" font-size="28" font-family="sans-serif" fill="#9ca3af">${desc}</text>
  </svg>`;

  // In production, use Resvg WASM to render SVG → PNG on the edge
  return c.body(svg, 200, { 'Content-Type': 'image/svg+xml' });
});

export default app;

Reference the endpoint in your page's OG meta tag: og:image = https://yourdomain.com/og/image?title=My+Post&desc=Short+description

Hono on Cloudflare Workers: edge caching for OG images

Add Cache-Control headers to your OG image endpoint so Cloudflare caches them at the edge and reduces generation costs:

c.header('Cache-Control', 'public, max-age=86400, s-maxage=86400, stale-while-revalidate=3600');

Verify your Hono app's OG tags

After deploying, paste your URL into OGFixer to preview how your Hono app's links appear on Twitter, LinkedIn, Slack, and Discord — and catch any OG tag issues before they go live.