paint-brush
MERN Stack: A Guide for New Developersby@nkko
149 reads

MERN Stack: A Guide for New Developers

by Nikola BalicSeptember 3rd, 2024
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

The MERN stack has emerged as a powerful framework for modern web development. It combines MongoDB, Express.js, React.js and Node.js. This guide will walk you through setting up a MERN Stack application efficiently. We'll use a Creator Relationship Management (CRM) App as our example.
featured image - MERN Stack: A Guide for New Developers
Nikola Balic HackerNoon profile picture

The MERN stack has emerged as a powerful framework for modern web development, combining MongoDB, Express.js, React.js, and Node.js. This guide will walk you through setting up a MERN stack application efficiently, leveraging a pre-configured repository and streamlined development environment management.

Overview of MERN Stack

The MERN stack comprises four key technologies:


  1. MongoDB: A flexible, document-based NoSQL database
  2. Express.js: A minimal web application framework for Node.js
  3. React.js: A JavaScript library for building dynamic user interfaces
  4. Node.js: A JavaScript runtime for scalable server-side applications


Each component plays a crucial role in creating dynamic and interactive web applications.

Setting Up the Development Environment

Prerequisites

  • Basic JavaScript knowledge
  • An Integrated Development Environment (IDE) like Visual Studio Code
  • Docker installed for containerized development
  • Daytona for managing your dev environments

Getting Started with the MERN App

We'll use a Creator Relationship Management (CRM) App as our example. This full-stack application is designed for influencers, podcasters, and creators to manage client relationships efficiently.

Setting up MongoDB Cluster

Follow the MongoDB Atlas Getting Started guide to create a cluster and obtain your MongoDB URI.


Note: If you encounter connection issues, allow access from anywhere in your cluster's Network Access settings.

Configuring the Development Workspace

We'll use Daytona to automate the setup of a Node.js dev environment with necessary tools and port forwarding based on our starter project.

Cloning and Setting Up Your MERN Stack Environment

  1. Create a workspace:

    daytona create https://github.com/daytonaio-experiments/starter-mern-saas.git
    
  2. Set your preferred IDE:

    daytona ide
    
  3. Open the workspace:

    daytona code
    
  4. Start the backend server:

    • Create a .env file in the backend directory with your MongoDB UR (you can find it in Atlas dashboard)I:

      MONGO_URI="mongodb+srv://<username>:<password>@SOMETHING.SOMETHING.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0"
      
    • Run the server:

      cd backend && npm run dev
      
  5. Start the frontend:

    • Create a .env file in the frontend directory:

      VITE_BACKEND_URL="http://localhost:8000/api/customers/"
      
    • Run the frontend:

      cd frontend && npm run dev
      


Your MERN app should now be running.

Repository Structure

The repository is organized into:


  • Backend: Server-side code (Node.js and Express.js)
  • Frontend: Client-side application (React.js and Tailwind CSS)
  • .devcontainer: Configuration files for the development environment

Streamlined Setup with .devcontainer

The .devcontainer/devcontainer.json file provides a predefined development environment. Here's the configuration:


{
    "name": "Node.js, Express, React, MongoDB & Tailwind",
    "image": "ubuntu:22.04",
    "features": {
        "ghcr.io/devcontainers/features/common-utils:2.4.7": {
            "username": "daytona",
            "userUid": 1000,
            "userGid": 1000,
            "configureZshAsDefaultShell": true
        },
        "ghcr.io/devcontainers/features/node:1": {
            "nodeGypDependencies": true,
            "version": "lts",
            "nvmVersion": "0.40.0"
        },
        "ghcr.io/devcontainers/features/git:1": {}
    },
    "overrideFeatureInstallOrder": [
        "ghcr.io/devcontainers/features/common-utils",
        "ghcr.io/devcontainers/features/git",
        "ghcr.io/devcontainers/features/node"
    ],
    "portsAttributes": {
        "5174": {
            "label": "Frontend",
            "onAutoForward": "notify"
        },
        "8000": {
            "label": "Backend",
            "onAutoForward": "ignore"
        },
        "27017": {
            "label": "MongoDB",
            "onAutoForward": "ignore"
        }
    },
    "customizations": {
        "vscode": {
            "extensions": [
                "mongodb.mongodb-vscode",
                "dbaeumer.vscode-eslint",
                "esbenp.prettier-vscode",
                "bradlc.vscode-tailwindcss",
                "davidanson.vscode-markdownlint"
            ]
        }
    },
    "workspaceFolder": "/workspaces/starter-mern-saas",
    "onCreateCommand": "npm install -g nodemon",
    "postCreateCommand": "cd backend && npm install && cd ../frontend && npm install",
    "remoteUser": "daytona"
}


This configuration ensures a consistent development environment across different machines.

Customizing the MERN Application

Adding New Routes

  1. Create a new route file (e.g., productRoutes.js):
const express = require('express');
const router = express.Router();
const productService = require('../service/productService');

router.get('/products', async (req, res) => {
    try {
        const products = await productService.getAllProducts();
        res.status(200).json(products);
    } catch (error) {
        res.status(500).json({ message: error.message });
    }
});

module.exports = router;


  1. Implement controller functions in a service file (productService.js):
class ProductService {
    async getAllProducts() {
        // Logic to fetch all products
    }
}

module.exports = ProductService;


  1. Register the new route in app.js:
const productRoutes = require('./routes/productRoutes');

app.use('/api', productRoutes);

Adding New React Components

  1. Create a new component file (e.g., ProductList.jsx):
import React, { useEffect, useState } from 'react';
import axios from 'axios';

const ProductList = () => {
    const [products, setProducts] = useState([]);

    useEffect(() => {
        const fetchProducts = async () => {
            const response = await axios.get('/api/products');
            setProducts(response.data);
        };
        fetchProducts();
    }, []);

    return (
        <div>
            <h1>Products</h1>
            <ul>
                {products.map(product => (
                    <li key={product.id}>{product.name}</li>
                ))}
            </ul>
        </div>
    );
};

export default ProductList;


  1. Integrate the component in App.jsx:
import React from 'react';
import ProductList from './components/ProductList';

function App() {
    return (
        <div className="App">
            <ProductList />
        </div>
    );
}

export default App;

Conclusion

You've now set up a MERN stack application, cloned an example repository, and learned how to customize both the backend and frontend. This streamlined setup process allows you to focus on developing and enhancing your application without worrying about environmental inconsistencies.


Happy coding, and enjoy your development journey with the MERN stack!