When creating my blog, I wanted each article to contain all of the information, and I wanted to hard code this information. Metadata was the perfect solution for this, but was harder to implement than expected.
Looking at the metadata object that is included in each blog article file better illustrate what I am looking to do!
export const metadata = {
title: "Exporting Metadata from MDX Files",
published: "2024-12-01",
updated: "2024-12-01",
author: 'Nash Bostwick',
thumbnail: '/blog/artical-template/thumbnail.jpeg',
description:"How to setup mdx file metadata to optimize seo and also organise files on your site.",
keywords: ['MDX', 'Metadata', 'Export', 'MDX Blog Metadata', 'Metadata Export'],
tags: ['test', 'test', 'test', 'test', 'test', 'test'],
isActive: true,
};
Then to read the metadata from the files I am using this function
export async function getBlogPostMetadata(directory, folderNames) {
const articles = await Promise.all(
folderNames.map(
(folder) =>
new Promise((resolve) => {
// Construct the full file path
const filePath = path.join(directory, folder, 'page.mdx');
// Read the file using fs.readFile with a callback
fs.readFile(filePath, 'utf-8', (err, fileContent) => {
if (err) {
console.error(`Error reading file "${filePath}":`, err.message);
resolve(null); // Resolve as null if there's an error
return;
}
try {
// Extract the metadata object
const metadataMatch = fileContent.match(
/export\s+const\s+metadata\s+=\s+({[\s\S]*?});/
);
if (!metadataMatch) {
throw new Error(`Metadata not found in file: ${filePath}`);
}
// Safely parse the metadata object
const metadata = Function(
`"use strict"; return (${metadataMatch[1]});`
)();
// Validate required metadata fields
if (!folder || !metadata.title) {
throw new Error(
`Missing some required metadata fields in: ${folder}`
);
}
resolve({
title: metadata.title || 'Untitled',
published: metadata.published || 'Untitled',
updated: metadata.updated || 'Untitled',
author: metadata.author || 'Untitled',
thumbnail: metadata.thumbnail || 'Untitled',
description: metadata.description || '',
keywords: metadata.keywords || [],
isActive: metadata.isActive || false,
folder,
});
} catch (error) {
console.error(
`Error processing file "${filePath}":`,
error.message
);
resolve(null); // Resolve as null if there's an error
}
});
})
)
);
Hopefully this helps someone. I couldn't find anyone online doing something similar. This doesn't require any dependencies keeping everything clean!