Online Food Ordering App (1)
Tags: express, node, react, reactnative
Published: 2020-12-16 18:56:20

*<span>Photo by <a href="https://unsplash.com/@abillion?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">abillion</a> on <a href="https://unsplash.com/s/photos/food-mobile-app?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></span>*



Today we are going to build an online food ordering app called "Gourmet". The app will be made of a REST API as the back-end and 2 react apps as the front-end, namely a react Admin Panel and a customer facing react-native mobile app.

Throughout the project, we are going to use the TDD approach, ES6, and CI/CD among other things.


### Features
The following are the requirements for our project, but you can expand it and add more features as you wish.

- Authentication: a customer should be able to signup, login and logout
- View menu and place order: a customer should be able to view the restaurant's menu, select the items she wants then place an order.
- View orders and order details: a customer should be able to view the orders she has placed and their details.
- Update order: the admin should be able to view all the orders placed, their details and should be able to update a specific order.


### Project steps
#### 1. [Backend - Project Setup]()
#### 2. [Backend - Authentication](https://dev.to/the22mastermind/online-food-ordering-app-2-28po)
#### 3. [Backend - Place order]()
#### 4. [Backend - View orders list and view a specific order]()
#### 5. [Backend - Update order]()
#### 6. [Frontend - Authentication]()
#### 7. [Frontend - Place order, view orders list, and view order details]()


### 1. Backend - Project Setup

To kick things off, create a github repo, copy your repo's URL, open your terminal, navigate to a directory where you wish your project to reside then enter the following command `git clone https://github.com/<YOUR_GITHUB_USERNAME>/<YOUR_REPO_NAME>.git`.
Alternatively, you could use GitHub CLI or SSH if you want.

After the above steps, enter `ls` command and you should see the name of your repo. Enter `cd YOUR_REPO_NAME` to go into your project directory and we are good to go.


**Prerequisites**

