Rushing Labs

Run Mongo + Express + React + Node with a Single Command

Almost two years ago, I posted a video covering a niche use-case of running a React and Express development environment from a single command. The video turned out to be the most successful video of my new YouTube channel, and still continues to push things forward.

If you would like to just see the code, skip ahead to the repo! :)

Strategy: What are we doing?§

Considering the previous video automated React & Express (and a touch of Node.js) behind a single command, the next step would seem to add Mongo DB to the mix.

So, Mongo DB + Express + React + Node.js, all behind a single command is what we're after. This is basically a monolithic MERN-stack app. While that doesn't follow the modern trends of service-oriented-architecture and microservices, it's still a useful way to run a MERN development environment.

The tool central to this functionality is the concurrently package. It allows us to run multiple processes from Node.js simultaneously.

Basically, the "scripts" section of our package.json is going to look a little something like this when we're done.

"scripts": {
    "dev": "concurrently --kill-others \"npm run server\" \"npm run start\" \"npm run db\"",
    "server": "echo Starting server...",
    "client": "echo Starting client...",
    "db": "echo Starting database..."

Install & Setup§

First, let's create our directory, easy-mern, and in there create an empty Node.js application.

mkdir easy-mern
cd easy-mern
npm init

Then inside our new Node app, we'll create a directory for the server, and we'll hold off on the front-end for now.

mkdir src
cd src
mkdir server

Install: React§

Let's quickly get our front-end off the ground. Still in easy-mern, we're going to run npx create-react-app client. It may seem like we need to create a folder for the React application, but doing it this way, create-react-app is going to create that directory for us.

cd client
npx create-react-app client

This may seem a little weird--once this command finishes we will have a full React application, built by create-react-app, inside our client directory. This includes it's own package.json and everything.

Install: npm packages§

Ok, with that done we can move onto the configurations that help us run the server and start the database. We want to cd .. back to our main directory, easy-mern.

First, we're going to install concurrently.

npm install concurrently --save

Then (if you don't already have it) we need to globally install nodemon. See this StackOverflow post for why this package needs a global install.

npm install -g nodemon

And then the rest of our packages...

npm install --save-dev body-parser dotenv express mongodb

Install: MongoDB§

At this point we need to break away from our terminal to install MongoDB. Since I'm running all of this from Windows, I just used the GUI installer. Use whatever you need for your OS.

The important piece is to keep track of your install directory and data directory.


Note: I'm installing MongoDB as a service.

You can keep track of the default data directory, or we'll create a custom one later to keep the path short.

After the install, we're dropped into Compass, where we can connect to our database, and create our first database and collection.

If MongoDB is running on your local system, you can use the default connection: mongodb://localhost:27017.

So that we'll have a database to read from later, we'll create one now in Compass. Click "Create Database" on the main window and fill in the details.

  • Database: website
  • Collection: sample-store

Start Mongo DB from CLI§

Now we need to figure out how to start Mongo DB from the terminal (CLI). Being able to do this, gives us our proof-of-concept for what to finally put in our package.json.

To learn how to do this, I read through this help article from Vithal Reddy. It helped me understand what was happening, but we'll cover the high points here.

For a shorter path to the data directory, I created a directory below the root of the drive. Not ideal, but keeps things usable.

mkdir C:\mongo-data

Then, we can open Command Prompt (cmd), and see how this works. After moving to the install directory where the mongod.exe is located, our becomes the following.

cd "C:\Program Files\MongoDB\Server\4.4\bin\mongod.exe"
.\mongod --dbpath C:\mongo-data

But this two-line approach is cumbersome to attempt in our package.json. So, a small adjustment and we are left with the following.

Test run in cmd

"C:\Program Files\MongoDB\Server\4.4\bin\mongod.exe" --dbpath C:\mongo-data

"db" script in package.json

"db": "cd C:\\Program Files\\MongoDB\\Server\\4.4\\bin && .\\mongod --dbpath C:\\mongo-data",

Connect the App§

Front-end: React§

Ok, now that we have Mongo DB installed and we know we can start it from the terminal...let's get back to our application. Keep in mind, our project directory should hold this shape:

- src/
  - client/
    - [React-app-files]
    - package.json
  - server/

First, let's make sure our front-end can talk to our server. We're going to add a proxy to /client/package.json. No need for any package, we only need to add "proxy": "http://localhost:5500", near the top of our package.json file.

Notice the port selection here. It is the same port our server will use, and it's important that it doesn't interfere with any port configurations for React or Mongo DB. Since we're using defaults (React: 3000, Mongo: 27017) we should be fine.

  "name": "easy-mern-frontend",
  "proxy": "http://localhost:5500",
  "dependencies": {
      /* dependency list */
  /* rest of file - removed for brevity */

Keep in mind, create-react-app has already built out a functioning React app for us, when we started. So, this is all we need to do for now.

Back-end: Express + Mongo§

Now let's move into \server

cd .. 
cd server

In our server directory, we're going to create three files: server.js, db.js, and routes.js.

touch server.js
touch db.js
touch routes.js

In \server\server.js, paste this code. Here, we are pulling in our dependencies, setting up some variables and pulling in the db.js and routes.js, and then kicking off server initialization.


const express = require('express'); // backend server
const envVar = require('dotenv').config(); // environment variables
const bodyParser = require('body-parser');
const app = express();

app.use(bodyParser.urlencoded({ extended: false }));

const port = 5500;
const initializeDatabases = require('./db');
const routes = require('./routes');

initializeDatabases().then(dbs => {
	// Initialize the application once database connections are ready.

	routes(app, dbs, express, path, fs)
        .listen(port, () => console.log(`Listening on port ${port}`) )

Now, put this code in \server\db.js. In the first two lines we pull in MongClient and establish our connection string, so we have the means to talk to Mongo DB. Then in connect() we are actually making the connection.

Finally, module.exports wraps our connection in a Promise, and notice that it attaches our database connection in an object to the key, siteData.


const MongoClient = require('mongodb').MongoClient;
const _conn_str = 'mongodb://localhost:27017/website';

function connect(url) {
	return MongoClient.connect(_conn_str, { useNewUrlParser: true, useUnifiedTopology: true }).then(client => client.db());
module.exports = async function() {
	let databases = await Promise.all([ connect(_conn_str) ]);
	return { siteData: databases[0] };

The last part to our back-end, \server\routes.js. We only define one route, and export it so server.js can pull it into its configuration. This single route answers to GET requests, and queries the sample-store collection in Mongo DB, for all of its documents.

Notice the app variable is provided from Express (you can see this by tracing it back to server.js), and our siteData key shows up again as this route returns the results from a Mongo DB query.

This file is where you would add more routes if you wanted to extend the back-end functionality of this working example.


module.exports = function(app, dbs) {

	app.get('/api/getData', (req, res) => {
			.toArray( (err, docs) => {
				if (err) {
				} else {

	return app;

Connecting the Scripts§

Now back in our main package.json (location: easy-mern\package.json), we can flesh out the rest of our scripts to start everything. So, here's the whole "scripts" section, and then let's break this down.

"scripts": {
    "dev": "concurrently --kill-others \"npm run server\" \"npm run start\" \"npm run db\"",
    "server": "cd src\\server && nodemon server.js",
    "client": "cd src && npm start",
    "db": "cd C:\\Program Files\\MongoDB\\Server\\4.4\\bin && .\\mongod --dbpath C:\\mongo-data"


This is where we use concurrently to run all of our scripts at once, and the --kill-others option will automatically kill all processes if any one of them dies. Since we want to run three things (front-end, back-end, database), then we associate those behind their own npm scripts, and we pass those scripts to concurrently.

Check concurrently's Usage section for more info:

"dev": "concurrently --kill-others \"npm run server\" \"npm run start\" \"npm run db\"",


Keep in mind, our directory structure for this project! Here, we cd to our server's directory, and start the process with nodemon. We start the server this way because nodemon will monitor our server for file changes. If any are detected, it automatically restarts the server for us! :D

nodemon, see:

"server": "cd src\\server && nodemon server.js",


Our client script is pretty straightforward, but remember create-react-app created another package.json inside our client directory. So the npm start portion of this command will run the start script in that file--not this one.

"client": "cd src\\client && npm start",


Finally, we have the database script. This is mostly a copy/paste of what we created earlier by making sure we could start the database from the terminal. We've added double-backslashes for escaping. Still, we cd into Mongo's install directory using the full path, and join this with && to run .mongod with the --dbpath option set.

"db": "cd C:\\Program Files\\MongoDB\\Server\\4.4\\bin && .\\mongod --dbpath C:\\mongo-data"

All Together Now!§

So now, from the terminal, sitting in our easy-mern/ directory, we should be able to issue a single command to start all three pieces of our application!

npm run dev

In your terminal you should see output from:

  • concurrently showing it's running the configured scripts
  • react-scripts reporting that React is starting
  • A few lines showing nodemon started the server
  • And finally, MongoDB dumps a bunch of information without config to turn down verbosity


You may have noticed we put hard-coded, full directory paths in the package.json and that could be problematic when/if things change. Well, we can utilize variables in our package.json, but beware--this lacks some cross-platform abilities--so use with caution!

Basically, npm allows variables to be accessed via the prefix, $npm_package_*, followed by an underscore pattern for each level of objects configured in package.json. For example, $npm_package_yourvar_isNested. However!, on Windows the single, leading $ is exchanged for surrounding %%, like %npm_package_yourvar_isNested%.

On a *nix-like system:

/* Accessed with... */
"scripts": {
    "db": "cd $npm_package_config_mongodir"
/* and then defined as... */
"config": {
    "mongodir": "~\\my\\mongo\\location",
    "mongodata": "~\\my\\data"

On Windows:

/* Accessed with... */
"scripts": {
    "db": "cd %npm_package_config_mongodir%"
/* and then defined as... */
"config": {
    "mongodir": "C:\\Program Files\\MongoDB\\Server\\4.4\\bin",
    "mongodatadir": "C:\\mongo-data"

For a more in-depth explanation, take a look at this article from Brian Childress, and the supporting (ever-present) StackOverflow post explaining the environment differences.


"Run MongoDB as a Service in Windows", Vithal Reddy -

"Variables in package.json", Brian Childress -