Skip to content

Maryam024/DevFlow

Repository files navigation

DevFlow

A collaborative project management platform — organize projects, track work on a kanban board, and collaborate with your team in one place. Built with the MERN stack (MongoDB, Express, React/Next.js, Node.js).

Node Next.js MongoDB Docker License

Contents

Features

  • Auth — register, login, email verification, forgot/reset password, rotating refresh tokens
  • Workspaces — invite teammates by email, role-based permissions (owner/admin/member)
  • Projects — organize work, markdown notes, archive, live stats dashboard
  • Kanban board — drag-and-drop tasks across Todo / In Progress / Review / Done
  • Tasks — priority, due dates, labels, checklists, multiple assignees, file attachments, threaded comments with @mentions
  • Notifications — task assignments, comments, and mentions, delivered to a notifications inbox (backend emits these live over Socket.io — see the architecture note below)
  • Global search — full-text search across projects and tasks
  • Dark mode, responsive layout throughout

Tech stack

Layer Technology
Frontend Next.js 14 (App Router), TypeScript, Tailwind CSS, React Query, React Hook Form, Zod, Framer Motion, @dnd-kit
Backend Node.js, Express, MongoDB, Mongoose
Auth JWT access + rotating refresh tokens, email verification, password reset
Realtime Socket.io (backend)
Storage Cloudinary (avatars, task attachments)
Email Resend (transactional email API)
Docs Swagger / OpenAPI
Testing Jest, Supertest, mongodb-memory-server
Tooling Docker Compose, GitHub Actions CI, ESLint, Prettier

Quick start (Docker — recommended)

The fastest way to get the whole stack running.

Requirements: Docker Desktop (or Docker Engine + Compose).

git clone <your-fork-url> devflow
cd devflow
docker compose up --build

Then open:

The compose file spins up MongoDB, the backend, and the frontend together, with sensible defaults baked in — no .env file is required to get it running. Without a RESEND_API_KEY configured, email sending falls back to console logging, so registration and invite flows still work end-to-end; you'll just read the verification/reset links from the backend container logs instead of an inbox:

docker compose logs -f backend

To load realistic demo data (a workspace, a project, and several tasks) once the containers are up:

docker compose exec backend npm run seed

This creates three demo accounts, all using the password password123:

Email Role
ada@devflow-demo.test Owner
grace@devflow-demo.test Admin
alan@devflow-demo.test Member

To stop everything: docker compose down (add -v to also delete the MongoDB volume).

Manual setup (without Docker)

Requirements: Node.js 20+, MongoDB 7+ (local install or MongoDB Atlas).

1. Backend

cd backend
cp .env.example .env
# edit .env - at minimum set MONGO_URI, JWT_ACCESS_SECRET, JWT_REFRESH_SECRET
npm install
npm run dev

The API starts on http://localhost:5000. Generate strong secrets for the two JWT values, for example:

node -e "console.log(require('crypto').randomBytes(48).toString('hex'))"

Optionally load demo data: npm run seed.

2. Frontend

In a second terminal:

cd frontend
cp .env.example .env.local
# NEXT_PUBLIC_API_URL defaults to http://localhost:5000/api/v1, which matches the
# backend above - only change it if your backend runs somewhere else
npm install
npm run dev

The app starts on http://localhost:3000.

Running tests

cd backend
npm test

Uses mongodb-memory-server, so no separate database is needed — it downloads and runs a temporary MongoDB instance automatically (requires normal internet access, since it fetches the MongoDB binary the first time you run it).

Environment variables

Backend (backend/.env)

