Skip to content

vikasjadhav-dev/jira-clone-task-manager

Repository files navigation

FlowBoard — Real-Time Collaborative Kanban

A production-grade Jira clone with live collaboration powered by Firebase, React, and TypeScript.

FlowBoard Firebase TypeScript Tailwind


✨ Features

Real-Time Collaboration

  • Live Presence Bar — animated avatar stack showing who's online right now (Firebase RTDB)
  • Instant Sync — all card moves, edits, and task updates propagate to every connected user via Firestore onSnapshot — no refresh needed
  • Concurrency Control — Firestore Transactions prevent data overwrites when two users edit simultaneously
  • Optimistic UI — drag-and-drop feels instant; changes revert gracefully if the write fails
  • Activity Feed — real-time log of every action (who moved what, when)

Board Features

  • Drag-and-drop kanban via @hello-pangea/dnd
  • Add / rename / delete columns
  • Create tasks with priority, assignees, Markdown description
  • Task detail panel with inline editing, comments, status changes
  • Priority tags: Critical 🔴, High 🟠, Medium 🟡, Low 🟢

Auth

  • Google sign-in (one click)
  • Email + password (register / sign in)
  • Protected routes — unauthenticated users redirected to /auth

🗂 Project Structure

src/
├── components/
│   ├── board/
│   │   ├── KanbanBoard.tsx      # DragDropContext + optimistic updates
│   │   ├── KanbanColumn.tsx     # Droppable column with task list
│   │   ├── TaskCard.tsx         # Draggable task card
│   │   ├── PresenceBar.tsx      # Live online users indicator
│   │   └── ActivityFeed.tsx     # Real-time activity sidebar
│   ├── task/
│   │   ├── CreateTaskDialog.tsx # New task form
│   │   └── TaskDetailModal.tsx  # Full task editor + comments
│   ├── layout/
│   │   └── ProtectedRoute.tsx
│   └── ui/                      # Shadcn/Radix UI components
├── context/
│   ├── AuthContext.tsx          # Firebase auth state
│   └── ToastContext.tsx         # Global notifications
├── hooks/
│   ├── useProjectSync.ts        # ★ Core: 4x onSnapshot listeners
│   ├── usePresence.ts           # RTDB presence registration + subscription
│   ├── useProjects.ts           # Real-time project list
│   └── useComments.ts           # Real-time task comments
├── services/
│   ├── authService.ts           # Google / email auth + user doc
│   ├── projectService.ts        # Project + column CRUD
│   ├── taskService.ts           # Task CRUD with Transactions + drag moves
│   └── presenceService.ts       # RTDB presence helpers
├── pages/
│   ├── AuthPage.tsx
│   ├── ProjectsPage.tsx
│   └── BoardPage.tsx
├── types/
│   └── index.ts                 # All TypeScript interfaces
└── lib/
    ├── firebase.ts              # Firebase initialization
    └── utils.ts                 # cn(), getInitials(), PRIORITY_CONFIG, etc.

🚀 Setup Guide

1. Clone & Install

git clone <your-repo-url>
cd jira-clone
npm install

2. Create a Firebase Project

  1. Go to console.firebase.google.com
  2. Click Add project → name it (e.g. flowboard)
  3. Disable Google Analytics (optional) → Create project

3. Enable Firebase Services

Firestore Database

  1. Sidebar → Firestore DatabaseCreate database
  2. Choose production mode (rules are provided)
  3. Select a region close to your users → Enable

