Setting up a Full Stack React & Node.js Project: A Comprehensive Cheat Sheet
Embarking on a new full stack React & Node.js project can be both exciting and daunting. To ensure a smooth and efficient setup process, I have compiled a step-by-step cheat sheet that will guide you from creating your project folder to fine-tuning your frontend and back-end configurations.
In this article, you will learn how to create a project folder, set up your server for development with the help of essential dependencies such as concurrently, and initialize a Git repository. We will also cover setting up your frontend using Create React App or Vite, configuring a proxy for seamless communication between your frontend and back-end, and organizing your files using best practices. Furthermore, it is important to note that the appendices at the end of this article contain useful and crucial information. Please be sure to review them carefully.
By following the instructions in this cheat sheet, you will be able to dive into your full stack project with confidence, laying a strong foundation for your application development journey. So, let us get started and happy coding!
Setting Up the Server
- Create a folder for your project using lowercase letters and hyphen-separated words.
Naming conventions can vary depending on personal preference and team standards. However, there are some general best practices that you can follow to ensure your project’s folder names are clear and consistent. Here
are a few suggestions:1. Use lowercase letters — it’s a common practice to use only lowercase letters when naming folders in web development. This is because Unix-based systems are case-sensitive, so using lowercase letters ensures that your files and directories will be accessible across different platforms. See also the appendix at the end of this document.
2. Use hyphens or underscores — when you need to separate words in your folder name, it’s a good idea to use either hyphens (-) or underscores (_). Both are commonly used, but hyphens are generally preferred since they are more readable and easier to type.
3. Use descriptive names — your folder name should be descriptive and concise, so anyone who reads it can quickly understand what it contains. Avoid using abbreviations or acronyms that may not be clear to everyone.
Based on these best practices, a good naming convention for a project folder could be something like ‘my-project’ or ‘my_app’. Again, the important thing is to choose a convention that is clear and consistent for you and your team.
2. Open the folder in VS Code.
3. Create a .gitignore file with the following content:
# Dependencies
node_modules
# Build/Production
/client/build
# Environment variables
*.env*
!.env.example
# Logs
/logs
*.log
# Editor specific
.vscode
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
# Temporary files
*.sw?
*.cache
.DS_Store
# Generated / Auto-generated files
/dist
/dist-ssr
.eslintcache
# Configuration
.prettierrc
4. In the terminal, run npm init
. Set the description
, entry point
to server.js
, author
to your name, and license
to MIT
.
Both licenses, ISC & MIT, allow users to use, copy, modify, and distribute the software, including for commercial purposes, without any requirement to share their changes.
The MIT license includes a disclaimer of liability, while the ISC license does not.
5. Install concurrently as a development dependency, by running npm i -D concurrently
.
6. Install express
and dotenv
by running npm i express dotenv
.
7. Create a config
folder and a config.env
file inside it.
8. Add the following content to config.env
:
NODE_ENV=development
PORT=5000
9. To use ES modules instead of CommonJS, add "type": "module",
to your package.json file after "main": "server.js",
.
10. Create a server.js file with the following content (for ES modules):
import express from 'express';
import dotenv from 'dotenv';
dotenv.config({ path: './config/config.env' });
const app = express();
app.get('/', (req, res) => res.send('Server running'));
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`));
If you are using Common JS Modules, use this:
const express = require('express');
const dotenv = require('dotenv');
dotenv.config({ path: './config/config.env' });
const app = express();
app.get('/', (req, res) => res.send('Server running'));
const PORT = process.env.PORT || 5001;
app.listen(PORT, console.log(`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`));
11. Update the scripts section in package.json (remove the test script):
If you are intending to use CRA (create-react-app), use this:
"start": "node server.js",
"server": "node --watch server.js",
"client": "npm start --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\""
If you are intending to use Vite, use this:
"start": "node server.js",
"server": "node --watch server.js",
"client": "npm run dev --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\""
12. In the terminal, run npm run server
and verify that you don't have any errors.
14. Open http://localhost:5000
in your browser to check if the server is running correctly and verify you see there “Server running”.
Setting Up the Frontend
- Run
npx create-react-app client
or runyarn create vite
and name your project “client”, to create a new Vite-based React app in the "client" folder.
If you didn’t install yarn on your machine before, in the terminal, run this command:
For macOS or Linux, you can use the following command:
npm install -g yarn
For Windows, you can use the following command:
npm install --global yarn
3. If you created a Vite-based React app, change to the client folder by using cd client
in the terminal, and run yarn
in order to install the node modules.
4. To install additional packages for your React app, don’t forget to first change to the client directory using cd client
.
5. Delete the .gitignore
and README.md
files in the client folder.
6. Remove the git repository from the client folder. Change to the client folder using cd client
and run -rf .git
on macOS or Linux.
On Windows, Open File Explorer and go to the client folder. Click the “View” tab on the top menu. Check the “Hidden items” checkbox in the “Show” section.
Once you’ve enabled the visibility of hidden items, delete the .git folder in the client folder.
Back in the terminal, return to the root directory with cd ..
.
7. Add a proxy to the package.json file in the client folder for easier API requests, so if you type an address in this way: ('/api/users')
, it will be directed to http://localhost:5000/api/users:
In a CRA (create-react-app) based project, add this line:
"proxy": "http://localhost:5000",
In a Vite based project, add to the vite.config.js file in the client folder:
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
proxy: {
"/api/": "http://localhost:5000/",
},
},
});
8. Change back to root folder using cd ..
and run npm run dev
to start both the back-end and frontend servers simultaneously.
Now you’re all set to start working on your Full Stack application!
Summary
In this cheat sheet, we outline the steps to set up a full stack project, ensuring a smooth and efficient setup process. The article covers creating a project folder, setting up the server using essential dependencies, initializing a Git repository, configuring the frontend with Create React App or Vite, setting up a proxy for seamless frontend and back-end communication, and organizing files using best practices.
By following these instructions, you’ll be well-prepared to dive into your full stack project with confidence, laying a strong foundation for your application development journey.
Happy coding!
Appendix I: A GitHub repository
Here’s a link to a GitHub repository containing a boilerplate code for a full stack application based on this article using Vite. In this link, you will find a GitHub repository for a full stack application based on this article using CRA.
Appendix II: Testing Your Application
To ensure that your full Stack application is functioning correctly, we will add a sample data array to the server.js file and create a GET endpoint for retrieving this data. We will also update the client-side App.js file to fetch and display the data.
- Add the
people
array to the server.js file and create a GET endpoint for retrieving this array:
import express from 'express';
import dotenv from 'dotenv';
dotenv.config({ path: './config/config.env' });
const app = express();
app.get('/', (req, res) => res.send('Server running'));
const people = [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' },
{ id: 3, name: 'Michael Brown' },
{ id: 4, name: 'Emily Johnson' },
{ id: 5, name: 'David Jones' },
{ id: 6, name: 'Sarah Davis' },
{ id: 7, name: 'Kevin Wilson' },
{ id: 8, name: 'Laura Taylor' },
{ id: 9, name: 'Richard Williams' },
{ id: 10, name: 'Emma White' },
];
app.get('/api/people', (req, res) => {
res.json(people);
});
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`));
2. Update the App.js file in the client folder to fetch and display the data:
import { useState, useEffect } from 'react'
import './App.css'
function App() {
const [people, setPeople] = useState([]);
useEffect(() => {
const fetchPeople = async () => {
try {
const response = await fetch('/api/people');
const data = await response.json();
setPeople(data);
} catch (error) {
console.error('Error fetching data:', error);
}
};
fetchPeople();
}, []);
return (
<div className="App">
<h1>List of People</h1>
<ul>
{people.map((person) => (
<li key={person.id}>{person.name}</li>
))}
</ul>
</div>
);
}
export default App;
3. Verify everything is working.
- Run
npm run dev
in the terminal to start both the back-end and frontend servers concurrently. - Open your web browser and navigate to http://localhost:3000 (or http://localhost:5173 if you are using Vite) to view the List of People.
- Check that the list of people from the
people
array in the server.js file is displayed correctly.
By following these steps, you can verify that your full stack application is functioning properly and can proceed with further development.
Appendix III: __dirname and __filename are not defined In ES modules
In ES modules, the __dirname
and __filename
variables are not defined. These variables are commonly used in CommonJS modules to get the directory name and file name of the current module, and might be needed in your Node.js project later on.
While it may be inconvenient to not have access to __dirname
and __filename
in ES modules, it is not a major limitation. There are alternative ways to get the directory and file name of the current module in ES modules, such as using the URL constructor to parse the import.meta.url
property.
The way to get around this in ES modules is by using the fileURLToPath
method imported from the url
module, and passing import.meta.url
as an argument to get the __filename
, and to get the __dirname
to use the path.dirname
method, like in this example:
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
Appendix IV: File and Directory Naming Best Practices
Unix-based systems, such as Linux and macOS, are case-sensitive. This means that if you create two files with the names “file.txt” and “File.txt” in the same directory, the system will treat them as two distinct files.
The implication of this is that you need to be careful when naming your files and directories. If you use inconsistent capitalization, you may end up with multiple files or directories with similar names, which can cause confusion and errors when working with them. Therefore, it’s a best practice to use consistent capitalization and avoid naming conflicts to ensure that your files and directories are easily accessible and manageable across different platforms.