Public
LikealexBlogs
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Viewing readonly version of og-images branch: v13View latest version
Add Open Graph (OG) meta tags to this blog so posts display rich previews when shared on social media (Twitter, Facebook, LinkedIn, Slack, etc.). Each page should have a dynamically generated OG image.
Study how valdottown/blog implements OG images:
components/OGImage.tsx- SVG component that renders the OG image with title textroutes/og-image.tsx- HTTP route that renders SVG to PNG usingresvg_wasmcomponents/Head.tsx- Adds OG meta tags to the HTML head, constructing image URL with title query param
Create an SVG-based React component similar to the reference:
- Default title: "alex wein's blog"
- For individual posts, show the post title with "alex wein's blog" displayed smaller (similar to how Val Town Blog shows "Blog" at the bottom)
- Use
word-wrappackage to handle long titles across multiple lines - Simple, clean design (white background, black text)
- Standard OG image dimensions: 1200x640
/** @jsxImportSource https://esm.sh/react@18.2.0 */
import wrap from "https://esm.sh/word-wrap@1.2.5";
export default function OGImage({ title = "alex wein's blog" }: { title?: string }) {
// Implementation here
}
Add a route handler for /og-image.png that:
- Accepts a
?title=query parameter - Renders the OGImage component to SVG using
renderToStaticMarkup - Converts SVG to PNG using
resvg_wasm: - Returns PNG with proper
Content-Type: image/pngheader - Optionally support
?format=svgfor debugging
Important: This blog does NOT use front-matter. Instead, extract the title from the first ## or # heading in each markdown file.
Create a utility function to extract the title:
function extractTitleFromMarkdown(markdown: string): string | null {
// Match first h1 or h2
const match = markdown.match(/^#{1,2}\s+(.+)$/m);
return match ? match[1] : null;
}
Modify Layout.tsx to accept and render OG meta tags:
og:title- page titleog:description- optional descriptionog:image- URL to the OG image endpoint with title paramog:type- "website" or "article"twitter:card- "summary_large_image"twitter:title,twitter:image
Example:
export function Layout({
children,
title = "alex wein's blog",
description,
ogImageTitle
}: {
children: ReactNode;
title?: string;
description?: string;
ogImageTitle?: string;
}) {
const baseUrl = "https://alexwein-alexblogs.web.val.run"; // Update with actual URL
const ogImageUrl = `${baseUrl}/og-image.png?title=${encodeURIComponent(ogImageTitle || title)}`;
return (
<html lang="en">
<head>
{/* existing meta tags */}
<meta property="og:title" content={title} />
<meta property="og:image" content={ogImageUrl} />
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:title" content={title} />
<meta property="twitter:image" content={ogImageUrl} />
{description && <meta property="og:description" content={description} />}
</head>
<body>{children}</body>
</html>
);
}
Modify each route to:
- Extract the post title from markdown content
- Pass the title to the Layout component
- Add the
/og-image.pngroute handler
For the homepage (/):
- Use default title "alex wein's blog"
For individual posts (/posts/:slug):
- Extract title from the markdown's first h1/h2
- Pass to Layout for OG tags
- OG image should show post title with "alex wein's blog" as subtitle
For special pages (about, dbt, visualizer):
- Use appropriate page-specific titles
alexBlogs/
├── components/
│ └── OGImage.tsx # NEW: SVG OG image component
├── utils/
│ └── extractTitle.ts # NEW: Extract title from markdown
├── Layout.tsx # MODIFIED: Add OG meta tag support
├── index.tsx # MODIFIED: Add /og-image.png route, pass titles
├── posts/
│ └── *.md
└── ...
After implementation:
- Visit
/og-image.png- should show default "alex wein's blog" image - Visit
/og-image.png?title=Test%20Title- should show custom title - Visit
/og-image.png?format=svg- should return SVG for debugging - Use a social media debugger (Facebook Sharing Debugger, Twitter Card Validator) to verify meta tags
- Check that each blog post page has unique OG image with its title
- The current posts use
##(h2) for titles, not#(h1). Handle both cases. - Keep the implementation simple - no need for custom fonts or complex styling initially
- The base URL will need to be determined from the request or hardcoded for now
- Consider caching the PNG renders if performance becomes an issue