Part 1.1 - Build a fullstack blogging website using MERN ( MongoDB, ReactJS, ExpressJS and NodeJS )
Tags: react, mongodb, javascript, nextjs
Published: 2023-10-07 12:11:06

👋 Hey there, today in this blog we will start a new series where we will learn “how to make a fullstack blogging website using MERN stack”  basically we will make a website very similar to [medium.com](http://medium.com). 

You probably think it is just some other tutorial claiming to make a fullstack website with just simple things but I will say, you should see the website demo first available below. You will see a lot of features there from having a fully working modern editor for writing blogs, to features like, like a blog, comment on blog and even replies to any comment ( basically nested comments ) on top of that a very good dashboard UI to manage blog and view insights like “like count, read count, comments count” and did I mention any interaction you do on website will store in database as a notification for other user. In short, its a kind of project which will just shine in your portfolio. 

Okay so let’s see how we can start building this project, I can’t wait to start this blog. 

*This project is so big so the tutorial of this project will be in parts. In video formats it will be 4 or 5 parts that you can find on “[Modern Web](https://www.youtube.com/channel/UCoygqHsdILWZFlfI5RMC-dw/)” youtube channel and In blogs there will be 3 - 4 parts for every video part* 

## Website Demo

If you want to see the full website in action, all features from simple to advance. You can watch the demo below. The video below also include this blog in video format.

{% youtube J7BGuuuvDDk %}

You can download full source code of this project if you want. [Download Source Code](https://www.patreon.com/posts/90122909)

## Github Initialisation

Okay, in order to follow this project, you need to download this [github repo](https://github.com/kunaal438/mern-blogging-website). 

You can fork the repo in your account and then clone it on your system or you can just download the repo without forking it to your account. Once you have the repo, you will get 2 folders inside it 

`blogging website - frontend` - this folder is frontend ( react ) code

`server` - this folder is backend ( node ) code

open both of these files on terminal separately because we need to install the packages in order to make this project. You don’t have to worry about any package name or version all of these things are mentioned in `package.json` file already.

### `blogging website - frontend` folder setup

Once this folder is open in terminal, first run `npm install` cmd to install all the packages, after that you just need to start the frontend vite server whenever you want to access the website. You can do that by running `npm run dev` cmd in terminal.

### `server` folder setup

Once this folder is open in terminal, first run `npm install` cmd to install all the packages. 

That’s sit once you have installed all the packages we can start working on the project.

## Navbar

Let’s start our project by working on our Navbar first. Let’s create navigation for easy user interaction. We will create navbar as a react component because we want to render navbar on multiple pages/routes. So open `navbar.component.jsx` under components folder. Create a very basic Navbar Functional component.

```jsx
const Navbar = () => {
	return (
		<h1> Navbar </h1>
	)
}

export default Navbar; // default let's you import function without { } 
```

Above component is returning an `h1` to render for now so that we can check whether or not our component working properly. Also make sure to export the component as a default component.

Now to render it, we will go inside `app.jsx` file which is our app file where we will setup routes for this project later. In file you will see its returning an `h1` by default. so remove that and instead add `<Navbar />`  to render it. ( Do not forget to import the component at top, in VScode you can do that automatically if you just press enter while typing component name from the suggestion VScode gives you )

```jsx
import Navbar from "./components/navbar.component";

const App = () => {

    return (
       <Navbar />
    );

}

export default App; 
```

So if you are getting “navbar” text on the page that means everything is working and if not then it’s time for you to recheck the code and see where you made mistake. 

Okay, let’s create our navbar now. So instead of returning `h1` return `nav` and we will create navbar inside it. Add Classname to it `navbar` because in `index.css` file, there is `navbar` class with bunch of tailwind CSS for navbar.

```jsx
const Navbar = () => {
	return (
		<nav className="navbar">
			{ 
				// nav elements will go here 
			}
		</nav>
	)
}
```

### Navbar - Logo

In our navbar, we have a logo and whenever user click on that logo we want to redirect user to homepage. So first let’s make the logo inside navbar.

```jsx
<nav className="navbar">

	<img src={logo} className="flex-none w-10" />

</nav>
```

`img` element has `flex-none` class, so that our navbar `flex` won’t affect its size. In the `src` I have given `{logo}`  , if you don’t know what this `{ }`  used for then its simple inside JSX to access/write JS you can use `{ }` and inside the brackets you can use JS and you can even call variable inside it to access variable name. So `src` is basically whatever this `logo` variable is. Now what is it ?

Well in order to use any external file in react you have to import it, whether its a component, function, image, svg anything. You have to first import it and this logo is exactly the import of image at the top of `navbar.component.jsx` file.

```jsx
import logo from "../../imgs/logo.png"; // img path respective to components folder as the file is inside components folder

// rest of the code
```

**Output**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/csbbpx4itv9wrajbpq62.png)

Okay we got `img` but how we can redirect user to `/` ( home route ). Well one way is to wrap the `img` inside an `a` tag.

```jsx
<a href="/">
	<img src={logo} className="flex-none w-10" />
</a>
```

This will redirect you whenever you will click on image. But if you notice the site. You will see whenever you are clicking on image the page get’s reload and this destroy the concept of React Single Page Application concept as whenever you will click on image. Browser will ask for the website again from the server. So then, what can we use. To resolve this issue, instead of `a` we will use `<Link> </Link>` component offered by `react-router-dom` . React router is a library that help you mimc the functionality of Browser routing insider React application. So using `Link` component of that, we can redirect the user to whatever route we want without reloading the page. 

So first import it at top.

```jsx
import { Link } from "react-router-dom";
import logo from "../../imgs/logo.png";

// rest of the code
```

And now, wrap the `img` inside `Link`

```jsx
<Link to="/" className="flex-none w-10">
    <img src={logo} className="w-full" />
</Link>
```

`to` prop means on which route we want to redirect. I have changed the `className`as well. That just adding the `flex-none` functionality to `Link` and `w-full` for `img` to cover full width that is `w-10`

But now you won’t see anything in the output. Why ? Because in order to use `Link` or any other features/components of `react-router-dom` you have to first wrap the `<App />` component inside `<BrowserRouter>` which is also a component from `react-router-dom` which mimics the Browser routing functionality, and since we will have the `<App />` inside it. The `App` which is our whole project, will be able to access the `BrowserRouter` functionalities. 

So inside `main.jsx` wrap the `App`

```jsx
<BrowserRouter>
  <App />
</BrowserRouter>
```

And make sure to import the `BrowserRouter` at the top too.

```jsx
import { BrowserRouter } from 'react-router-dom'

ReactDOM.createRoot(document.getElementById('root')).render(
	// React Component
)
```

### Navbar - Search Box

After logo we need a search box in our navbar. Well we will make this search box functional later. But right now, let’s get the UI done. So after `Link` create a `div` and let’s create a search box input like this 👇

```jsx
// inside <nav> tag after <Link> .. </Link>

<div className="absolute bg-white w-full left-0 top-full mt-0.5 border-b border-grey py-4 px-[5vw] md:border-0 md:block md:relative md:inset-0 md:p-0 md:w-auto">
    <input 
        type="text"
        placeholder="Search"
        className="w-full md:w-auto bg-grey p-4 pl-6 pr-[12%] md:pr-6 rounded-full placeholder:text-dark-grey md:pl-12"
    />
</div>
```

To understand the tailwind classes I use, I suggest you watch the video tutorial as you will get better understanding of each classes. Anyway, so basically the `div` is a container for `input` and the search icon that we will create next.

```jsx
// after search box input

<i className="fi fi-rr-search absolute right-[10%] md:pointer-events-none md:left-5 top-1/2 -translate-y-1/2 text-xl text-dark-grey"></i>
```

For icons, I am using **Flat Icons** , in the Github files font awesome installation is already done, so you can use any font awesome icon directly in the project. The one I am using is `fi fi-rr-search` ( a magnifying glass icon )

After this we will see something like this.

**Output  - smaller screens**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txlgxmxobbrgjd22mm9x.png)


**Output - medium screens**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ck1l8x7gg8s4dyif9xvb.png)


So it’s done, but in smaller screens, what we want is to show/hide the search box whenever user clicks on search icon visible on navbar. Something like 👇

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/glvg17q34yn8nfdk3i8q.png)


