With the release of Next.js 14, the App Router has revolutionized how developers build dynamic websites and applications. Combining this cutting-edge framework with Markdown creates a powerful, modern blogging platform that is fast, scalable, and developer-friendly. In this guide, we’ll break down the entire process, ensuring you have the latest insights into Next.js blogging and Markdown.
Next.js 14 App Router simplifies routing and server-side rendering, allowing developers to create highly performant applications. Pairing it with Markdown for content management provides a lightweight, efficient solution for bloggers and small businesses.
Markdown provides a lightweight, plain-text format for writing content, making it an excellent choice for managing blogs. Paired with tools like gray-matter
and react-markdown
, Markdown simplifies content creation and improves developer productivity.
To begin, set up a Next.js 14 project using the App Router.
Install Next.js 14:
npx create-next-app@latest my-blog-platform --experimental-app
cd my-blog-platform
npm run dev
Folder Structure: With the App Router, the app/
directory is used instead of pages/
. Inside app
, you’ll define your routes, layouts, and components.
Editor Setup: Use VS Code with extensions like ESLint and Prettier to format your code and enforce best practices.
Markdown files will store your blog posts, making content creation intuitive. Here's how to integrate Markdown into your project:
Create a posts/
Directory: Store your .md
files here.
Install Dependencies:
npm install gray-matter react-markdown
gray-matter
: Parses frontmatter (metadata like title and date).react-markdown
: Converts Markdown content into React components.Read Markdown Files: Create a utility function in lib/getPosts.js
:
import fs from "fs";
import path from "path";
import matter from "gray-matter";
const postsDirectory = path.join(process.cwd(), "posts");
export function getPosts() {
const fileNames = fs.readdirSync(postsDirectory);
return fileNames.map((fileName) => {
const fullPath = path.join(postsDirectory, fileName);
const fileContents = fs.readFileSync(fullPath, "utf8");
const { data, content } = matter(fileContents);
return {
slug: fileName.replace(/\.md$/, ""),
metadata: data,
content,
};
});
}
With the App Router, dynamic routing is more intuitive and integrated into the component-based structure.
Create a Dynamic Route:
app/
directory, create a folder structure like app/blog/[slug]/page.js
.Fetch and Render Blog Content:
import fs from "fs";
import path from "path";
import matter from "gray-matter";
import ReactMarkdown from "react-markdown";
export async function generateStaticParams() {
const postsDirectory = path.join(process.cwd(), "posts");
const filenames = fs.readdirSync(postsDirectory);
return filenames.map((filename) => ({
slug: filename.replace(/\.md$/, ""),
}));
}
export default async function BlogPost({ params }) {
const { slug } = params;
const filePath = path.join(process.cwd(), "posts", `${slug}.md`);
const fileContents = fs.readFileSync(filePath, "utf8");
const { data, content } = matter(fileContents);
return (
<div>
<h1>{data.title}</h1>
<p>{data.date}</p>
<ReactMarkdown>{content}</ReactMarkdown>
</div>
);
}
Metadata for SEO: Utilize the metadata
export for dynamic SEO metadata:
export async function generateMetadata({ params }) {
const { slug } = params;
const filePath = path.join(process.cwd(), "posts", `${slug}.md`);
const fileContents = fs.readFileSync(filePath, "utf8");
const { data } = matter(fileContents);
return {
title: data.title,
description: data.excerpt,
};
}
Tailwind CSS is a popular utility-first framework that simplifies styling.
Install Tailwind CSS:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init
Configure tailwind.config.js
and add content paths:
module.exports = {
content: [
"./app/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
],
};
Apply Tailwind Classes: Create reusable components for consistency.
export default function BlogCard({ post }) {
return (
<div className="border p-4 rounded shadow-md hover:shadow-lg">
<h2 className="text-xl font-bold">{post.metadata.title}</h2>
<p>{post.metadata.excerpt}</p>
</div>
);
}
Enhance user experience with a search bar that filters blog posts.
Install fuse.js
:
npm install fuse.js
Implement Search:
import Fuse from "fuse.js";
import { useState } from "react";
export default function SearchBar({ posts }) {
const [query, setQuery] = useState("");
const fuse = new Fuse(posts, {
keys: ["metadata.title", "content"],
threshold: 0.3,
});
const results = query
? fuse.search(query).map((result) => result.item)
: posts;
return (
<div>
<input
type="text"
placeholder="Search..."
value={query}
onChange={(e) => setQuery(e.target.value)}
className="border p-2 rounded"
/>
<div>
{results.map((post) => (
<BlogCard key={post.slug} post={post} />
))}
</div>
</div>
);
}
Deploying your blogging platform is straightforward with Vercel:
At Prateeksha Web Design, we specialize in creating high-performance, scalable web platforms using cutting-edge technologies like Next.js 14. Whether you're a small business or an individual blogger, we ensure your blogging platform is tailored to your needs, offering:
With Next.js 14 App Router and Markdown, building a blogging platform has never been more efficient. By following this guide, you can create a modern, scalable, and SEO-friendly blog that caters to your audience. For those seeking a professional touch, Prateeksha Web Design is here to help turn your vision into reality. Let’s build something amazing together!
Prateeksha Web Design offers services to build a custom blogging platform using Next.js and Markdown, providing a seamless and user-friendly experience for bloggers. Our team of experts will help you create a dynamic and responsive website that showcases your content in a visually appealing way. We will also integrate features such as SEO optimization, social media sharing, and customizable layouts to enhance your blog's functionality. Contact us today to get started on building your dream blogging platform.
Interested in learning more? Contact us today.