Boilerplate For Mern Project

#mern #nodejs #react #dev
  • Initialise a new Github/Bitbucket Repository
  • Clone it to your machine (SSH)
  • Make sure you have a NodeJS with LTS installed, otherwise nvm
  • Now follow the commands given below, after opening repo in VScode

Backend


touch backend
cd backend
npm init -y
npm i express dotenv cors
npm i -D nodemon
  • Add scripts to your package.json
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node app.js",
    "dev": "nodemon app.js"
  },
  • Create app.js and paste following code
const express = require("express");
const app = express();

require("dotenv").config();
const PORT = process.env.PORT;

app.get("/api", (req, res) => {
  res.json({ users: ["himanshu", "abhishek", "ankit"] });
});

app.listen(PORT, () => {
  console.log(`server running successfully on PORT: ${PORT}`);
});
  • Create a .env and type PORT=3000 in it.

CORS

Allow requests from React Server to avoid CORS errors.

// handle CORS
const cors = require("cors");
const corsOptions = {
  origin: "http://localhost:5173",
  methods: "GET, POST, PUT, DELETE, PATCH, HEAD",
  credential: true,
};
app.use(cors(corsOptions));

Global Error Handling

  • Add following line just before app.listen(PORT) in app.js
// Global Error Handler
app.use((err, req, res, next) => res.status(500).json({ error: err.message }));
  • And use this handler to wrap around any async function to avoid repetitive try and catch.
  • utils/asyncHandler.js
function asyncHandler(fn) {
  return (req, res, next) => {
    return Promise.resolve(fn(req, res, next)).catch(next);
  };
}

module.exports = asyncHandler;

Frontend


  • Now cd out of that folder to the main folder to create a react project.
npm create vite@latest

# project name: frontend
# react
# javascript
# remove additional files
  • Let's first try fetching data from backend and display it on react app
import React, { useState, useEffect } from "react";

function App() {
  const [backendData, setBackendData] = useState([]);

  const fetchBackendData = async () => {
    try {
      const response = await fetch("http://localhost:3000/api");
      const resData = await response.json();
      setBackendData(resData.users);
    } catch (error) {
      console.error("Error fetching backend data:", error);
    }
  };

  useEffect(() => {
    fetchBackendData();
  }, []);

  return (
    <div>
      {backendData.length > 0 ? (
        backendData.map((user, index) => <div key={index}>{user}</div>)
      ) : (
        <p>Loading...</p>
      )}
    </div>
  );
}

export default App;
  • If everything works fine on npm run dev, we can move to the next steps and remove all the code for testing API. Otherwise backtrack.

Tailwind (Optional)


Now let's add Tailwind CSS with Prettier formatting.

First ensure you have the following VSCode Extensions Installed

1. ES7+ React/Redux/React-Native snippets
2. ESLint
3. Prettier - Code Formatter
4. Tailwind CSS IntelliSense
  • Run the following commands inside frontend folder
npm install -D tailwindcss postcss autoprefixer prettier prettier-plugin-tailwindcss
npx tailwindcss init -p
  • Configure your template paths in tailwind.config.js
export default {
  content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
};
  • Configure or create postcss.config.js
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};
  • Also disable prop-type rule from eslint eslint.config.js
    rules: {
      ...js.configs.recommended.rules,
      ...react.configs.recommended.rules,
      ...react.configs["jsx-runtime"].rules,
      "react/prop-types": 0,
      ...reactHooks.configs.recommended.rules,
      "react/jsx-no-target-blank": "off",
      "react-refresh/only-export-components": [
        "warn",
        { allowConstantExport: true },
      ],
    },
  • Add this file to format tailwind classes using prettier .prettierrc.json
{
  "plugins": ["prettier-plugin-tailwindcss"]
}
  • Add tailwind directives to your CSS main.css
@tailwind base;
@tailwind components;
@tailwind utilities;
  • And import it to main.jsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App.jsx";
import "./main.css";

createRoot(document.getElementById("root")).render(
  <StrictMode>
    <App />
  </StrictMode>,
);
  • Finally add some tailwind to your App.jsx and check if everything is working fine.
function App() {
  return (
    <>
      <div className="flex to-blue-600">Lorem ipsum dolor sit amet.</div>
    </>
  );
}

export default App;

That's it! You can git push and start working on your project!