To create that after the parent `div` of search box. Make another `div` and this will be a container for actions buttons on the right side in our navbar.

```jsx
// after search box's div & inside nav

<div className="flex items-center gap-3 md:gap-6 ml-auto">
    <button className="md:hidden bg-grey w-12 h-12 rounded-full flex items-center justify-center">
        <i className="fi fi-rr-search text-xl"></i>
    </button>
</div>
```

So this JSX element with tailwind styles will give an output like this. Where you will see the search icon button in smaller screens and as soon as you hit medium screen size, you will not get the search icon because the search box will be inside navbar in that screen size.

**Output - smaller screens**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0wriia0pws295kqfgcwe.png)


**Output - medium screens**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p9dc8wj6oaq5kljl4crj.png)


Now, how we can show/hide the search box. Well to achieve this I will use React States to track whether the search box should be visible or not. So let’s create a state first to track that.

```jsx
const Navbar = () => {

	const [ searchBoxVisibility, setSearchBoxVisibility ] = useState(false) // default value will be false

	return (
			// navbar code here
	)

}
```

Now since we have a state now, we will toggle its value from true → false → true whenever the search icon got click. To do that add `onClick` to the `button` and run a function to call `setSearchBoxVisibility` function to change the state’s value.

```jsx
// search icon button

<button className="md:hidden bg-grey w-12 h-12 rounded-full flex items-center justify-center"
	onClick={() => setSearchBoxVisibility(currentVal => !currentVal)}
>
    <i className="fi fi-rr-search text-xl"></i>
</button>
```

