Plan the Project: Features, API, Data Model and Folders

MERN Stack Full Course: MongoDB, Express, React and Node.js · Foundations · 6 min read · Updated

Plan before you code

  1. Start with what people need to do: sign in, add jobs, filter them and attach a resume.
  2. Each feature becomes API routes, written down before any code.
  3. The routes decide what data we keep, so we design the Job and the User.
  4. Then we choose a folder layout: one folder for the server and one for the client.
  5. A short plan costs minutes and saves hours of rewriting.

Beginners often start with code and discover halfway that the pieces do not fit. Professionals spend a short time planning first, because changing a plan costs minutes and changing finished code costs days. The plan for a small app fits on one page. This lesson makes that page for the project you will build, and shows the thinking so you can repeat it for your own ideas.

Step 1: say what it does, in plain words

Write the purpose as two sentences a friend would understand. For us: *A signed-in person keeps a list of the jobs they applied for, moves each one through a status, adds notes and the resume they sent, and sees a few numbers about their search. Nobody can see anyone else's jobs.* Notice the last sentence. It is a rule, and rules like it drive the design: it is why every job must belong to a user, and why every query must filter by that user.

Step 2: list the screens

  • Sign in and Create account.
  • My jobs: numbers at the top, search and filters, a list with pages, and an “Add a job” form.
  • One job: edit the details, attach or replace the resume, delete.
  • A “not found” page.

Step 3: turn screens into API routes

For every thing a screen needs, write one route. A table is the clearest way. Look at the table in the plan file below: register, login, “who am I”, then the five job routes (list, add, read, change, delete), then statistics. Two details deserve attention. The list route takes query parameters for search, filter, sort and page, because the screen has those controls. And the statistics route is separate, because counting per status is a different question from listing jobs.

# Job Tracker: the plan

## What it does
A signed-in person keeps a list of the jobs they applied for, moves each one through a status
(saved, applied, interview, offer, rejected), adds notes, and sees a few numbers about their search.

## Folders
```
mern-job-tracker/
  package.json        shortcuts that run both apps
  docs/PLAN.md        this file
  server/             Node.js + Express + Mongoose  (the API)
  client/             React + Vite                  (the screens)
```

## API (JSON, all under /api)
| Method | Path              | What it does                         | Signed in? |
|--------|-------------------|--------------------------------------|------------|
| GET    | /api/health       | is the server up                     | no         |
| POST   | /api/auth/register| create an account                    | no         |
| POST   | /api/auth/login   | get a token                          | no         |
| GET    | /api/auth/me      | who am I                             | yes        |
| GET    | /api/jobs         | list my jobs (search, filter, page)  | yes        |
| POST   | /api/jobs         | add a job                            | yes        |
| GET    | /api/jobs/:id     | one job                              | yes        |
| PUT    | /api/jobs/:id     | change a job                         | yes        |
| DELETE | /api/jobs/:id     | remove a job                         | yes        |
| GET    | /api/jobs/stats   | counts per status                    | yes        |

## Data
- **User**: name, email (unique), passwordHash, createdAt
- **Job**: user (who owns it), company, role, location, status, salary note, notes, appliedOn, resumeFile

## Rules we keep
- A person can only ever see and change their own jobs.
- Passwords are never stored as text and never sent back.
- Secrets live in `.env`, never in Git.

Step 4: design the data

Next, list what you must remember about each thing. A User has a name, an email that must be unique, and a password (stored only as a hash, never as text). A Job has an owner, a company, a role, a place, a status from a fixed list, a free-text pay note, notes, and later an attached resume. Think about what to store as text and what as a fixed choice: the status has five allowed values, so we will make the database enforce them. Pay is free text on purpose, because people write it as “£28k”, “₦150,000 per month” or “₹600 a day”, and forcing a number and currency would lose information.

Step 5: choose the folders

Two apps in one repository keep everything together while keeping their tools apart. server/ is the API with its own package.json. client/ is the React app with its own. A small package.json at the top has shortcuts. The files below create that top-level shortcut file, so one command can install both apps and one command can start both.

{
  "name": "mern-job-tracker",
  "private": true,
  "version": "1.0.0",
  "description": "Job Tracker: a MongoDB, Express, React and Node.js app",
  "scripts": {
    "setup": "npm install --prefix server && npm install --prefix client",
    "server": "npm run dev --prefix server",
    "client": "npm run dev --prefix client",
    "dev": "concurrently -n api,web -c blue,green \"npm:server\" \"npm:client\"",
    "build": "npm run build --prefix client",
    "start": "npm start --prefix server"
  },
  "devDependencies": {
    "concurrently": "^9.1.0"
  }
}

npm run setup installs both apps. npm run dev uses the concurrently package to run the server and the client together in one terminal. You will use it from lesson 25, when the client appears.

Why plan the “boring” rules first?

Features are exciting, but rules are where real apps succeed or fail: who can see what, what happens with bad input, what is never stored. Writing three rules at the start (your own jobs only, no plain-text passwords, secrets in .env) means that you check every later lesson against them. Security added at the end is weaker than security designed at the start.

Your task

  1. Open docs/PLAN.md from the zip. Add one feature you would like (for example “interview date”) and write the route and the data field it needs.
  2. Draw the data model on paper: two boxes (User and Job) and an arrow from Job to User.
  3. Write three rules for your own app idea, in the same style as the plan.

How to check it worked

  • Every screen has the routes it needs in the table.
  • Every field has a reason, and every rule can be checked later.

Summary

  • Plan in this order: purpose, screens, routes, data, folders.
  • Write rules (ownership, secrets, passwords) before features.
  • Keep API and client as two apps in one repository.

Download the solution (mern-lesson-06.zip)

Frequently asked questions

Is planning really needed for a small project?

A short plan is. Five minutes spent listing screens, routes and data prevents the most common problem: realising halfway that a field or a route is missing and having to change code in many places.

Why store the pay as text instead of a number?

Pay in adverts comes in many forms: per hour, per day, per month, in different currencies, sometimes as a range or “negotiable”. A text field keeps exactly what the advert said, and we do not guess or convert, which would risk showing wrong information.

Should the client and server be in one repository?

For a learning project and for small teams, yes: one place to clone, one history, easy to deploy together. Larger teams sometimes split them. The folders stay separate either way.