Problem
The landing page of my Quick Drop app is created using NextJS.
Recently, I have started doing some content marketing for my app. One of the task is to create Open Graph banner images for the blog, that I’m setting up for Quick Drop.
After some research, it looks like there is an issue with generating of open graph images when the NextJS is configured with output: "export"
After some more research and with the help of ChatGPT, I can finally find a temporary solution for this issue. The plan is to create a node script to pre-generate all open graph images for all blog pages. The OG image will have the content adapted dynamically to every blog post, with the title is rendered on top of a template.
Solution
The solution consists of several html, javascript font and image files:
-
The
Inter
font files are downloaded from Google Font -
The
background.png
file is the background image for all generated Open Graph images, the size is 1200x630 as per recommendation.
- The
logo.png
is the logo of the Quick Drop app. It is used for branding on the OG image
- The
template.html
the template for the Open Graph image. The
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Custom Font Screenshot</title>
<style>
@font-face {
font-family: 'Inter-Bold';
src: url('Inter-Bold.ttf') format('truetype');
}
@font-face {
font-family: 'Inter-Regular';
src: url('Inter-Regular.ttf') format('truetype');
}
body {
font-family: 'Inter-Regular', sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background: url('background.jpg') no-repeat center center fixed;
padding-left: 20px;
padding-right: 20px;
}
.text-regular {
font-family: 'Inter-Regular', sans-serif;
}
.text-bold {
font-family: 'Inter-Bold', sans-serif;
}
</style>
</head>
<body>
<div style="position: relative; width: 1160px; height: 590px; color: white;">
<div style="position: absolute; top: 0px; left: 0px; display: flex; align-items: center; opacity: 0.7;">
<img src="logo.png" width="50" height="50">
<span class="text-bold" style="font-size: 24px; margin-left: 10px; color: #FF2C55;">Quick Drop</span>
</div>
<div
style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 90px; text-align: center; width: 100%; color: #FF2C55;">
<span class="text-bold">{{title}}</span>
</div>
<div class="text-bold" style="position: absolute; top: 10px; right: 0px; font-size: 24px; opacity: 0.7; color: #FF2C55;">
https://quickdrop.antran.app
</div>
</div>
</body>
</html>
- The
generateOGImages.js
is the main javascript file responsible for generating the image based on the input parameters:pageTitle
: the title text that will be rendered on the OG imagefilePath
: the path of the output file
const puppeteer = require('puppeteer');
const path = require('path');
const fs = require('fs').promises;
async function generateImage(pageTitle, filePath) {
const templatePath = path.join(__dirname, 'template.html');
let html = await fs.readFile(templatePath, 'utf8');
html = html.replace('{{title}}', pageTitle);
const tempFilePath = path.join(__dirname, 'temp.html');
await fs.writeFile(tempFilePath, html);
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 1200, height: 630 });
await page.goto(`file:${tempFilePath}`, { waitUntil: 'networkidle0' });
await page.screenshot({ path: `${filePath}.png` });
await browser.close();
await fs.unlink(tempFilePath);
console.log(`${filePath}.png saved`);
}
module.exports = generateImage;
- The
build.js
is used to generate all OG images for all pages
const generateImage = require('./generateOgImages');
async function main() {
await generateImage("How to compress PDFs for free quickly?", "public/blogs/compress_pdf/og");
}
main().catch(console.error);
Before pushing the site to my remote server, I’ll manually run the following command to generate the OG images for all pages added into the build.js
:
node scripts/build.js
The generated Open Graph image should look like this:
When you post website to X, the result can be seen from this Tweet:
Many legacy systems restrict the size of PDF files when you try to upload them. It's pretty annoying.
— Quick Drop App (@UseQuickDrop) May 16, 2024
This blog will show you how to compress your PDFs for free, and also how to integrate the process with @UseQuickDrop https://t.co/mleDCxNHDK