Published: Jan 1, 20234 min read

My 2023 Blog Redesign: Next.js 13, TypeScript, & Contentlayer

Written by: Ekom Enyong — Cover Photo by: Daniele Levis Pelusi on Unsplash
https://images.unsplash.com/photo-1500042825080-66d3b701f10f?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2671&q=80

This article is not a walk-through or tutorial! I wanted to share some of the new Next.js 13 features, Tailwind CSS animations, and custom components I'm using on my website this year.

Introduction

Nearly every year, I redesign (and sometimes rebuild) my website from the ground up. It's a great exercise to practice new things I've learned over the year, refactor any wrong code, and implement new design techniques. I feel more confident with my design skills this year than ever!

Beyond the actual design, I didn't change much about my website. That being said, let's dive right in!

Next.js 13

The release of Next.js 13 has introduced new features that I have enjoyed using, even though it's still in beta. I am utilizing the appDir for my page and routing structure and also love the custom TypeScript VSCode plugin Vercel provides to make the developer experience better.

I am also utilizing @next/font and @vercel/analytics to make use of font optimization and Vercel's new analytics acquisition.

Contentlayer

I am still using Contentlayer to compile my Markdown files. 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. Contentlayer is perfect for projects that need scalable markdown content but don't need a robust CMS. While it is in beta, I suggest you try it out on your next project.

A Fresh Coat of paint

Last year, I was all about pastels. Pink has been my favorite color for over 20 years now, so that wasn't going to change. But as far as some of the other pastels colors I used, they are gone.

Screenshot of my blog homepage in 2022.
A screenshot of my personal website homepage in 2022.

I still use pink but with a soft gradient on my website layout. My new design includes micro-animations to provide a modern web experience but is still quite performant as far as Google is concerned.

Screenshot of my newly updated homepage in 2023.
A screenshot of my newly designed website in 2023.

While I have dropped my large, all-caps headings, I still feel my website represents a modern and minimal design.

Updating MDX Code Blocks

Last year when I redesigned my website, I used rehype-prism-plus. This year I discovered rehype-pretty-code and implemented Railly Hugo's One Hunter Vercel Theme with a custom background.

One of my favorite features of rehype-pretty-code is that you can highlight inline code like so: const age = 25 .

I still have a custom Pre component that allows readers to copy a code block to their clipboard, which you can try out below!

components/emoji.tsx

// 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>
  );
}

Tailwind Merge

To be able to create usable components without style conflicts, I am using clsx and tailwind-merge. You can do the same with your Tailwind CSS projects by creating a function as follows:

utils/clsxm.ts

import clsx, { ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
// Merge classes with tailwind-merge with clsx full feature
export function clsxm(...classes: ClassValue[]) {
  return twMerge(clsx(...classes));
}

Skeleton Component

This year, I created a custom skeleton component. This is useful when you want to show a user that data is not yet available but loading. I wrote this component out as :

components/skeleton.tsx

interface ISkeleton extends React.HTMLAttributes<HTMLDivElement> {}
 
export default function Skeleton({ className, ...props }: ISkeleton) {
  return (
    <div className={clsxm("animate-pulse bg-gray-200", className)} {...props} />
  );

Summary

As I go into 2023, I am still using the same web technologies I was building with last year. I look forward to further expanding my design and React development knowledge this year.

I would love to hear your comments, revisions, or suggestions on this post. Let's discuss it on Twitter!


Ekom Enyong is an SEO Manager who has spent the last decade helping brands increase leads and organic traffic through digital strategy and high-quality content.