Creating a Full Stack Project Management App with React, Next.js, MongoDB, and Tailwind CSS

Posted by


In this tutorial, we will be creating a Full Stack Project Manager App using React, Next.js, MongoDB, and Tailwind CSS. This app will allow users to create projects, add tasks to their projects, and mark tasks as completed.

Before we begin, make sure you have Node.js and npm installed on your computer. You will also need a MongoDB Atlas account to create a free MongoDB database for this project.

Step 1: Setting up the project

First, let’s create a new Next.js project by running the following commands in your terminal:

npx create-next-app project-manager-app
cd project-manager-app

Next, let’s install the required dependencies for this project:

npm install react react-dom next
npm install axios mongoose
npm install tailwindcss postcss autoprefixer

Step 2: Configuring Tailwind CSS

Next, we need to configure Tailwind CSS for our project. Create a postcss.config.js file in the root of your project with the following content:

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};

Create a tailwind.config.js file in the root of your project with the following content:

module.exports = {
  purge: [],
  darkMode: false,
  theme: {
    extend: {},
  },
  variants: {},
  plugins: [],
};

Create a styles directory in the styles directory, and create a new tailwind.css file with the following content:

@tailwind base;
@tailwind components;
@tailwind utilities;

Update your pages/_app.js file with the following content to include Tailwind CSS:

import "../styles/tailwind.css";

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

export default MyApp;

Step 3: Setting up MongoDB

Next, we need to set up our MongoDB database. Create a new cluster on MongoDB Atlas and get your connection string.

Create a new db.js file in the root of your project with the following content:

import mongoose from "mongoose";

const connection_string = "YOUR_CONNECTION_STRING";

const connectDB = async () => {
  try {
    const conn = await mongoose.connect(connection_string, {
      useUnifiedTopology: true,
      useNewUrlParser: true,
      useCreateIndex: true,
    });
    console.log(`MongoDB Connected: ${conn.connection.host}`);
  } catch (error) {
    console.error(`Error: ${error.message}`);
    process.exit(1);
  }
};

export default connectDB;

Step 4: Creating the models

Next, let’s create our models for the project and tasks. Create a new models directory in the root of your project.

Create a Project.js file with the following content:

import mongoose from "mongoose";

const projectSchema = mongoose.Schema({
  name: {
    type: String,
    required: true,
  },
  tasks: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: "Task",
    },
  ],
});

const Project = mongoose.model("Project", projectSchema);

export default Project;

Create a Task.js file with the following content:

import mongoose from "mongoose";

const taskSchema = mongoose.Schema({
  name: {
    type: String,
    required: true,
  },
  completed: {
    type: Boolean,
    default: false,
  },
});

const Task = mongoose.model("Task", taskSchema);

export default Task;

Step 5: Creating the API routes

Next, let’s create our API routes for handling project and task data. Create a new api directory in the root of your project.

Create a projects.js file with the following content:

import connectDB from "../../db";
import Project from "../../models/Project";

connectDB();

export default async (req, res) => {
  if (req.method === "POST") {
    try {
      const project = await Project.create(req.body);

      res.status(201).json({ success: true, data: project });
    } catch (error) {
      res.status(400).json({ success: false });
    }
  } else if (req.method === "GET") {
    try {
      const projects = await Project.find().populate("tasks");

      res.status(200).json({ success: true, data: projects });
    } catch (error) {
      res.status(400).json({ success: false });
    }
  }
};

Create a tasks.js file with the following content:

import connectDB from "../../db";
import Task from "../../models/Task";

connectDB();

export default async (req, res) => {
  if (req.method === "POST") {
    try {
      const task = await Task.create(req.body);

      res.status(201).json({ success: true, data: task });
    } catch (error) {
      res.status(400).json({ success: false });
    }
  } else if (req.method === "PUT") {
    try {
      const task = await Task.findByIdAndUpdate(req.query.id, req.body, {
        new: true,
        runValidators: true,
      });

      res.status(200).json({ success: true, data: task });
    } catch (error) {
      res.status(400).json({ success: false });
    }
  }
};

Step 6: Creating the components

Next, let’s create our components for displaying projects and tasks. Create a components directory in the src directory of your project.

Create a ProjectForm.js file with the following content:

import { useState } from "react";
import axios from "axios";

const ProjectForm = () => {
  const [name, setName] = useState("");

  const handleSubmit = async (e) => {
    e.preventDefault();

    try {
      const res = await axios.post("/api/projects", { name });
      console.log(res.data);
    } catch (error) {
      console.error(error.response.data);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        placeholder="Project Name"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />
      <button type="submit">Create Project</button>
    </form>
  );
};

export default ProjectForm;

Create a ProjectsList.js file with the following content:

import { useState, useEffect } from "react";
import axios from "axios";

const ProjectsList = () => {
  const [projects, setProjects] = useState([]);

  useEffect(() => {
    const fetchProjects = async () => {
      const res = await axios.get("/api/projects");
      setProjects(res.data.data);
    };

    fetchProjects();
  }, []);

  return (
    <div>
      {projects.map((project) => (
        <div key={project._id}>{project.name}</div>
      ))}
    </div>
  );
};

export default ProjectsList;

Step 7: Using the components

Finally, let’s use our components in our pages/index.js file:

import ProjectForm from "../components/ProjectForm";
import ProjectsList from "../components/ProjectsList";

const Home = () => {
  return (
    <div>
      <h1>Project Manager App</h1>
      <ProjectForm />
      <ProjectsList />
    </div>
  );
};

export default Home;

And that’s it! You have now created a Full Stack Project Manager App using React, Next.js, MongoDB, and Tailwind CSS. You can now start adding more features to the app such as editing projects, adding due dates to tasks, and filtering projects by status. Happy coding!

0 0 votes
Article Rating
12 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
@clickadelic7681
1 month ago

Clerk – I'm out 🙁

@DuncanPenny-v7q
1 month ago

Davis Paul Rodriguez Brian Anderson Barbara

@mugabejeanaime
1 month ago

Loved your work 👏👏 . u've gained a sub

@snkd266
1 month ago

your ideas are so good bro ,can u make a detailed project like typing etc tutorial i guess it may increase your views

@saumitrapathak6416
1 month ago

Lovely project but could you please have another video where you teach how to deploy the website as that would be really useful

@kingvas7638
1 month ago

use express js with typescript and not Next js for both front end and back end , not good practice also use jwt auth not 3rd party, i will skop that sorry, thanks for the effort btw

@shreysadhukha8477
1 month ago

bro you missed some of the parts while recording

@vikasr3080
1 month ago

It would be better if you could give us a starting template code ( github repository) so that we dont mess up the initial configuration .

@reinhard_silaen
1 month ago

Man, please stop using third-party authentication. Whenever a tutorial that use clerk I totally skip it

@carlosroberto-gv2wv
1 month ago

Not Dark mode ?

@poudelsanchit
1 month ago

Can we deploy this for free somewhere and still ensure it’s fast?

@sumanthprabhu11
1 month ago

Deployment?