Skip to content

Blog Images

A retro-style 8-bit illustration features a computer screen with a visible code script. Surrounding it are symbolic representations of image generation: a markdown document, an image prompt morphing into abstract art, and a fading alt-text bubble. The design uses corporate colors, simple geometric shapes, and is limited to five colors, without including people or text.
Generated by 🤖 AI

We generate cover images to the blog, this in itself is completely uninteresting… but the script that generated the images is worth a look.

The generation of an blog post cover is done in 3 phases:

  • convert the blog markdown into an image prompt
  • generate an image from the image prompt
  • generate an alt text description from the image prompt
  • resize, copy image and patch the blog post frontmatter
blog-image.genai.mts
script({ parameters: { force: false }, accept: ".md,.mdx" })
const file = env.files[0]
const target = path.changeext(file.filename, ".png")
const fm = MD.frontmatter(file.content)
if (env.vars.force || !(await workspace.stat(target))) {
// phase 1: generate image prompt
const style =
"iconic, 2D, 8-bit, corporate, 5-color, simple, geometric, no people, no text"
const { text: imagePrompt } = await runPrompt(
(_) => {
_.def("BLOG_POST", MD.content(file.content))
_.$`Generate an image prompt for gpt-image-1 that illustrates the contents of <BLOG_POST>.
Include specific description related to the content of <BLOG_POST>.
${style}`
},
{ responseType: "text", systemSafety: false }
)
// phase 2: generate image
const image = await generateImage(
`${imagePrompt}
STYLE:
${style}`,
{
mime: "image/png",
size: "landscape",
maxHeight: 762,
model: "openai:gpt-image-1",
}
)
// phase 3: generate alt text
const { text: alt } = await prompt`
Generate an alt text description from <IMAGE_PROMPT>.
Rephrase the prompt in a way that would be useful for someone who cannot see the image.
Do not start with "Alt Text:".
IMAGE_PROMPT:
${imagePrompt}`.options({
responseType: "text",
systemSafety: false,
label: "alt-text",
})
// phase 4: patch frontmatter
fm.cover = {
alt,
image: "./" + path.basename(target),
}
await workspace.copyFile(image.image.filename, target)
}
if (env.vars.force || !fm.tags?.length) {
const res = await prompt`
Generate 5 keyword tags from <BLOG_POST>. The tags are used for SEO purposes in a blog.
Respond with 1 tag per line.
<BLOG_POST>
${MD.content(file.content)}
</BLOG_POST>`.options({
responseType: "text",
systemSafety: false,
label: "tags",
})
if (!res.error)
fm.tags = res.text
?.split(/\r?\n/g)
.map((tag) => tag.trim())
.filter(Boolean)
}
if (!fm.excerpt) {
const res = await prompt`
Generate an excerpt from <BLOG_POST>.
- Do not use "Excerpt", "Unlock", "Master".
- Maximize engagement on LinkedIn. Your tone is friendly and technical.
- Do not be excited.
- Do not add code snippets or sections.
<BLOG_POST>
${MD.content(file.content)}
</BLOG_POST>`.options({
responseType: "text",
systemSafety: false,
label: "excerpt",
})
if (!res.error) fm.excerpt = res.text.trim()
}
// phase 5: save files
file.content = MD.updateFrontmatter(file.content, fm)
await workspace.writeFiles(file)

Once this script worked for a couple posts, use used the convert command to generate the images for all the blog posts.

Terminal window
genaiscript convert blog-image blog/*.md*

The images are somewhat abstract, but they are generated from the blog post content. The image prompt could definitely be improved, but it’s a good start.