OPEN TO WORK

Available for new opportunities! Let's build something amazing together.

Generate open graph preview image in Code with Front Matter

Extensions Front Matter VSCode Open Graph
post

This post is over a year old, some of this information may be out of date.

Since I moved my blog to Hugo, I created a Front Matter - VSCode extension which makes content/article management easier within Visual Studio Code.

A couple of versions ago, I added the ability to integrate your custom scripts. These will show up as actions in the Front Matter side panel. This functionality allows total flexibility to your content management workflow. As everyone has different needs, it will not limit you.

One of the scripts I use for new articles is generating a preview image for open graph and Twitter.

Show image Generate social image action
Generate social image action

The script

The script uses node-html-to-image dependency, which, as the name suggests, converts HTML to an image. Under the hood, it uses puppeteer to generate the image.

My preview image looks as follows:

Show image Preview image
Preview image

The code of the script looks as follows:

//@ts-check
import nodeHtmlToImage from "node-html-to-image";
import * as uuid from "uuid";
import { format, parseJSON } from "date-fns";
import { ContentScript } from "@frontmatter/extensibility";
const html = `
<html>
<head>
<style>
body {
width: 1128px;
height: 600px;
}
</style>
<!-- Include external CSS, JavaScript or Fonts! -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css2?family=Nunito&display=swap" rel="stylesheet">
</head>
<body>
<div class="p-4" style="background-color: #fefefe;font-family: 'Nunito', sans-serif; font-size: 20px; width: 1128px; height:600px;">
<div class="d-flex flex-column justify-content-center align-items-center text-center" style="border: 10px solid #025a5f; height:100%; width:100%; border-radius:50px;">
<span class="tweet-text mb-2" style="font-size: 52px;">
{title}
</span>
<span class="text-muted mb-2">
{date}
</span>
<div class="flex justify-center my-4">
<div class="rounded-full inline-flex" style="background-color: #198c95; height: 0.25rem; width: 4rem;"></div>
</div>
<div class="mb-2">
<img src="https://www.eliostruyf.com/images/eliostruyf_2022.jpg" class="rounded-circle" width="150px">
</div>
<h4 class="mt-2" style="color: #025a5f" >Elio Struyf</h4>
<span class="text-muted">@eliostruyf</span>
</div>
</div>
</body>
</html>
`;
const contentScriptArgs = ContentScript.getArguments();
if (contentScriptArgs) {
const { workspacePath, frontMatter } = contentScriptArgs;
if (workspacePath && frontMatter) {
if (frontMatter.title && frontMatter.date) {
const parsedHtml = html
.replace(`{title}`, frontMatter.title)
.replace(`{date}`, format(parseJSON(frontMatter.date), "MMM dd, yyyy"));
const fileName = `${uuid.v4()}.png`;
// @ts-ignore
nodeHtmlToImage({
output: `${workspacePath}/static/social/${fileName}`,
html: parsedHtml,
})
.then(() =>
ContentScript.updateFrontMatter({ preview: `/social/${fileName}` })
)
.catch((e) => ContentScript.done(e?.message || e));
}
}
}

Adding the script to Front Matter

To make the script available as an action in the Front Matter side panel, you will first have to add a file with the script’s code to your project.

Once you added the file, make sure to install the dependencies: npm i node-html-to-image uuid date-fns @frontmatter/extensibility -D.

After that, it is time for the final step, registering the command. You can register the script in your .vscode/settings.json file with the following code:

"frontMatter.custom.scripts": [{
"title": "Generate social image",
"script": "./scripts/social-img.mjs",
"nodeBin": "~/.nvm/versions/node/v18.17.1/bin/node"
}]

Open the Front Matter side panel, and the new button should show up. When you click on the new button, it will start generating the image. When the script completes, it will show a notification with the path of the image.

Show image The output of the script in a VSCode notification
The output of the script in a VSCode notification

Running this in WSL

I encountered an issue when trying to run the script in WSL. It had to do with some missing dependencies.

Terminal window
# Related GitHub issue: https://github.com/puppeteer/puppeteer/issues/1837
sudo apt install ca-certificates fonts-liberation gconf-service libappindicator1 libasound2 libatk-bridge2.0-0 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 lsb-release wget xdg-utils -y

Update

2024-01-16

Updated the script to use the new @frontmatter/extensibility dependency.

Related articles

Report issues or make changes on GitHub

Found a typo or issue in this article? Visit the GitHub repository to make changes or submit a bug report.

Comments

Elio Struyf

Solutions Architect & Developer Expert

Loading...

Let's build together

Manage content in VS Code

Present from VS Code