First Blog at this site

Over the past few years, I have been somewhat a blogger, but I have never truly settled on a platform, what I have tried include: Ghost and Outline. The former, while the capability of self-hosting it nice, and with an oracle 4c24g instance (always free), you can essentially use it without any concerns about its performance and accessibility, when combined with cloudflare. But having experienced their transition from ver 4.0 to 5.0, I found that it is becoming more and more clumsy with all those new features that I don't need (e.g. membership, newsletter, etc.). The latter, I admit it is a little bit stretch to call it a blogging platform when it is designed to be used as an internal knowledge base, but I have been using it for a while, and had great experience when it is up and available, that is to say, it is not very stable with the docker-compose setup, and I had to restart it every now and then.

So, after finishing this semester and having experienced Next.js with a course project, I find it is a good time to start creating my very own blogging site with only Next.js and Tailwind CSS. My goal here is to maximize its functionalities (those that I need) while maintaining its simplicity, and I will try to keep it as simple as possible. There will definitely be further improvements, modifications and additions applied to this website, but I think it is very safe to say that it will be a long-term project, and I no longer have to worry about the content being lost due to a mistake in the migration process (cuz it's completely on GitHub right now!!!).

The developing process, at least for this 0.1.0 version, is very straightforward, I have designated to have all the blog stored in a folder called _posts, and I have a blog post api implemented as follows to read and load all the metadata embedded in the mdx file

// Function to fetch metadata from all MDX files in the _posts folder
export async function fetchAllMetaData(): Promise<MetaData[]> {
  const postsDirectory = path.join(process.cwd(), "_posts");
  const filenames = fs.readdirSync(postsDirectory);
  const allMetaData: MetaData[] = [];

  filenames.forEach((filename) => {
    const filePath = path.join(postsDirectory, filename);
    const fileContents = fs.readFileSync(filePath, "utf8");

    // Extract metadata from the file content
    const metaMatch = fileContents.match(/export const meta = (.*?);/s);
    if (metaMatch && metaMatch[1]) {
      try {
        // Evaluate the string as an object
        const metaData = eval("(" + metaMatch[1] + ")");
        allMetaData.push(metaData as MetaData);
      } catch (error) {
        console.error(`Error parsing metadata in file ${filename}: `, error);

  return allMetaData;

And the project folder structure is as follows

├── _posts                      # All the blog posts
├── app/
│   ├── blog/                   # Blog page
│   │   └── {blog_slug}         # Individual blog page
│   └── components/             # Reusable components
│       └── mdx                 # MDX components
├── lib                         # Utility functions
├── public/                     # Static assets
│   └── images                  # Images to be used in mdx with next/image
└── types

This blog has taken a great deal of inspiration from Lee Robinson's blog, especially the style and the way he organizes his blog posts. However, other than the nav bar, I have implemented everything from scratch, from the blog post api to the blog page, I have minimized the hosting and managing effort by using Github repo as storage (all content and images will be included in the github repo), vercel as the deployment platform and did not choose to include the viewing count, comment sections, etc. These are trivial to implement as I have experienced all these features in my course project building a online post-based forum [Bluedit](https://github. com/Lemon2ee/bluedit), but I think it is not necessary for a personal blog, at least for right now.