HOW TO BUILD A MEVN APP WITH VITE FRONTEND (PART 1)
Tags: mevn, node, mongodb, express
Published: 2023-08-07 15:56:26

Full-stack web development describes the process of building the frontend and backend of a web application. It uses several technologies to accomplish this task; these technologies are collectively referred to as full-stack web development stack. There are several full-stack web development stacks, but we will be discussing the MEVN stack.

This is a three-part tutorial; try to understand each step and have fun while at it. See you on the other side!

---

## **WHAT IS MEVN?**
MEVN is a full-stack JavaScript web development stack that comprises MongoDB, Express.js, VueJS, and NodeJS. It has grown in popularity in recent times, and it is a highly scalable stack. Its scalability makes it a great choice for developers building small projects and enterprise-level applications.

**MongoDB** is a document-based database that stores data in a JSON-like format.

**Express.js** is a lightweight Node.js web application framework. It provides robust features and utilities that make building APIs and routing easy.

**Vue.js** is a modern progressive frontend JavaScript framework used for building user-friendly interfaces. It is designed to be approachable and easy to integrate for building interactive and dynamic web applications.

**Node.js** is a server-side JavaScript runtime environment that allows developers to run JavaScript code on the server. It is asynchronous, event-driven, and highly scalable for developing servers and databases.

---

## **WHAT IS VITE?**
Vite is a build tool and development server that allows for quick and efficient frontend development. It is frequently used with modern frontend frameworks such as Vue.js, React, and Svelte.

---

## **BUILDING OUR APPLICATION**
We will be building a simple MEVN CRUD app. First, create a project directory and name it `mevn-crud`. This is where all the magic will be done, and I am rooting for you.

---

## Create server (backend) with Node.js and Express.js.
Inside your project directory, create a folder named `server` and navigate into it on your terminal.

Initialise npm: 
```
npm init -y
```
To use ECMAScript modules, add `"type": "module"` to your generated `package.json` file. Your `package.json` should look like this:
```
{
  "name": "server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

```

Install necessary dependencies:
```
npm i express mongoose body-parser cors dotenv
```

We will also need `nodemon` and `concurrently` for a better development experience. Nodemon reloads the server automatically whenever there is a change in any server file. Concurrently, enable us to run multiple node commands together.

Install `nodemon` and `concurrently` as dev dependencies:
```
npm install --save-dev nodemon concurrently
```

Update `scripts` in `package.json`:
```
"scripts": {
    "dev:server": "nodemon index.js --ignore ../client/",
    "dev:client": "npm run dev --prefix ../client/",
    "dev": "concurrently \"npm run dev:server\" \"npm run dev:client\""
  },
```
We need an entry point for our server now that we have finished installing our dependencies and configuring our `package.json` file.

Create a new file called `index.js` and add the following code to it:
```
// index.js
import express from "express";

const app = express();
const PORT = 3000;

app.get("/", (req, res) => {
  res.send("Hello World");
});

app.listen(PORT, () => {
  console.log(`App is running on http://localhost:${PORT}`);
});
```

Run `npm run dev:server` in your `server` folder to start your server, and visit `http://localhost:3000/`, where you will see `Hello, World!` displayed.

Kudos! Your server is set.

---

## Setup MongoDB database and connect the server using mongoose
**Step 1.** Create an account or sign in to [MongoDB Atlas](https://www.mongodb.com/atlas/database).

**Step 2.** On the `Deploy your database` page, select the `M0 free` plan, allow other default settings, and click on the `Create` button.
![Deploy your database page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uilzin8mlt218be120wu.png)

**Step 3.** Highlight the `Username and Password` option if it is not already highlighted. Specify a username and password and click on `Create User` button. _Keep your password safe; you will need it later._
![Username and password setup](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6fves1os9627fq2g4nss.png)

**Step 4.** Scroll down and highlight `My Local Environment`. Input `0.0.0.0/0` under IP address and click on the `Add Entry` button. This will allow access to your Atlas cluster from anywhere. Click on `Finish and Close` when you are done and go to overview.
![Allow access setting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e9njimp1w6g0fe77we7t.png)

**Step 5.** Locate and click on the connect button under your cluster.
![Connect cluster](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qc1ycv38r24flagywykh.png)

**Step 6.** On the displayed menu, click on `Drivers` under `Choose Your Application`. Copy the Mongo URL, which starts with `mongodb+srv`.

**Step 7.** Go back to your application and create a `.env` file in your `server` folder and add `MONGO_URI` and `PORT`.
```
MONGO_URI='<mongdb_uri>'
PORT=3000
```> Ensure that you replace the password in your `mongdb_uri` with the user password you generated.

**Step 8.** Replace your `index.js` code with the following:
```
// index.js
import express from "express";
import mongoose from "mongoose";
import cors from "cors";
import bodyParser from "body-parser";
import dotenv from "dotenv";

const app = express();
dotenv.config();

app.use(cors()); // to allow cross origin requests
app.use(bodyParser.json()); // to convert the request into JSON
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/xwww-

// Connect to database
mongoose
  .connect(process.env.MONGO_URI, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  })
  .then(() => console.log("MongoDB database Connected..."))
  .catch((err) => console.log(err));

app.listen(process.env.PORT, () =>
  console.log(`App is running on http://localhost:${process.env.PORT}`)
);

> 
```
Run `npm run dev:server` to check if everything is working fine. `MongoDB database Connected...` will be printed on your terminal if the server is properly connected to Mongo Atlas.

---

## Create a basic schema with mongoose
Create a `models` folder inside your `server` folder and create a `Todo.js` file inside it. Add the following code to create a schema:
```
import { Schema, model } from "mongoose";

const TodoSchema = new Schema({
  title: {
    type: String,
    required: true,
  },
  description: {
    type: String,
    required: true,
  },
});

const Todo = model("todo", TodoSchema);

export default Todo;
```

---

## Create API routes
Create `TodoList.js` inside `/routes/api` folder in the `server` folder. Use the following code to create CRUD API endpoints:
```
//TodoList.js
import { Router } from "express";
import Todo from "../../models/Todo.js";

const router = Router();

router
  .route("/")
  
// Get all todos in the database
  .get(async (_req, res) => {
    try {
      const todoList = await Todo.find();
      if (!todoList) throw new Error("No Todo List found");
      res.status(200).json(todoList);
    } catch (error) {
      res.status(500).json({ message: error.message });
    }
  })

  //Post request creates a new todo in the database
  .post(async (req, res) => {
    const newTodo = new Todo(req.body); // create a new instance of the Todo model
    try {
      const todo = await newTodo.save(); // Save created todo
      if (!todo) throw new Error("Something went wrong saving the Todo");
      res.status(200).json(todo);
    } catch (error) {
      res.status(500).json({ message: error.message });
    }
  });

router
  .route("/:id")

  // Update the todo with the given id
  .put(async (req, res) => {
    const { id } = req.params;
    try {
      const updated = await Todo.findByIdAndUpdate(id, { ...req.body });
      if (!updated) throw Error("Something went wrong ");
      res.status(200).json(updated);
    } catch (error) {
      res.status(500).json({ message: error.message });
    }
  })

  // Delete the todo with the given id
  .delete(async (req, res) => {
    const { id } = req.params;
    try {
      const removed = await Todo.findByIdAndDelete(id);
      if (!removed) throw Error("Something went wrong ");
      res.status(200).json(removed);
    } catch (error) {
      res.status(500).json({ message: error.message });
    }
  })

  // Get the todo with the given id
  .get(async (req, res) => {
    const { id } = req.params;
    try {
      const todo = await Todo.findById(id);
      if (!todo) throw new Error("No Todo found");
      res.status(200).json(todo);
    } catch (error) {
      res.status(500).json({ message: error.message });
    }
  });

export default router;

```

Import the `TodoList.js` file into the `index.js` file and create an API route for it. Add the following code to `index.js`:

```
// index.js

import TodoListRoutes from "./routes/api/TodoList.js";

---

// Create routes
app.use("/api/todoList", TodoListRoutes);

```
Use any preferred API testing tool, like Insomnia, to test your API. Ensure all requests (POST, GET, PUT, and DELETE) are working.

---

## **Summary**
Wow! You've made great strides. You have successfully created a Node.js/Express.js CRUD app with a Mongo Atlas connection. Take a break and return for Part 2, where we will set up our Vue3 client (frontend) to consume our API.

Github Repository: https://github.com/isonguyom/mevn-crud
Live Demo: https://mevn-crud.onrender.com/


If you have any questions or additions, please leave them in the comment section below.