Make sure you have [Node.js v10+](https://nodejs.org/en/) installed before proceeding by running `node -v`.


- Run `git checkout -b chore-project-setup-init` to create a new branch for our first task of project setup.
- Run `yarn init -y` to initialize a new project. Alternatively, you could use `npm init` but I prefer yarn for it's easy to read CLI output, faster package installation speed, and offline mode among other things. Google **yarn vs npm** to find out the pros and cons one has over the other.
- Open your project in VSCode by running `code .` in the root directory of your project.


**Dependencies**

- Run `yarn add express body-parser cors dotenv joi jsonwebtoken lodash make-runnable moment morgan pg pg-hstore sequelize sequelize-cli sequelize-test-helpers bcrypt` to install the packages we are going to be using.

- Run `yarn add @babel/core @babel/node @babel/plugin-syntax-class-properties @babel/plugin-transform-runtime @babel/preset-env babel-eslint babel-plugin-istanbul` to install babel and its plugins which will help to convert our ES6 Javascript code into backwards compatible versions for older browsers and environments.


**Dev-dependencies**

- Run `yarn add --dev eslint @babel/register chai chai-http coveralls cross-env mocha mocha-lcov-reporter nodemon nyc` to install dev-dependencies which are packages used mainly in development and testing environments.


**Configure ESLint**

- Run `yarn run eslint --init` to start ESLint configuration.
- ![carbon](https://dev-to-uploads.s3.amazonaws.com/i/lg9ur5618ee0szbaaiug.png)
 
- ![carbon (1)](https://dev-to-uploads.s3.amazonaws.com/i/mgcg4xllxwauptakiauz.png)
 
- ![carbon (2)](https://dev-to-uploads.s3.amazonaws.com/i/42041f3mry7978mj5wj5.png)
 
- ![carbon (3)](https://dev-to-uploads.s3.amazonaws.com/i/6aobld29re5jqybm0z5c.png)
 
- ![carbon (4)](https://dev-to-uploads.s3.amazonaws.com/i/o25gbc7est8lv5gkxpuj.png)
**Select Node only**

- ![carbon (5)](https://dev-to-uploads.s3.amazonaws.com/i/79npy9btr8l1wi1x0hzd.png)
 
- ![carbon (6)](https://dev-to-uploads.s3.amazonaws.com/i/r0fv7l67r6b3mhtblli4.png)
 
- ![carbon (7)](https://dev-to-uploads.s3.amazonaws.com/i/xwuy04b2mhyke311k8mm.png)
 
If you are asked to install additional ESLint dependencies, select yes and Enter. This last step should look like the image below.
- ![carbon (8)](https://dev-to-uploads.s3.amazonaws.com/i/9qq70sjd31n4gir5z326.png)
 
- In the root directory of your project, you should see a new config file called .eslintrc.json. Learn more about ESLint [here](https://eslint.org/docs/user-guide/getting-started)

**Note:** In the root directory of our project, there's a new file called package-lock.json will was created by npm after installing the additional ESLint packages. We are now using 2 package managers (yarn and npm). This is not ideal.

Let's stick to one (i.e. yarn).

- Delete **package-lock.json** file and **node_modules** directory
- In the terminal, make sure you are in the root directory of your project and run `yarn install` to install all our dependencies afresh


**Configure package.json**

- Open package.json file in VSCode and the following scripts key with start and dev command to start our server in production and development environments respectively

![carbon (9)](https://dev-to-uploads.s3.amazonaws.com/i/39dftgy6rix8a09t367s.png)
 
- Let's create that server.js file. In your terminal run `mkdir src && touch src/server.js`. You should see an empty server.js file inside src dir.
- Make sure to update your main entry file to `server.js` as well.
![carbon (10)](https://dev-to-uploads.s3.amazonaws.com/i/9n0xesy54h36sokw1nb0.png)


**Configure server.js**

Let's test if our server can start up. Add the following statement `console.log('Server is up and running');` in server.js and save. At this point you should see a ESLint warning because of that console.log() statement.

In the terminal, navigate to the project's root dir and run `yarn dev`. You should see 'Server is up and running' being logged in the terminal. Change 'Server is up and running' in server.js to 'Server is up!' and save, the server should restart automatically to reflect your new changes. This is made possible by the nodemon package we specified in the dev script and it's going to allow us to focus on building our api without worrying about stopping and starting our server each time we make changes.

Create a .babelrc configuration file in your project's root dir and paste the following inside:
![carbon (11)](https://dev-to-uploads.s3.amazonaws.com/i/eqp6mj1tkr58b5jjx0xg.png)
 
Don't forget to replace 14 with your version of Node.

At this point our server is not doing much. Let's change that.

- In your terminal run `Ctrl+C` to stop the server.
- Create a .env file in your project's root dir and inside put PORT=4000 and save. This will be the port number our server will use in development and local testing environments. When we go into CI or production, the port will be provided dynamically by the platform we will be using, hence the `process.env.PORT` instead of hardcoding the port value. This .env file will also allow us to keep track of all the sensitive keys, secrets, and passwords that should not be exposed to the public. Remember to keep this file outside of version control systems. Speaking of which, let's do it right away.

  - Create a .gitignore file in your project's root dir and add the following inside:
  ![carbon (12)](https://dev-to-uploads.s3.amazonaws.com/i/idmsowtpsfeylmwzxa3o.png)
  - Notice `node_modules/` and `.env`. Basically, everything we put in this file will not be committed to github. Check out [this article](https://www.freecodecamp.org/news/gitignore-what-is-it-and-how-to-add-to-repo/) to learn more.
- Replace the console statement inside server.js with the following code and save:
![carbon (13)](https://dev-to-uploads.s3.amazonaws.com/i/wa9fs1ktc4hqf57cl5lq.png)
 
- Run `yarn dev` and you should see the server running with message `Live at 4000`
- Open your browser and navigate to [http://localhost:4000](http://localhost:4000) and you should see the following response: `{"error":"Route not found"}` which is exactly what we expect since we haven't yet implemented our API routes.

If you reached this step, **CONGRATULATIONS!**:tada::tada::tada:

Just 1 or 2 things remaining and then we deploy our API :fire:


**Tests**

So far we have managed to implement the substructure of our API. Next up we are going to write tests, setup Continuous Integration and Continuous Delivery (CI/CD).

I recommend deploying your app early on because it helps to detect and debug issues when your codebase is still small. Another advantage is that you can ship features that your users can start using without waiting for the entire app to be done.

Okay, let's do it.

- In the project's root dir, create a new dir `tests` and inside tests create a file called `server.js` and paste the following code inside:
![carbon (15)](https://dev-to-uploads.s3.amazonaws.com/i/7ozkd6pmpxsxj0gtqd8n.png)

- Update your scripts in package.json and add a `dev-test` command like:
![carbon (16)](https://dev-to-uploads.s3.amazonaws.com/i/sn8rxorcm6wxixydnayc.png)

This is the command we will use in development to run our tests which will produce a nice table in terminal showing test coverage. We need another command for our CI service.

- Add the `test` command like below:
![carbon (17)](https://dev-to-uploads.s3.amazonaws.com/i/zjduas05hibi2mq70aji.png)

- When our hosted CI service will finish running the above `test` command, it will create a coverage directory which contains the coverage results of our tests.

- Check out [this link](https://docs.travis-ci.com/user/tutorial/#to-get-started-with-travis-ci-using-github) to add Travis-ci to your github repo. There's a lot more you can do with Travis, make sure to check out their [docs](https://docs.travis-ci.com/).

- Create a `.travis.yml` configuration file in your project root directory and paste the following inside:
![carbon (19)](https://dev-to-uploads.s3.amazonaws.com/i/xe3zqp692al3ky2bghtt.png)

- Time to commit our changes.
    - Run `git add .`
    - Run `git commit -m "chore(project-setup-init):pre-deployment"`
    - Run `git push origin chore-project-setup-init`

- Back on github, raise a PR and you should see your branch build successfully.
 

**Deployment**

We want our production build to be based off the master/main branch of our github repo. Basically, we will be creating new branches, build features, test locally, commit to github then test with Travis-CI, then merge to main branch which will trigger a new build of our production build. Yes, I said build of a build :laughing:.

- Signup on [Heroku](https://signup.heroku.com/) and login
- Create a new app, then switch to the **deploy** tab then scroll down to deployment method and select GitHub and you should see a Connect to GitHub option below
- Select your github username and your github repo. Type the name of your repo and hit search if it doesn't show up then click `connect`
- You should see that your app is now connected to github and a **Automatic deploys** option below
- on **Automatic deploys** select main/master branch, tick `Wait for CI to pass before deploy`, then hit **Enable Automatic deploys** button and that's it.

- Head back to your PR on github and merge it. Travis-CI should build our merge commit successfully which will then trigger our production build on heroku.
- On heroku, the **Activity** tab should show a **Build succeeded** status.
- Hit **Open app** button and we should see our `{"error":"Route not found"}` error message. This is good. it's a good error :smile:.


**Conclusion**

Our API is now live :fire:.

In the next post we will focus on implementing authentication namely signup, login, and logout functionalities. We will cover the concepts of JWT token, Postgres, and Sequelize ORM among other things.


Thank you for reading, see you in the next one!

[Demo Link](https://gourmetfood-api.herokuapp.com/)

[GitHub Repo](https://github.com/the22mastermind/gourmet-api/tree/chore-project-setup-init)