Lets build a Markdown blog using Next.js, Shadcn, Tailwind, Pieces, Remark & Rehype 🔥

 Building a Markdown blog using **Next.js**, **Shadcn**, **Tailwind CSS**, **Pieces**, **Remark**, and **Rehype** is a fantastic idea! This stack will give you a modern, performant, and highly customizable blog. Let’s break it down step by step.


---


### **1. Set Up Next.js Project**

Start by creating a new Next.js project:


```bash

npx create-next-app@latest my-markdown-blog

cd my-markdown-blog

```


---


### **2. Install Tailwind CSS**

Install Tailwind CSS and configure it:


```bash

npm install -D tailwindcss postcss autoprefixer

npx tailwindcss init -p

```


Update `tailwind.config.js`:


```javascript

/** @type {import('tailwindcss').Config} */

module.exports = {

  content: [

    "./app/**/*.{js,ts,jsx,tsx}",

    "./pages/**/*.{js,ts,jsx,tsx}",

    "./components/**/*.{js,ts,jsx,tsx}",

  ],

  theme: {

    extend: {},

  },

  plugins: [],

};

```


Add Tailwind to your `globals.css`:


```css

@tailwind base;

@tailwind components;

@tailwind utilities;

```


---


### **3. Add Shadcn Components**

Shadcn is a collection of reusable components built on top of Tailwind CSS. Install it:


```bash

npx shadcn-ui@latest init

```


Follow the prompts to configure Shadcn. Then, add components as needed:


```bash

npx shadcn-ui@latest add button

npx shadcn-ui@latest add card

```


---


### **4. Set Up Markdown Processing**

To process Markdown files, we’ll use **Remark** and **Rehype**.


Install the required packages:


```bash

npm install remark remark-html remark-prism rehype-highlight gray-matter

```


- `remark`: Core Markdown processor.

- `remark-html`: Converts Markdown to HTML.

- `remark-prism`: Adds syntax highlighting with Prism.

- `rehype-highlight`: Alternative syntax highlighter.

- `gray-matter`: Parses front matter from Markdown files.


---


### **5. Create a Markdown Utility**

Create a utility function to parse Markdown files. Add a file `lib/markdownToHtml.js`:


```javascript

import { remark } from 'remark';

import html from 'remark-html';

import prism from 'remark-prism';

import matter from 'gray-matter';


export async function markdownToHtml(markdown) {

  const result = await remark()

    .use(html)

    .use(prism)

    .process(markdown);

  return result.toString();

}


export function parseMarkdown(content) {

  const { data, content: markdown } = matter(content);

  return { data, markdown };

}

```


---


### **6. Fetch and Display Markdown Posts**

Create a folder `_posts` in the root directory and add some Markdown files with front matter:


```markdown

---

title: "My First Post"

date: "2023-10-01"

---


# Hello, World!


This is my first blog post.

```


Create a page to list all posts (`pages/index.js`):


```javascript

import fs from 'fs';

import path from 'path';

import Link from 'next/link';

import { parseMarkdown } from '../lib/markdownToHtml';


export async function getStaticProps() {

  const postsDirectory = path.join(process.cwd(), '_posts');

  const filenames = fs.readdirSync(postsDirectory);


  const posts = filenames.map((filename) => {

    const filePath = path.join(postsDirectory, filename);

    const fileContent = fs.readFileSync(filePath, 'utf8');

    const { data } = parseMarkdown(fileContent);

    return {

      slug: filename.replace(/\.md$/, ''),

      ...data,

    };

  });


  return { props: { posts } };

}


export default function Home({ posts }) {

  return (

    <div className="container mx-auto p-4">

      <h1 className="text-3xl font-bold mb-4">Blog Posts</h1>

      <ul>

        {posts.map((post) => (

          <li key={post.slug} className="mb-2">

            <Link href={`/posts/${post.slug}`}>

              <a className="text-blue-500 hover:underline">{post.title}</a>

            </Link>

          </li>

        ))}

      </ul>

    </div>

  );

}

```


---


### **7. Create Dynamic Post Pages**

Create a dynamic route for individual posts (`pages/posts/[slug].js`):


```javascript

import fs from 'fs';

import path from 'path';

import { markdownToHtml, parseMarkdown } from '../../lib/markdownToHtml';


export async function getStaticPaths() {

  const postsDirectory = path.join(process.cwd(), '_posts');

  const filenames = fs.readdirSync(postsDirectory);


  const paths = filenames.map((filename) => ({

    params: { slug: filename.replace(/\.md$/, '') },

  }));


  return { paths, fallback: false };

}


export async function getStaticProps({ params }) {

  const filePath = path.join(process.cwd(), '_posts', `${params.slug}.md`);

  const fileContent = fs.readFileSync(filePath, 'utf8');

  const { data, markdown } = parseMarkdown(fileContent);

  const content = await markdownToHtml(markdown);


  return { props: { post: { ...data, content } } };

}


export default function Post({ post }) {

  return (

    <div className="container mx-auto p-4">

      <h1 className="text-3xl font-bold mb-4">{post.title}</h1>

      <div

        className="prose prose-lg"

        dangerouslySetInnerHTML={{ __html: post.content }}

      />

    </div>

  );

}

```


---


### **8. Add Syntax Highlighting**

To enable syntax highlighting, update your `tailwind.config.js`:


```javascript

module.exports = {

  content: [

    // ...existing content

  ],

  theme: {

    extend: {},

  },

  plugins: [require('@tailwindcss/typography')],

};

```


Then, wrap your Markdown content with the `prose` class (as shown in the `Post` component above).


---


### **9. Add Pieces for Code Snippets**

If you want to integrate **Pieces** for managing code snippets, you can use their API or SDK. Install the Pieces client:


```bash

npm install @pieces-app/client

```


Use it to fetch and display code snippets in your blog posts.


---


### **10. Deploy**

Deploy your blog to **Vercel** or any other platform:


```bash

vercel

```


---


### **Final Notes**

- Customize the design using Tailwind and Shadcn components.

- Add more features like tags, categories, or a search bar.

- Optimize performance with Next.js features like `getStaticProps` and `getStaticPaths`.


Let me know if you need help with any specific part! 🚀

Comments

Popular posts from this blog

React Portflio Website Basic to Advance

Todo List app using html,js and tailwind.css with features login,logout,storing the data in localstorage addtodos,deletetodos and updating todos,toastify library and many more