โ† Back to articles

How I rebuilt this blog.

2022-07-28 ยท 5 min read

If you don't already know, I recently decided to rebuild my blog. Previously, I had used Jekyll, a Ruby tool designed for writing blogs and their default theme for GitHub Pages with a couple of tweaks. This time, I decided to build a blog application myself - one that would allow me to:

  • Write blog articles on the site and send emails, i.e., kind of like an admin panel
  • Posts vs. complete articles for quick updates
  • One with my own custom design

Ultimately, I decided to switch over because there were some limitations with the previous blog and I wanted to get rid of those limitations. I was also inspired by Josh W. Comeau's blog, which was written with very similar tools. Most importantly, I really just wanted to get some practice building a NextJS full-stack app, since there definitely are tools out there that could get rid of the aforementioned limitations.


The design

The first thing I did was build a static design. Here's a quick snippet of the SCSS:

#blog-wrapper {
    /* Flexbox wrapper for entire website */
    @media screen and (min-width: $min-width) {
        display: flex;
        position: relative;

        #nav {
            flex-basis: 0;
            flex-grow: 3;
        }

        #blog {
            flex-basis: 0;
            flex-grow: 9;
        }
    }
}

I spent a pretty long time tweaking the styles to get the site looking the way I wanted, but it came out pretty great. (I hope.) One of the issues I ran into was styling images:

A picture of the Golden Gate Bridge that I took! Pretty nice, eh?A picture of the Golden Gate Bridge that I took! Pretty nice, eh?

I realized that I wanted to add captions to images, but ultimately I would be writing content in Markdown, just like I had done with Jekyll. In HTML, the images would look like this:

<div class="image">
    <image src="/assets/images/goldengatebridge.webp">
    <em>A picture of the Golden Gate Bridge that I took! Pretty nice, eh?</em>
</div>

While Markdown does let you include HTML, I didn't want to write this every time I wanted to use an image. There's a solution to this: the MDX library. According to the main page of the project site:

MDX allows you to use JSX in your markdown content. You can import components, such as interactive charts or alerts, and embed them within your content. This makes writing long-form content with components a blast. ๐Ÿš€

With the MDX library, I could turn the HTML above into a component:

export default {
    img: ({ src, alt }) => (
        <span className="image">
            <img src={src} />
            <em>{alt}</em>
        </span>
    )
};

The only downside of this was that I couldn't use NextJS's image optimization for local images. (If you know, please do let me know. I'm sure I could write a hacky solution, but I don't want to.) Besides, I needed to figure out to add links to headings as well, so I went ahead and did that. Try hovering over the headings!

Content

Once I finished the design of the different pages, I started working on logic. All the code for this website is located at a personal GitHub repo. In it, I have a file called generate.js that is responsible for reading the content inside a folder called _content, which contains:

  • Articles
  • Main pages

The difference between these is that articles are viewed through the article pages, while main pages are included in the menu bar - for example, my resume.

generate.js also takes care of generating unique slugs - that is, unique routes for each article so article routes don't overlap. These are then used by NextJS' getStaticProps to cache content, thus making loading article content more efficient.

Newsletter and backend implementation

I also decided to implement a newsletter. This was one of the aforementioned drawbacks of using Jekyll, where I had to create a separate Flask app to store and view subscribers. This new newsletter points to /api/subscribe, which in turn updates a MongoDB database hosted on MongoDB Atlas, both tools that were on my learning list earlier this year. MongoDB was utilized for managing nearly everything on the backend, which I did through an admin interface that I also had to create. I planned for this admin interface to let me:

  • View and delete subscribers
  • View and send newsletters

The backend was implemented with a few tools: nodemailer for sending the mail (through my personal domain email, jianmin[at]jianminchen.com), mongoose for modeling subscribers and admins in the database, and chakra-ui/@react so I wouldn't have to write SCSS for the backend (although adapting for mobile was a burden, but oh well).

Conclusion

After wrapping the code part up, I decided to do a couple of extra things:

  • Utilize SEO
  • Test with NextJS' core-web-vitals to ensure everything was as optimized as I could possibly make it
  • Use depcheck to make sure there are no unnecessary dependencies

Overall, it was a lot of fun building this! It was genuinely a great learning experience.