Artical Featured Image

Exporting Data From MDX Files

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.

Exporting the Metadata

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,
};

Reading the Metadata

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!

NashBrowns Logo