`currentVal` is the first parameter that you can use while calling setState functions to access the most recent value of the state and to just toggle that current `Boolean` value, you can return the `currentVal` with `!` in the beginning.

Now if you click on the button, it should change the state value from false → true → false and so on. But you won’t see anything because the state is changing but its value doesn’t affecting the UI. So to show or hide the search box. We will add conditional classes to it. 

```jsx
<div className={"absolute bg-white w-full left-0 top-full mt-0.5 border-b border-grey py-4 px-[5vw] md:border-0 md:block md:relative md:inset-0 md:p-0 md:w-auto " + 
( searchBoxVisibility ? "show" : "hide" )}
>
    { 
				// search box input and icon
		}
</div>
```

Above code is just adding `show` or `hide` class on the basis of `searchBoxVisibility` state. `show/hide` classes are inside `index.css` file. If you didn’t get what is happening in above code. Well first, instead of `" "` for `className` there is `{ }` is the start and the end, which means inside it we can use JS. Then, we are simply concatenating class string using `“tailwind classes” + “class from the condition”` . To add condition I have used `ternary operator` which is a short form of `if else` that you can use inside JSX instead of actual `if else` and its syntax is like this `condition ? true case : false case`  . Now here are 2 things to remember while using classNames like this. First wrap you condition inside `( )` otherwise it will not concatenate with the string and second add a `[space]` at the end of the static classNames, like I have added space after `md:w-auto` at the end. This will make sure that the classes will have space after concatenation other wise after concatenation, if you don’t have space at the end, it will look like this `md:w-autoshow` instead of `md:w-auto show` and this will then not apply both styles to the element. 

So now you should be able to show/hide the search box by clicking on the search button. 

**Output** 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kuf5f965tpse8h9lzl1r.gif)

But there is an issue, if you just hide the search box, and then go to medium or large screen sizes. You will notice that there is no search box and neither the search button to show/hide the search box visibility. That is because we have `hidden` class to the button on medium screen so its not showing and since the state is false, the parent `div` has `hide` class because of the condition. To fix this, add `md:show` class to the search box’s `div` . So that on medium screens even if we have `hide` class, it will have show class which will overwrite the `hide` styles.

```jsx
<div className={"tailwind classes md:w-auto md:show " + 
( searchBoxVisibility ? "show" : "hide" )}
>
    { 
				// search box input and icon
		}
</div>
```

### Navbar - Sign in / sign up button

Now we want some sing in / sing up buttons + a “write” button in the navbar for easy navigation for the user. So let’s create that. Inside the `div` where we have search button to show/hide the search box. Add a “write” `Link` element which will be `hidden` in smaller screens.

```jsx
// search icon button 

<Link to="/editor" className="hidden md:flex gap-2 link">
    <i className="fi fi-rr-file-edit"></i>
    <p>Write</p>
</Link>
```

**Output**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dtunoxmeucjx7qkh2l1x.gif)


Now to create sign in / sign up buttons which will redirect the user to `/signin` or `/signup` route. Code this after the above code.

