nextjsmdxmetadata

Building a Modern Blog with Next.js and MDX

A comprehensive guide on creating a modern blog using Next.js 13+, MDX for content management, and Tailwind CSS for styling. Learn about SSR, routing, and best practices.

My Awesome Post

Here is the content of my post.

Building a Modern Blog with Next.js and MDX

Creating a modern blog requires balancing various factors: performance, SEO, developer experience, and user experience. In this comprehensive guide, I'll walk you through building a blog using Next.js 13+, MDX, and Tailwind CSS.

Why Next.js?

Next.js has become the go-to framework for React applications, and for good reason. It offers:

  1. Server-Side Rendering (SSR) and Static Site Generation (SSG)
  2. Automatic Route Pre-fetching
  3. Built-in Image Optimization
  4. API Routes

Let's dive into the implementation.

Project Setup

First, create a new Next.js project with TypeScript and Tailwind CSS:

npx create-next-app@latest my-blog --typescript --tailwind --eslint
cd my-blog

Directory Structure

Here's our project structure:

my-blog/
├── src/
│   ├── app/
│   │   ├── articles/
│   │   │   ├── [slug]/
│   │   │   │   └── page.tsx
│   │   │   └── page.tsx
│   │   └── layout.tsx
│   ├── components/
│   ├── content/
│   │   └── articles/
│   └── lib/
└── package.json

Implementing MDX Support

MDX allows us to use JSX in our markdown files. Here's how to set it up:

import { serialize } from 'next-mdx-remote/serialize';
import { MDXRemote } from 'next-mdx-remote/rsc';
import rehypeHighlight from 'rehype-highlight';
import remarkGfm from 'remark-gfm';

// Custom components for MDX
const mdxComponents = {
  h1: (props: any) => (
    <h1 className="text-4xl font-bold my-4" {...props} />
  ),
  code: (props: any) => (
    <code className="bg-gray-100 p-1 rounded" {...props} />
  ),
  // ... more components
};

// Usage in page component
const mdxSource = await serialize(content, {
  mdxOptions: {
    remarkPlugins: [remarkGfm],
    rehypePlugins: [rehypeHighlight],
  },
});

Static Site Generation

Next.js 13+ introduces a new App Router with built-in support for static site generation:

// app/articles/[slug]/page.tsx
export async function generateStaticParams() {
  const articles = getAllArticles();
  return articles.map((article) => ({
    slug: article.slug,
  }));
}

export const dynamicParams = false;

Performance Optimizations

1. Image Optimization

Next.js provides the Image component for automatic optimization:

import Image from 'next/image';

function BlogImage() {
  return (
    <Image
      src="/blog-image.jpg"
      alt="Blog Image"
      width={800}
      height={400}
      priority
      className="rounded-lg"
    />
  );
}

2. Font Optimization

Use Next.js 13's built-in font optimization:

import { Inter } from 'next/font/google';

const inter = Inter({ subsets: ['latin'] });

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={inter.className}>
      {children}
    </html>
  );
}

SEO Considerations

Next.js 13+ introduces a new metadata API:

import { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'My Blog',
  description: 'A modern blog built with Next.js',
  openGraph: {
    title: 'My Blog',
    description: 'A modern blog built with Next.js',
    type: 'website',
  },
};

Styling with Tailwind CSS

Tailwind CSS provides utility classes for rapid development. Here's an example of a card component:

function ArticleCard({ article }) {
  return (
    <div className="rounded-lg border border-gray-200 p-6 hover:shadow-lg transition-shadow">
      <h2 className="text-2xl font-bold mb-2">{article.title}</h2>
      <p className="text-gray-600">{article.description}</p>
      <div className="mt-4 flex gap-2">
        {article.tags.map((tag) => (
          <span key={tag.slug} className="px-2 py-1 bg-gray-100 rounded-full text-sm">
            {tag.name}
          </span>
        ))}
      </div>
    </div>
  );
}

Conclusion

Building a modern blog with Next.js offers numerous advantages:

  • Excellent performance through static generation
  • Great developer experience with TypeScript and MDX
  • Built-in optimizations for images and fonts
  • Strong SEO capabilities
  • Beautiful styling with Tailwind CSS

The complete source code for this blog is available on GitHub.