In this post, I will show you how to generate link preview images for your blog posts so that they look good when you share them on social media.
Below, you can see how it's gonna look like:
We will create a simple Flask endpoint that will accept a URL and return a generated image based on the website's metadata.
So let's get to work.
Prepare a Jinja2 template for an HTML version of your card
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ title }}</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<style>
@page {
size: 1200px 628px;
margin: 0;
padding: 0;
}
html {
font-size: 137.5%;
-webkit-font-smoothing: antialiased;
}
body {
padding: 3rem;
font-family: 'Inter', sans-serif;
color: #111111;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='18' viewBox='0 0 100 18'%3E%3Cpath fill='%231c64f2' fill-opacity='0.05' d='M61.82 18c3.47-1.45 6.86-3.78 11.3-7.34C78 6.76 80.34 5.1 83.87 3.42 88.56 1.16 93.75 0 100 0v6.16C98.76 6.05 97.43 6 96 6c-9.59 0-14.23 2.23-23.13 9.34-1.28 1.03-2.39 1.9-3.4 2.66h-7.65zm-23.64 0H22.52c-1-.76-2.1-1.63-3.4-2.66C11.57 9.3 7.08 6.78 0 6.16V0c6.25 0 11.44 1.16 16.14 3.42 3.53 1.7 5.87 3.35 10.73 7.24 4.45 3.56 7.84 5.9 11.31 7.34zM61.82 0h7.66a39.57 39.57 0 0 1-7.34 4.58C57.44 6.84 52.25 8 46 8S34.56 6.84 29.86 4.58A39.57 39.57 0 0 1 22.52 0h15.66C41.65 1.44 45.21 2 50 2c4.8 0 8.35-.56 11.82-2z'%3E%3C/path%3E%3C/svg%3E");
}
h1 {
font-size: 3.052rem;
margin-top: 0;
}
p {
font-size: 1.563rem;
line-height: 1.5;
}
</style>
</head>
<body>
<h1>{{ title }}</h1>
<p>{{ excerpt }}</p>
</body>
</html>
Create a Flask endpoint that will generate the preview image
import io
import requests
from lxml import etree
@app.route('/preview.png')
def preview():
# Fetch the URL
page_html = requests.get(request.args['url']).text
# Parse the HTML response
parser = etree.HTMLParser()
tree = etree.parse(io.StringIO(page_html), parser)
# Get the website's title and description from its metadata
head = tree.xpath('/html/head')[0]
title = head.xpath('meta[@property="og:title"]/@content')[0]
description = head.xpath('meta[@property="og:description"]/@content')[0]
# Render the HTML version of the preview
preview_html = render_template('card.html', title=title, excerpt=description)
# Use weasyprint to convert the HTML preview to PNG
preview_img = weasyprint.HTML(string=preview_html).write_png(resolution=2 * 96)
return Response(preview_img, mimetype='image/png')
Below are the steps one by one:
- fetch the URL,
- parse the HTML response,
- get the website's title and description from its metadata,
- render the HTML version of the preview,
- use
weasyprint
to convert the HTML preview to PNG, - and return the generated image.
And that's it! Now you can use the endpoint in your website metadata so that it looks good when shared on social media:
<meta property="og:image" content="https://YOUR_DOMAIN/preview.png?url=YOUR_URL"/>
Top comments (2)
Usign metatags.io/ (free tool) you generate the metatags you need to paste in the
of your website.It is a 3 minuntes solution. Meta Tags — Preview, Edit and Generate
I was looking for this so badly. Thanks for the share