Realtime Database

  1. Sidebar → Realtime DatabaseCreate database
  2. Choose a location → Start in locked mode
  3. Note your database URL (e.g. https://your-project-default-rtdb.firebaseio.com)

Authentication

  1. Sidebar → AuthenticationGet started
  2. Sign-in method tab → enable:
    • Email/Password → Enable → Save
    • Google → Enable → add your Project support email → Save

4. Get Firebase Config

  1. Project Overview → gear icon → Project settings
  2. Scroll to Your apps → click </> (Web)
  3. Register app (nickname: flowboard-web) → don't need Firebase Hosting
  4. Copy the firebaseConfig object values

5. Configure Environment Variables

cp .env.example .env

Edit .env with your values:

VITE_FIREBASE_API_KEY=AIzaSy...
VITE_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=your-project
VITE_FIREBASE_STORAGE_BUCKET=your-project.appspot.com
VITE_FIREBASE_MESSAGING_SENDER_ID=123456789
VITE_FIREBASE_APP_ID=1:123456789:web:abc123
VITE_FIREBASE_MEASUREMENT_ID=G-XXXXXXX
VITE_FIREBASE_DATABASE_URL=https://your-project-default-rtdb.firebaseio.com

⚠️ Never commit .env — it's in .gitignore. Use Vercel's environment variable UI for production.

6. Deploy Security Rules

Install Firebase CLI if you haven't:

npm install -g firebase-tools
firebase login
firebase use --add   # select your project

Deploy Firestore rules + indexes + RTDB rules:

firebase deploy --only firestore:rules,firestore:indexes,database

7. Run Locally

npm run dev

Open http://localhost:5173


🌐 Deploy to Vercel

Option A: Vercel CLI

npm install -g vercel
vercel

Follow the prompts. When asked about environment variables, add each VITE_FIREBASE_* variable.

Option B: Vercel Dashboard

  1. Push your code to GitHub
  2. Go to vercel.comNew Project → import your repo
  3. Framework preset: Vite (auto-detected)
  4. Environment Variables tab → add all VITE_FIREBASE_* keys
  5. Click Deploy

The vercel.json rewrite rule ensures React Router works with direct URL navigation.

After Deploying

Add your Vercel domain to Firebase Auth's authorized domains:

  1. Firebase Console → Authentication → Settings → Authorized domains
  2. Click Add domain → paste your *.vercel.app URL

🏗 Architecture Deep Dive

Real-Time Sync (useProjectSync)

useProjectSync(projectId)
  ├── onSnapshot(project doc)      → project metadata
  ├── onSnapshot(columns subcol)   → all columns
  ├── onSnapshot(tasks subcol)     → all tasks (ordered by `order`)
  └── onSnapshot(activity subcol)  → activity log

All four listeners run in parallel. The hook tracks readiness and sets loading: false only when all three primary listeners have fired at least once.

Concurrency Control

All task moves and updates use runTransaction():

// moveTask — atomic drag-and-drop
await runTransaction(db, async (transaction) => {
  const taskSnap = await transaction.get(taskRef); // Read inside transaction
  if (!taskSnap.exists()) throw new Error('Task not found');
  
  transaction.update(taskRef, { columnId: destColumnId, order: Date.now() });
  transaction.update(srcColRef, { taskIds: newSrcIds });
  transaction.update(dstColRef, { taskIds: newDstIds });
});

If two users drag the same card simultaneously, the second transaction will retry with fresh data.

Optimistic UI

User drags card →
  1. onOptimisticUpdate() patches local BoardState instantly (0ms)
  2. moveTask() transaction runs against Firestore (~200–500ms)
  3. onSnapshot fires with confirmed server state
  4. Optimistic patch clears, Firestore state takes over

On error:
  3. Catch block reverts optimistic state
  4. Toast notification shown

Presence System

registerPresence(uid, projectId)
  ├── set(rtdb, presence/{projectId}/{uid})    ← RTDB write
  ├── onDisconnect(presenceRef).remove()       ← Auto-cleanup on disconnect
  └── setDoc(firestore, .../presence/{uid})    ← Firestore mirror

subscribeToPresence(projectId, callback)
  └── onValue(rtdb, presence/{projectId})      ← Real-time listener

🔒 Security Rules Summary

Resource Read Create Update Delete
/users/{uid} Any auth user Own user only Own user only
/projects/{id} Members only Auth user (becomes owner) Members only Owner only
/projects/{id}/tasks/{id} Members only Members (sets self as reporter) Members only Members only
/projects/{id}/activity/{id} Members only Members (sets self as userId)
RTDB /presence/{proj}/{uid} Any auth user Own uid only Own uid only Own uid only

🛠 Tech Stack

Layer Technology
Frontend framework React 18 + Vite
Language TypeScript 5
Styling Tailwind CSS 3
UI components Radix UI + Shadcn patterns
Drag & Drop @hello-pangea/dnd
Markdown react-markdown
Real-time DB Firebase Firestore 10
Presence Firebase Realtime Database
Auth Firebase Auth (Google + Email)
Offline support Firestore persistent multi-tab cache
Routing React Router 6
Deployment Vercel

📝 Available Scripts

npm run dev        # Start development server (localhost:5173)
npm run build      # TypeScript check + Vite production build
npm run preview    # Preview production build locally
npm run lint       # ESLint check

🐛 Troubleshooting

"Missing or insufficient permissions" → Deploy Firestore rules: firebase deploy --only firestore:rules → Ensure the user is a member of the project

Google sign-in popup blocked → Allow popups for localhost in your browser settings

Presence not showing → Check RTDB rules are deployed: firebase deploy --only database → Confirm VITE_FIREBASE_DATABASE_URL is set correctly

Tasks not updating in real-time → Check browser console for Firestore listener errors → Ensure Firestore indexes are deployed: firebase deploy --only firestore:indexes

"auth/unauthorized-domain" on production → Add your Vercel domain in Firebase Console → Authentication → Settings → Authorized domains

Important Notes

Project Firebase Configuration & Presence System

This project uses a hybrid database approach: Cloud Firestore for persistent data and Firebase Realtime Database (RTDB) for live user presence (online/offline status).

1. Environment Variables (.env)

The Realtime Database requires a specific URL. Because our database is hosted in Singapore, use this format:

VITE_FIREBASE_DATABASE_URL="https://YOUR_PROJECT_ID.asia-southeast1.firebasedatabase.app"

2. Security Rules (Console)

Navigate to Realtime Database > Rules and publish the following. This allows users to see who is online while only being able to edit their own status:

{
  "rules": {
    "presence": {
      "$projectId": {
        ".read": "auth != null",
        "$uid": {
          ".write": "auth != null && auth.uid === $uid"
        }
      }
    }
  }
}

3. Why RTDB?

Firestore does not detect "unexpected" disconnects (tab closing/internet loss). RTDB uses the onDisconnect() hook to automatically remove user records, keeping our "Online" list 100% accurate.


AuthPage

MainPage

ProjectPage

About

A full-stack Task Management platform inspired by Jira, featuring agile boards, project workflows, and high-reliability live user presence. Built with React, Firestore, and Realtime Database to track active collaborators in real-time.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors