• Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
alexwein

alexwein

alexBlogs

me writing about things maybe
Remix of stevekrouse/markdownBlogStarter
Public
Like
alexBlogs
Home
Code
10
components
2
other-posts
2
posts
9
Layout.tsx
README.md
about.md
analytics.ts
H
index.tsx
prompt.md
robots.txt
Environment variables
1
Branches
7
Pull requests
Remixes
1
History
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.
Sign up now
Code
/
prompt.md
Code
/
prompt.md
Search
2/7/2026
Viewing readonly version of og-images-2 branch: v5
View latest version
prompt.md

Townie Prompt: Add Open Graph Meta Tags to Alex's Blog

Goal

Add Open Graph (OG) meta tags to this blog for better social media sharing. When a link to the blog is shared on Twitter, Discord, Slack, etc., it should show a nice preview image with the post title.

Reference Implementation

See how valdottown/blog implements OG images:

  • components/Head.tsx - The <head> component with OG meta tags
  • components/OGImage.tsx - SVG component that renders the OG image
  • routes/og-image.tsx - HTTP endpoint that serves the OG image as PNG

Current Project Structure

alexwein/alexBlogs (branch: og-images-2)
├── index.tsx          # Main HTTP handler with all routes
├── Layout.tsx         # HTML wrapper (currently minimal <head>)
├── analytics.ts       # Hit tracking
├── about.md           # About page content
├── posts/             # Blog posts (markdown files)
│   ├── 2025-12-25-chart-games-2025.md
│   ├── 2025-12-24-five-friendly-sql-tips.md
│   └── ... (more posts)
├── other-posts/       # Special posts (like dvs-spin.md)
└── robots.txt

Implementation Plan

1. Create components/OGImage.tsx

Create an SVG component that generates the OG image. Follow the reference blog's approach:

  • Use SVG (1200x640 viewport) for the image
  • Display the post title as the main text (with word wrapping using word-wrap package)
  • Below the title, display "alex wein's blog" as the site name (similar to how the reference shows "Blog")
  • Use a simple, clean design with a horizontal line separator
  • Keep the font styling simple (sans-serif) since custom fonts are tricky in SVG-to-PNG conversion

Example structure:

Create val
/** @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 }) { // Word wrap the title // Return SVG with title text and "alex wein's blog" footer }

2. Create routes/og-image.tsx (or og-image.tsx in root)

Create an HTTP endpoint that:

  • Accepts a ?title= query parameter
  • Renders the OGImage component to SVG
  • Converts SVG to PNG using https://deno.land/x/resvg_wasm@0.2.0/mod.ts
  • Returns the PNG with appropriate Content-Type headers

The route should be accessible at /og-image.png.

3. Create components/Head.tsx

Create a reusable Head component that includes:

  • Basic meta tags (charset, viewport)
  • Page <title> (with format: {postTitle} | alex wein's blog or just alex wein's blog for homepage)
  • OG meta tags:
    • og:type = "website"
    • og:title = the page title
    • og:description = (optional, can be empty or a default)
    • og:image = URL to /og-image.png?title={encodedTitle}
  • Twitter card meta tags:
    • twitter:card = "summary_large_image"
    • twitter:title = the page title
    • twitter:image = same as og:image

Props should include:

  • title: string - The page/post title

4. Update Layout.tsx

Modify Layout to accept and use the Head component:

  • Add a title prop
  • Replace the existing <head> contents with the new Head component
  • Keep the existing stylesheet link

5. Update index.tsx

Update all routes to pass the appropriate title:

Homepage (/)

  • Title: "alex wein's blog"

Individual post pages (/posts/*)

  • Extract the title from the markdown content by finding the first ## or # heading
  • Pass this extracted title to Layout

About page (/about)

  • Title: "About"

Special pages (like /dbt, /2019/03/15/visualizing-visualizers/)

  • Extract title from markdown or use a sensible default

6. Title Extraction Helper

Create a helper function to extract the title from markdown:

function extractTitleFromMarkdown(markdown: string): string { // Look for first h1 (# ) or h2 (## ) heading const h1Match = markdown.match(/^#\s+(.+)$/m); const h2Match = markdown.match(/^##\s+(.+)$/m); // Prefer h1, fall back to h2, then default return h1Match?.[1] || h2Match?.[1] || "alex wein's blog"; }

Note: The current posts use ## (h2) as their top-level headings, so make sure to check for both # and ##.

Important Details

Base URL

You'll need to determine the base URL for constructing absolute OG image URLs. Options:

  1. Hardcode it (e.g., https://alexwein-alexblogs.web.val.run)
  2. Derive it from req.url in the handler
  3. Use a constant file like the reference does

Route Integration

The /og-image.png route needs to be added to the main handler in index.tsx. Add it before the 404 fallback:

if (url.pathname === "/og-image.png") { // Import and use the og-image handler }

Or create it as a sub-app using Hono like the reference does.

Dependencies to Add

  • https://esm.sh/word-wrap@1.2.5 - For wrapping long titles
  • https://deno.land/x/resvg_wasm@0.2.0/mod.ts - For SVG to PNG conversion

Design Notes

Keep the OG image design simple and readable:

  • White background
  • Black text
  • A colored horizontal line as a separator (pick a nice accent color)
  • The post title large and prominent
  • "alex wein's blog" smaller, at the bottom

Summary of Files to Create/Modify

FileAction
components/OGImage.tsxCreate - SVG image component
components/Head.tsxCreate - Head component with OG tags
og-image.tsx or routes/og-image.tsxCreate - PNG endpoint
Layout.tsxModify - Use Head component, accept title prop
index.tsxModify - Extract titles, pass to Layout, add og-image route

Testing

After implementation, test by:

  1. Visiting /og-image.png - should show default "alex wein's blog" image
  2. Visiting /og-image.png?title=Test%20Title - should show "Test Title"
  3. Using a social media debugger (Twitter Card Validator, Facebook Sharing Debugger, etc.) to verify the OG tags are working
FeaturesVersion controlCode intelligenceCLIMCP
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
© 2026 Val Town, Inc.