Rebuilding My Blog with Next.js, TypeScript, and Contentlayer
I updated my Next.js, TypeScript, Tailwind CSS blog with a fresh coat of paint, new components, and Contentlayer for markdown.
Table of Contents
Introduction
It's that time of year again when I totally redesign my website from the ground up. While my individual post template hasn't changed too much, I redesigned my page templates to feel a little more me. I have some future plans and wanted to align my personal website design with those upcoming plans.
Not much else has changed in this website refresh. I did add a few new custom components and features but I'm still using Next.js, TypeScript, and Tailwind CSS. Beyond the design of the site, the only other major change is one you can't see — a new tool to compile my markdown files.
Let's take a break look at how I changed my website this time around.
Contentlayer for MDX
Last year was the first time I built a blog website using MDX using @next/mdx
. In January of this year, I came across Contentlayer, a content SDK that focuses on great DX and performance. Some of the reasons you might love Contentlayer include:
- Easily
import
your content as data - Use JS/TS — no new query language to learn
- Strong-typed data with auto-generated type definitions
- Built-in and configurable content validations
- Detailed error messages
- Fast build and page performance
The first tool I used that also follows the concept of structured content, or thinking of content as data, was Sanity.io, which I enjoy using to build web platforms for clients. Discovering Contentlayer was perfect to use for projects that need scalable content but don't need a robust CMS. Now that it is in beta, I suggest you try it out on your next project.
Fresh Coat of Paint
While I appreciated how clean my previous design was, I wanted something that didn't feel like every other portfolio website out there. I decided to go with large sans-serif typography on pastel colored backgrounds. It's a refreshed, modern take on minimal and I am actually really proud of this design.
New Custom Components
I added a sticky, collapsible TableOfContents
component that makes the reading experience for desktop users much more enjoyable. I also added a SocialShare
widget to make it easy for readers to share my posts with their audiences on Twitter, FaceBook, and LinkedIn.
Admonition
I love using admonitions in Obsidian and I wanted to bring that same feel to my blogging experience. I have created 10 different admonition types with an optional title prop and the ability to nest admonitions. Check out some of them below:
This is an example of a default admonition without a title
prop. In this case,
the title default to the type of admonition.
This is a cool message!
This is another cool message!
I know... nested admonitions are 🔥!
Upgraded Code Blocks
I upgraded my code blocks to include code titles, line number functionality, and line highting with rehype-prism-plus. I have also included a Pre
component that allows a user to copy a code block to their clipboard. Try it out by hovering over the code block below.
// You can copy this code block
interface EmojiProps {
label?: string;
emoji: string;
}
// Note the highlighted rows below
export default function Emoji({ label, emoji, ...props }: EmojiProps) {
return (
<span
role="img"
aria-label={label || ''}
aria-hidden={label ? 'false' : 'true'}
{...props}
>
{emoji}
</span>
);
}