```jsx
// search icon button & write button

<Link className="btn-dark py-2" to="/signin">
    Sign In
</Link>
<Link className="btn-light py-2 hidden md:block" to="/signup">
    Sign Up
</Link>
```

`/signup` button/Link will be hidden in smaller screens as we don’t want to clutter our navbar on small devices. 

**Output**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tnr3dzqyg7ibicgefnv7.png)


## Route Setup

So after navbar, let’s setup some routes in react app, so that we can deliver sign in / sing up form and start working on those pages. Now since, ReactJS is a SPA means a simple page application, creating routes is difficult. So we will take help of “react-router” again in order to setup Routes. So open `App.jsx` and let’s setup Routes.

So in return first remove everything and add `Routes` Component which is provided by “react-router-dom”.

```jsx
import { Routes } from "react-router-dom";

const App = () => {

		return (
				<Routes>
						{ 
							// All the routes will come here 
						}
				</Routes>
		)

}
```

`Routes` Component basically allows you to setup routes for you projects. Now inside it we will use `Route` ( without `s` ) Component to create each and every routes. So inside it add this.

```jsx
<Routes>
    <Route path="/" element={<Navbar />}></Route>
    <Route path="/signin" element={<h1> Sing In Form </h1>}></Route>
    <Route path="/signup" element={<h1> Sing Up Form </h1>}></Route>
</Routes>
```

`Route` component lets you define the routes using 2 props.

- `path` - it defines the route path. In the above code we have created 3 Routes with `/`, `/signup`, `/signin` path. Where the react router deliver different Components.
- `element` - it renders whatever elements you pass inside it when the path is matched. For instance, If I now access `/signin` path. I will see a `h1` with “Sign in form” text.

After setting these 3 routes, if you go on these 3 routes, you will see the elements being render but there is a issue. Well basically, I want to show `<Navbar />` component to `/signin` and `/signup` routes as well, not only those but as we will work on other pages, in most pages we want the navbar. So how we can do that, well the simple fix is that inside each page, render `<Navbar />` separately, means add `<Navbar />` in all pages at the top before writing their HTML. But thats not a good practice. So instead of doing that we will go for second option, which is `Outlet`.

 `Outlet` is a component again provided by `react-router` which allows you to create nested routes and render multiple components at once. Let see how it works. So first of all we have to change our routes a little bit. 

```jsx
<Routes>
    <Route path="/" element={<Navbar />}> // `Navbar` will get render whenever the path matches i.e -> "/"
        <Route path="signin" element={<h1> Sing In Form </h1>} /> // h1 will get render on path -> "/signin"
        <Route path="signup" element={<h1> Sing In Form </h1>} /> // h1 will get render on path -> "/signup"
    </Route>
</Routes>
```

In the above code, I have nested the `signin` and `singup` route inside `/` path. Which will enable you to render 2 component because when you go to `/signin` let’s say, then 2 condition will be true, the first is `/` where react router will render `Navbar` and then the `signin` route where react router will render `h1`. But if you see your output, on all those 3 paths you will Navbar, but no h1. 

So first, congrats as we got the navbar on all these 3 paths but we lost the h1 component. Well there is nothing to worry about it. To render components in this type of nested routes. We use `Outlet` Component from “react-router”. We will add this `Outlet` on the parent route component. So in this case the parent route is `/` and its component is `Navbar`. So open `navbar.component.jsx` and at the end in return add `<Outlet />`  make sure to import that and also wrap your `<nav>` and `<Outlet />` in an empty component ( `<></>` ) so that react wont’s throw any error because in react you can only render 1 parent component.

This is how your `navbar.component.jsx's return` will look.

```
return (
    <>
        <nav className="navbar">
            // navbar code
        </nav>

        <Outlet />
    </>
)
```

So as long as we have `Outlet` in `Navbar` Component, we will see both routes on nested routes.

So thats sit for this blog, I hope you learned a lot by following this article. Make sure you follow me to not miss the next part whenever I will post it. Also if you want, you can checkout my [channel](https://www.youtube.com/channel/UCoygqHsdILWZFlfI5RMC-dw/), and show you love by subscribing me and you can watch the full tutorial of this part 1. If you have any doubt feel free to ask me in comments. Till then thanks for reading.

{% youtube J7BGuuuvDDk %}