The title of this post may sound like clickbait. After all, it is about AI.
From time to time, I review my site in search of elements that can be improved. This time, I wanted to focus on one aspect related to SEO. I noticed that every sub-page had exactly the same content in the meta name="description"
tag. I decided to change this and add unique content for each sub-page, which might at least slightly improve their positioning in search results.
I started from the most visited pages on my website - articles in the posts section. In my CMS panel (I use Decap CMS), I already had a place to write a description. However, I have been lazy so far and have never even written a short summary of a post. Writing a short 120–160 character summary for each post on my site felt too time-consuming. AI is great at creating text content, so I decided to hand over this task to AI. I chose Mistral AI, which I have been using privately quite often for several months. They offer several models, and for this task I chose a free one - mistral-small-latest
.
To solve this task I’ve written a short python script. The procedure is very simple: for each file in a given folder, take its main content (omit the frontmatter metadata), send a request to Le Platforme API and execute the appropriate prompt on it: “Generate an SEO-friendly meta description (110-160 characters) for this blog post: /content of the blog post/“. After receiving the response from the API, place the obtained content as a new field in the file - “description”.
Here’s my script:
import frontmatter
import os
import requests
import time
apikey = {yourApiKey}
folder = "./../../geodev_site/src/lib/content/blog"
def generate_description(text, apikey):
url = "https://api.mistral.ai/v1/chat/completions"
headers = {
"Authorization": f"Bearer {apikey}",
"Content-Type": "application/json"
}
data = {
"model": "mistral-small-latest",
"messages": [
{
"role": "user",
"content": f"Generate an SEO-friendly meta description (110-160 characters) for this blog post:\n\n{text}"
}
]
}
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
description = response.json().get("choices", [{}])[0].get("message", {}).get("content", "").strip()
return description
else:
print(f"❌ Error: {response.status_code}, {response.text}")
def update_descriptions(folder, api_key):
files = os.listdir(folder)
for filename in files:
try:
if filename.endswith(".md"):
path = os.path.join(folder, filename)
post = frontmatter.load(path)
content = post.content
if "description" not in post.metadata:
description = generate_description(content[:1000], api_key)
if description:
post.metadata["description"] = description
with open(path, "w") as f:
f.write(frontmatter.dumps(post))
print(f"✅ Updated: {filename}")
else:
print(f"❌ Not Updated: {filename}")
time.sleep(3);
except:
print(f"❌ Error")
update_descriptions(folder, apikey)
You may notice that I use time.sleep(3)
after each request is completed. This is because I got a lot of 429 http responses:
I added a 3 second break after each response, which may be too much, but thanks to this the entire process completed correctly for all 54 files.
That’s it. Each article file now has a description
metadata field with the appropriate content generated by Mistral AI. Example below.
category: React
date: 2021-01-24 17:18:31.121000+00:00
description: Learn how to create a reusable scroll indicator in React using hooks
and Styled Components. Enhance user experience by highlighting scrollable content.
slug: Scroll indicator component in React
tag:
- react
- components
templateKey: blog-post
title: Scroll indicator component in React
Now after writing the next post I just need to execute this script.