Blog using md files in NextJS

You will need to install below node packages.

    "gray-matter": "^4.0.3",
    "react-markdown": "^8.0.3"
Once these packages are installed, you can create md files in a folder using below syntax.

---
title: List of best Indian stocks for 2050 
slug: best-indian-stocks
---

  Here is the list of stocks grouped by sector
     
1. IT - Tata ELXI
2. Tyre - Balkrishna Industries
3. Auto - Maruti Suzuki
4. Bank - Kotak Mahindra Bank, ICICI Bank
5. Textile - Page Industries
6. FMCG - HUL, P&G
7. Finance - Bajaj Finance
8. Footwear - Bata, Relaxo Footwear
9. Other - Dixon tech
After this you will need to create an index route and dynamic route to handle the blog pages. Create an index route using below syntax. Below code will list all pages of a blog.

import React from 'react'
import ReactMarkdown from 'react-markdown'
import fs from 'fs'
import BottomMenu from '../../components/BottomMenu'
import RightMenu from '../../components/RightMenu'
import TopMenu from '../../components/TopMenu'
import HtmlHead from '../../components/HtmlHead'
import LeftBanner from '../../components/LeftBanner'
import MyLink from '../../components/MyLink'
import matter from 'gray-matter'

const blog = (props) => {
    const realData = props.data.map(blog => matter(blog))
    const listItems = realData.map(listItem => listItem.data)

    let type = "projects"
    let pageTitle = "My Blogs"
    let pageDescription = pageTitle
    return (
        <>
            <HtmlHead type={type} pageTitle={pageTitle} pageDescription={pageDescription} />
            {/* <TopMenu type={type} /> */}
            <div className="main">
                <div className="left"><LeftBanner /></div>
                <div className="middle">

                    <h2>{pageTitle}</h2>

                    <ul>
                        {
                            listItems.map(blog => {
                                //render blog links here
                                //return blog.title + " - " + blog.slug
                                return (<li style={{lineHeight:'1.5em', padding:'2px'}}><MyLink link={"/blog/" + blog.slug} text={blog.title} /></li>)
                            })

                        }

                    </ul>
                    <BottomMenu />

                </div>
                <RightMenu type={type} />
            </div>
        </>
    )


}

export default blog


export const getStaticProps = async () => {
    const fs = require('fs')
    const path = require('path')
    
    //let p1 = `/vercel/path0\content`;
    let files = fs.readdirSync(path.join(process.cwd(), 'content', 'blog'), 'utf-8')
 

    const getSortedFiles = async (dir) => {
        const files = await fs.promises.readdir(dir);
      
        return files
          .map(fileName => ({
            name: fileName,
            time: fs.statSync(`${dir}/${fileName}`).mtime.getTime(),
          }))
          .sort((a, b) =>  b.time - a.time )
          .map(file => file.name);
      };
      
    //   Promise.resolve()
    //     .then(() => getSortedFiles(path.join(process.cwd(), 'content', 'blog')))
    //     .then((f)=>{
    //             files  = f;
    //             console.log('files in ', files);

    //     })
    //     .catch(console.error);

   files = await getSortedFiles(path.join(process.cwd(), 'content', 'blog'))
   const blogs = files.filter(f => f.endsWith(".md"))
   //console.log('files ', files);
    const data = blogs.map(blog => {
        //const path = `/vercel/path0\content\${blog}`;
        const rawContent = fs.readFileSync(path.join(process.cwd(), 'content', 'blog', blog), 'utf-8')

        return rawContent
    })

    return {
        props: {
            data
        }
    }
}


To show individual blogs, create a dynamic route (pages/blog/[blog].tsx) as shown below.


import React from 'react'
import matter from 'gray-matter'
import ReactMarkdown from 'react-markdown'
import fs from 'fs'
import BottomMenu from '../../components/BottomMenu'
import RightMenu from '../../components/RightMenu'
import TopMenu from '../../components/TopMenu'
import HtmlHead from '../../components/HtmlHead'
import LeftBanner from '../../components/LeftBanner'
import MyLink from '../../components/MyLink'


const blog = (props) => {
    
const {data, content} = matter(props.content)

    let type = "projects"
    let pageTitle = data.title
    let pageDescription =  data.title
    return (
        <>
            <HtmlHead type={type} pageTitle={pageTitle} pageDescription={pageDescription}  />
            <div className="main">
                <div className="left"><LeftBanner/></div>
                <div className="middle">
                <MyLink text="<- Blog Home" link="/blog"/>

                    <h1>{pageTitle}</h1>

    <ReactMarkdown children={content}/>
  


        <BottomMenu/>

                </div>
                <RightMenu type={type} />
            </div>
        </>
    )

    
}

export default blog


export const getServerSideProps = async context =>{
    const path = require('path')

    const {blog} = context.params
  
    const content = fs.readFileSync(path.join(process.cwd(),'content','blog',blog + ".md"),'utf-8')
  
   return {
     props : {
       content
     }
   }
  
  }

Web development and Automation testing

solutions delivered!!