Variable Description Required
MONGO_URI MongoDB connection string Yes
JWT_ACCESS_SECRET / JWT_REFRESH_SECRET Long random strings signing the two token types Yes
CLIENT_URL Frontend origin, used for CORS and links in emails Yes (defaults to http://localhost:3000)
PORT Backend port No (default 5000)
RESEND_API_KEY Transactional email (verification, reset, invites) No — without it, emails are logged to the console instead of sent¹
CLOUDINARY_CLOUD_NAME / CLOUDINARY_API_KEY / CLOUDINARY_API_SECRET File uploads No — required only for avatar/attachment uploads to work
RATE_LIMIT_WINDOW_MS / RATE_LIMIT_MAX API rate limiting No

¹ Variable name shown as RESEND_API_KEY per Resend's standard convention — confirm this matches whatever your email.service.js actually reads before deploying.

See backend/.env.example for the full list with defaults.

Frontend (frontend/.env.local)

Variable Description
NEXT_PUBLIC_API_URL Base URL of the backend API, e.g. http://localhost:5000/api/v1

Architecture overview

flowchart LR
    FE["Next.js<br/>(App Router)"]
    API["Express REST API<br/>(Node.js)"]
    WS["Socket.io"]
    DB[("MongoDB")]
    CDN["Cloudinary"]
    MAIL["Resend<br/>(email)"]

    FE -- "HTTPS / REST + JWT" --> API
    API -- Mongoose --> DB
    API --> CDN
    API --> MAIL
    API -. events .-> WS
    WS -. "planned: live push" .-> FE
Loading

Backend follows a layered architecture: routes (HTTP + validation) → controllers (thin, request/response only) → services (business logic) → models (Mongoose schemas). Every response follows a consistent shape ({ success, message, data } / { success: false, message, errors? }), produced by a single global error handler. See CONTINUE.md for the full set of conventions established while building this out (auth strategy, permission middleware chain, kanban position algorithm, notification triggers, etc.) if you want the detailed reasoning behind specific decisions.

Frontend uses the Next.js App Router with route groups: (auth) for the unauthenticated split-screen auth pages, (app) for the authenticated shell (sidebar + topbar), guarded by a client-side redirect that also preserves the original destination (so an invite-email link survives a login redirect). Server state lives in React Query; the only client state kept outside it is the in-memory access token and the kanban board's local drag state.

Note on real-time notifications: the backend fully implements Socket.io (JWT-authenticated connections, private per-user rooms, events emitted on task assignment/comments/mentions — see backend/src/config/socket.js), but the frontend doesn't yet open a socket connection to consume it; the notifications inbox currently works via a 30-second React Query poll instead, which is a fine fallback but means notifications aren't instant. Wiring up socket.io-client (already a frontend dependency) in a small hook that invalidates the notifications query on incoming events would close this gap — see Known limitations.

ER diagram

erDiagram
    USER ||--o{ REFRESH_TOKEN : has
    USER ||--o{ WORKSPACE_MEMBER : "is member via"
    WORKSPACE ||--o{ WORKSPACE_MEMBER : has
    WORKSPACE ||--o{ INVITATION : has
    WORKSPACE ||--o{ PROJECT : contains
    PROJECT ||--o{ TASK : contains
    TASK ||--o{ COMMENT : has
    TASK ||--o{ ATTACHMENT : has
    TASK }o--o{ USER : "assigned to"
    USER ||--o{ NOTIFICATION : receives

    USER {
      ObjectId _id
      string name
      string email
      string password
      string avatarUrl
      boolean isEmailVerified
    }
    WORKSPACE {
      ObjectId _id
      string name
      string slug
      ObjectId owner
    }
    PROJECT {
      ObjectId _id
      ObjectId workspace
      string name
      string key
      string status
      number taskCounter
    }
    TASK {
      ObjectId _id
      ObjectId project
      number number
      string title
      string status
      string priority
      number position
      date dueDate
    }
    COMMENT {
      ObjectId _id
      ObjectId task
      ObjectId author
      string content
    }
    ATTACHMENT {
      ObjectId _id
      ObjectId task
      string url
      string publicId
    }
    NOTIFICATION {
      ObjectId _id
      ObjectId recipient
      string type
      boolean isRead
    }
Loading

API documentation

Full interactive API docs (Swagger UI) are served by the running backend at /api/v1/docs (e.g. http://localhost:5000/api/v1/docs). Every route is documented with its request/response shape directly from the source (@openapi JSDoc blocks above each route definition in backend/src/routes/).

Folder structure

devflow/
├── backend/
│   ├── src/
│   │   ├── app.js, server.js        # Express app + entry point
│   │   ├── config/                  # env, db, cloudinary, socket, swagger
│   │   ├── models/                  # Mongoose schemas
│   │   ├── services/                # business logic
│   │   ├── controllers/             # HTTP request/response handlers
│   │   ├── routes/                  # route definitions + API docs
│   │   ├── middleware/              # auth, permissions, validation, errors
│   │   ├── validators/              # express-validator chains
│   │   ├── utils/                   # ApiError, ApiResponse, helpers
│   │   └── scripts/seed.js          # demo data
│   └── tests/                       # Jest unit + integration tests
├── frontend/
│   └── src/
│       ├── app/                     # Next.js App Router pages
│       │   ├── (auth)/              # login, register, password reset, etc.
│       │   └── (app)/               # authenticated shell: dashboard, workspaces,
│       │                            #   projects (kanban board), settings
│       ├── components/              # ui/ (primitives), kanban/, app/ (shell), etc.
│       ├── hooks/                   # React Query hooks per resource
│       ├── lib/                     # api clients, validation schemas, utils
│       └── context/                 # auth context
├── docker-compose.yml
└── CONTINUE.md                      # full build log / architectural decision record

Deployment guide

Backend → Render or Railway

  1. Push this repo to GitHub.
  2. Create a new Web Service, point it at the backend/ directory as the root.
  3. Build command: npm install. Start command: npm start.
  4. Set the environment variables from the table above (use a MongoDB Atlas connection string for MONGO_URI in production).
  5. Set CLIENT_URL to your deployed frontend's URL once you have it (step below).

Database → MongoDB Atlas

  1. Create a free cluster at mongodb.com/atlas.
  2. Add a database user and allow network access from your backend host (or 0.0.0.0/0 for simplicity while testing).
  3. Copy the connection string into MONGO_URI.

Frontend → Vercel

  1. Import the repo into vercel.com, set the root directory to frontend/.
  2. Set NEXT_PUBLIC_API_URL to your deployed backend's API base URL (e.g. https://your-backend.onrender.com/api/v1).
  3. Deploy. Then go back to your backend's environment variables and set CLIENT_URL to this Vercel URL, so CORS and email links point to the right place.

File uploads → Cloudinary

Create a free account at cloudinary.com, grab your cloud name, API key, and API secret from the dashboard, and set the three CLOUDINARY_* backend environment variables.

Email → Resend

Create a free account at resend.com, generate an API key, and set RESEND_API_KEY in the backend environment. Verify a sending domain in the Resend dashboard before going to production, or use their shared test domain during development.

Testing

cd backend
npm test          # run once
npm run test:watch

Tests use mongodb-memory-server for a real (in-memory, ephemeral) MongoDB instance, so they exercise actual database behavior rather than mocks — integration tests cover the full auth flow, workspace permissions, kanban task ordering, and file uploads (with Cloudinary itself mocked, since that's a genuine external network dependency).

Known limitations

A few trade-offs were made deliberately to keep this a realistic, maintainable portfolio project rather than an over-engineered one — worth knowing about, and reasonable things to mention if this comes up in an interview:

  • Deleting a workspace does not cascade-delete its projects/tasks/comments/attachments (only project deletion cascades to its tasks). A production system would handle this with a background cleanup job or a transaction.
  • Comment "edit" support exists in the API and UI, but there's no edit history — an edited comment just shows an "(edited)" marker.
  • The backend's Socket.io layer is fully built (see Architecture overview), but the frontend consumes notifications via polling rather than a live socket connection — a good next step, and a natural thing to discuss if asked "what would you improve next?"

License

MIT

About

Modern collaborative project management platform featuring Kanban boards, JWT authentication, workspaces, file uploads, and real-time notifications.

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors