Skip to content

Instantly share code, notes, and snippets.

Last active March 24, 2023 18:31
Show Gist options
  • Save joshvickerson/5dab835046ef9d0cf0a5b9310ff821b2 to your computer and use it in GitHub Desktop.
Save joshvickerson/5dab835046ef9d0cf0a5b9310ff821b2 to your computer and use it in GitHub Desktop.
Convert a JSON Export of post data from AnchorCMS to individual markdown files grouped by year for consumption by Eleventy
import json
import os
from datetime import datetime
from markdownify import markdownify # requires installation:
outputDirBase = 'posts/'
# open the file
with open('blog_posts.json', 'r') as file:
post_data = json.load(file)
for post in post_data:
filename = post['slug']
postTitle = post['title']
postDescription = post['description']
postTag = post['category']
postCreated = post['created']
postUpdated = post['updated']
postContent = post['markdown']
# determine date-based output path
# convert created date to datetime object, so we can get the year
created = datetime.strptime(postCreated, '%Y-%m-%d %H:%M:%S')
# convert the updated date to a datetime object
updated = datetime.strptime(postUpdated, '%Y-%m-%d %H:%M:%S')
# some updated timestamps are before created timestamps (possibly a bug from the CMS)
# set updated to the same time if that's the case, since it doesn't make sense
if updated < created:
updated = created
outputDirFinal = outputDirBase + str(created.year) + '/'
# if output directory doesn't exist, create it
# on macOS, this requires sudo permissions
if not os.path.exists(outputDirFinal):
# we read the data, now write to a md file, formatting with front matter for Eleventy
newFileName = outputDirFinal + filename + '.md'
newFile = open(newFileName, 'w')
# start front matter
newFile.write('title: "' + postTitle.replace('"', '\\"') + '"\n')
newFile.write('description: "' + postDescription.replace('"', '\\"') + '"\n')
newFile.write('date: \'' + created.strftime('%Y-%m-%d') + '\'\n')
newFile.write('updated: \'' + updated.strftime('%Y-%m-%d') + '\'\n')
newFile.write('tags: [\'' + postTag + '\']\n')
# end front matter
# uncomment the next line to inject blog archive notice box
# newFile.write('{% include "partials/blog-archive-notice.html" %}\n\n')
# write the post content, converting from HTML to markdown
# log output
print("Wrote: " + newFileName)
posts.title, posts.slug, posts.description, posts.created, posts.updated, posts.markdown, categories.title as 'category'
FROM `posts`
INNER JOIN `categories`
on (posts.category =;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment