Scaffolding the Next.js App
 (Part - 2)
Published: 2021-06-01 10:03:23

In this series, I am rewriting the code of my blog [ashutosh.dev](https://ashutosh.dev) in Next.js and Mojolicious as backend. This is the third article of the series.

To do this, we downloaded all of our articles from the dev web app (JSON file is under the data folder). You can use your file or download it from the [GitHub](https://github.com/akuks/ashutosh-dev) repository under the data folder.

## Create and Update next.config.js file
If not created, please create the **next.config.js** file and update it with the following code:


```javascript
module.exports = {
    webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
        config.node = {
            fs: 'empty', // This is required
        }
        return config
    }
}
```

This file is responsible for setting up the configuration for Next.js. In this, we are setting up fs (file system) to empty. So, it will not create any issues while reading the file.

## Fixing the Header

In the Header, we added an anchor link for the Home, Contact, and About pages. It's not the Next.js way of handling the anchor tags. Let's fix that.

Open the **NavigationComponent.js** file and replace 

```javascript
<a className="block lg:inline-block mt-4 lg:mt-0 mr-10 font-bold text-white hover:underline"
    href="/">
         Home
</a>
<a className="block lg:inline-block mt-4 lg:mt-0 mr-10 font-bold text-white hover:underline"
href="/about">
     About
</a>
<a className="block lg:inline-block mt-4 lg:mt-0 text-white font-bold hover:underline"
    href="/contact">
        Contact
</a>
```

with 

```javascript
<Link href="/">
    <a className="block lg:inline-block mt-4 lg:mt-0 mr-10 font-bold text-white hover:underline">
        Home
    </a>
</Link>
<Link href="/about">
    <a className="block lg:inline-block mt-4 lg:mt-0 mr-10 font-bold text-white hover:underline">
        About
    </a>
</Link>
<Link  href="/contact">
    <a className="block lg:inline-block mt-4 lg:mt-0 text-white font-bold hover:underline">
        Contact
    </a>
</Link>
```

And add the following at the top of the file.

```javascript
import Link from "next/link"; 
```

## Fixing the Categories Component

We need to replace the anchor tags in the Categories component also. Let's fix it too.

```javascript
<a className="hover:underline hover:text-cyan-600" href="#"> {event} </a>
```

with 

```javascript
<Link href={'/?categories=' + event}>
    <a className="hover:underline hover:text-cyan-600" > {event} </a>
</Link>
```

## Modifying index.js
So far, we have added the articles.json file to the root of our application. It's time to read it and pass it to the components.

The idea is to read the file and convert it to the JSON object and then pass it further to the components. Reading the file is not possible directly. We need to add getStaticProps() function to our index.js file. If you are new and not aware of the getStaticProps(), you can read it on [this link](https://ashutosh.dev/blog/post/2021/04/what-is-getstaticprops-nextjs). 

```javascript
export async function getStaticProps(context) {
    let blog = new Array();
    const fileToRead = path.join(process.cwd(), '/data/articles.json')
    const data = JSON.parse(await fs.readFileSync(fileToRead))
    for (let index in data) {
        const catList = data[index].cached_tag_list
        blog.push({
            title: data[index].title,
            date: data[index].published_at,
            body: data[index].body_markdown,
            description: data[index].description,
            categories: catList
        });
    }
    // Reverse an Array
    const reverseData = blog.slice(0).reverse()
    return  {
        props: {
            sample_blogs: reverseData
        }
    }
}
```

We need to reverse the Array because the JSON file is not sorted with the recent blogs first.

We also need to modify the **Home()** function.

```javascript
<div className="flex flex-auto">
 	<CategoriesComponent />
        <BlogComponent Blogs={props} />
        <div></div>
 </div>
```

And don't forget to import 

```javascript
import fs from 'fs';
import path from 'path';
```

Now the file will look like 

```javascript
import Head from 'next/head'
import CategoriesComponent from "../components/Categories/CategoriesComponent";
import BlogComponent from "../components/Blog/BlogComponent";
import fs from 'fs'
import path from 'path'

function Home(props) {
  return (
    <div>
      <Head>
        <title>Ashutosh.dev - A place to learn Programming</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <div className="flex flex-auto">
          <CategoriesComponent />
          <BlogComponent Blogs={props} />
          <div></div>
      </div>
    </div>
  )
}
export async function getStaticProps(context) {
    let blog = new Array();
    const fileToRead = path.join(process.cwd(), '/data/articles.json')
    const data = JSON.parse(await fs.readFileSync(fileToRead))
    for (let index in data) {
        const catList = data[index].cached_tag_list
        blog.push({
            title: data[index].title,
            date: data[index].published_at,
            body: data[index].body_markdown,
            description: data[index].description,
            categories: catList
        });
    }
    // Reverse an Array
    const reverseData = blog.slice(0).reverse()
    return  {
        props: {
            sample_blogs: reverseData
        }
    }
}
export default Home
```

## Refactor BlogComponent.js and BlogList.js

From index.js, we passed props to the BlogComponent. Now, we need to use the Props in our BlogComponent. 

Open the file and modify the code as:

```javascript
import BlogList from "./BlogList";

function BlogComponent(props) {
    return (
        <div className="ml-4 mt-4 w-1/2 container mr-4">
            <BlogList Blogs={props.Blogs} />
        </div>
    )
}

export default BlogComponent
```

Open the BlogList.js file and update the following code:

```javascript
import Link  from "next/link";
import IndividualBlogDetails from "./IndividualBlogDetails";
function BlogList(props) {
    const Blogs  = props.Blogs.sample_blogs
    return (
        <div className="ml-4">
            {
                Blogs.map( event =>
                    <IndividualBlogDetails details={event} />
                )
            }
        </div>
    )
}
export default BlogList
```

## Create IndividualBlogComponent

We'll further break down the components into another component.

Create a new file IndiviudalBlogComponent.js, under the blog folder.

```javascript
import Link from "next/link";

function IndividualBlogDetails(props) {
    const event = props.details
    const cat = (event.categories).split(", ");
    return (
        <div key={event.slug} className={`border-b shadow rounded-md hover:shadow-lg hover:border`}>
            <div className={`ml-4 mt-4`}>
                <Link href={`/blog/${encodeURIComponent(event.slug)}` }>
                    <a className={`hover:text-cyan-500`}>
                        <h1 className={`font-bold text-2xl`}>{event.title}</h1>
                    </a>
                </Link>
            </div>
            <p className={`ml-4 mt-4`}>{event.description}</p>
             {/*Posted Date*/}
            <div className="ml-4 mt-8 flex">
                <p>
                    <span className={`text-gray-400`}>Published: </span>
                    <small>
                        <time className={`hover:underline hover:text-cyan-500`}>{humanReadableDate(event.date)}</time>
                    </small>
                </p>
                {/*Categories Belongs to*/}
                <div className={`ml-10 mb-4`}>
                    {
                        cat.map
                        ( event =>
                            <span key={cat} className={`inline-block bg-cyan-200 text-cyan-800 text-xs px-2 rounded-full uppercase font-semibold tracking-wide mr-2`}>
                                <Link href={`/?categories=${encodeURIComponent(event)}` }>
                                    <a className={`hover:underline`}>{event}</a>
                                </Link>
                            </span>
                        )
                    }
                </div>
            </div>
        </div>
    )
}
function humanReadableDate(date) {
    return new Date(date).toLocaleDateString(
        undefined,
        {year: "numeric", month: "long", day: "numeric"}
    )
}

export default IndividualBlogDetails
```

The date in the JSON is the timestamp, so we have converted the data into a readable format.

Open the browser, and you will see the home page like the below illustration.

So far, we have created a home page where we see all the blog lists. But we also need to click on the blog page to go over the details of the blog. Create **[slug].js** file inside the blog folder under the pages directory.

```javascript
function IndividualBlogPage(props) {
    return (
        <div>
            Individual blog page
        </div>
    )
}

export default IndividualBlogPage
```

If you click, then you'll see the blog page details. We'll update the details of the individual blog in our next article of the series.