Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 128 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
ProdHub is a modern, all-in-one web application built to help you organize, achieve, and grow. Seamlessly manage projects, tasks, habits, and your calendar from a single, intuitive platform—all with smart AI-powered features and robust security.

**Try ProdHub Now**
We are available at: [https://my-productivity-hub-5a3ba.web.app/](https://my-productivity-hub-5a3ba.web.app/)
🌐 Web App: [https://my-productivity-hub-5a3ba.web.app/](https://my-productivity-hub-5a3ba.web.app/)
🧩 Chrome Extension: [ProdHub on the Chrome Web Store](#) *(coming soon)*

![ProdHub](images/dashboard_2.png)

---

## Key Features

**Dashboard Overview**
Expand All @@ -30,13 +33,13 @@ Break down projects into actionable steps. Set priorities (High, Medium, Low), a

ProdHub uses the Google Gemini API for smart, context-aware planning:

- **Goal Decomposition:** Turns your big ambitions into actionable projects. And with Ai gemerated pre tasks for better understanding.
- **Goal Decomposition:** Turns your big ambitions into actionable projects. And with AI generated pre tasks for better understanding.

- **Daily Planning:** Creates a prioritized daily schedule based on your tasks and calendar.

- Smart Scheduling: The "Plan My Day" button on the dashboard will trigger an AI that acts as a productivity coach. It will analyze overdue tasks, today's high-priority items, and your fixed Google Calendar appointments.

- Actionable Output: Instead of just a list, the AI will generate a suggested schedule with time blocks and priorities. It will be presented in a clean, easy-to-read modal. For example, it might suggest: "9:00 AM - 10:00 AM: Focus on 'Draft Project Proposal' (Overdue Task)" and then slot other tasks around your scheduled meetings.
- Actionable Output: Instead of just a list, the AI will generate a suggested schedule with time blocks and priorities. It will be presented in a clean, easy-to-read modal.

- Context-Aware: If you haven't synced your calendar, the planner will still work with your tasks but will also gently remind you that connecting your calendar can lead to even better plans.

Expand All @@ -48,13 +51,115 @@ ProdHub uses the Google Gemini API for smart, context-aware planning:

**Secure Calendar Integration:** Sync your Google Calendar securely and privately. ProdHub only reads event information to help you plan and never stores or modifies your calendar data. Your data stays yours.

<!--**Persistent, Private Data:**
---

## 🧩 Chrome Extension

ProdHub is also available as a **Chrome side panel extension**, so you can access your full productivity dashboard without leaving your current tab.

### Features of the Extension

- Opens as a **side panel** — keeps your current tab intact
- Full access to all ProdHub features: tasks, habits, goals, schedule, and AI planner
- **Responsive UI** — compact, mobile-friendly layout optimized for the narrow side panel
- Secure Google sign-in via Firebase Authentication
- Real-time sync with your Firestore data across web and extension

### Installing the Extension (Development / Unpacked)

1. **Build the extension bundle:**
```sh
npm run build:extension
```
This runs `react-scripts build` and then copies `manifest.extension.json` → `build/manifest.json`, making the `build/` folder a valid Chrome extension package.

2. **Load in Chrome:**
- Open `chrome://extensions/` in your browser
- Toggle **Developer mode** ON (top right)
- Click **"Load unpacked"**
- Select the `build/` folder

3. **Open the side panel:**
- Click the ProdHub icon in your Chrome toolbar
- The side panel will open. Sign in with Google to get started.

### Publishing to the Chrome Web Store

Follow these steps to publish your own instance of the extension:

#### Step 1 — Prepare & Build

```sh
npm run build:extension
```

Then create a ZIP of the `build/` folder contents (**not** the folder itself — the `manifest.json` must be at the root of the ZIP):

```sh
# PowerShell (Windows)
Compress-Archive -Path .\build\* -DestinationPath prodhub-extension.zip
```

```sh
# macOS / Linux
cd build && zip -r ../prodhub-extension.zip . && cd ..
```

> [!IMPORTANT]
> Verify that `manifest.json` is at the **root** of the ZIP (not inside a subfolder). Chrome will reject the package otherwise.

#### Step 2 — Create a Developer Account

- Go to the [Chrome Developer Dashboard](https://chrome.google.com/webstore/devconsole/)
- Sign in with your Google account
- Pay the one-time **$5 developer registration fee** if this is your first extension

#### Step 3 — Upload the Extension

1. Click **"New Item"** in the dashboard
2. Drag and drop `prodhub-extension.zip` into the upload area
3. Wait for it to process — you will be taken to the listing editor

#### Step 4 — Complete the Store Listing

Fill in the following required fields:

| Field | Suggested Value |
|---|---|
| **Name** | ProdHub – Productivity Side Panel |
| **Short description** | All-in-one productivity: tasks, habits, goals & AI planner in your Chrome side panel. |
| **Category** | Productivity |
| **Language** | English |
| **Screenshots** | At least 1 screenshot (1280×800 or 640×400 px) |
| **Privacy Policy URL** | Link to your privacy policy (required if you handle user data) |

Everything you add is saved in real-time to your secure, private Firebase account. Your information is always up-to-date and accessible wherever you are.
> [!NOTE]
> ProdHub uses Firebase Authentication and Firestore. In the **Privacy Practices** tab you must declare that your extension collects user authentication data (email, name) stored in Firebase.

**Safe Sign-In:**
#### Step 5 — Submit for Review

Log in with Google or a traditional email and password. ProdHub prioritizes your privacy and security every step of the way.-->
- Set visibility to **Public** (or **Unlisted** for testing)
- Click **"Submit for Review"**
- Review typically takes **a few hours to a few days**

#### Extension Manifest Reference

The extension uses `manifest_version: 3` with the following key configuration:

```json
{
"name": "ProdHub Chrome Extension",
"version": "1.0",
"manifest_version": 3,
"permissions": ["sidePanel", "identity"],
"side_panel": { "default_path": "index.html" },
"action": { "default_title": "Open ProdHub Panel" }
}
```

The extension manifest lives at `public/manifest.extension.json` and is automatically copied to `build/manifest.json` by the `build:extension` script.

---

## Technology

Expand All @@ -65,6 +170,9 @@ ProdHub is built for speed, reliability, and a great user experience.
- **Styling:** Tailwind CSS
- **AI Integration:** Google Gemini API
- **Calendar Integration:** Google Calendar API via Google Identity Services
- **Extension:** Chrome Manifest V3 Side Panel API

---

## Get Started with ProdHub

Expand Down Expand Up @@ -138,12 +246,14 @@ Update `src/App.js` to use these variables for your `firebaseConfig`.

#### 6. Run and Deploy

- **Start locally:**
`npm start` (opens at `http://localhost:3000`)
- **Build:**
`npm run build`
- **Deploy:**
`firebase deploy` (ensure `firebase.json` is set to use the `build` folder)
| Command | Description |
|---|---|
| `npm start` | Start local dev server at `http://localhost:3000` |
| `npm run build` | Build production web app |
| `npm run build:extension` | Build Chrome extension package in `build/` |
| `firebase deploy` | Deploy web app to Firebase Hosting |

---

## Running with Docker 🐳

Expand All @@ -158,12 +268,12 @@ This project is fully containerized, allowing you to run it in a consistent and
1. **Clone the Repository**

```bash
git clone [https://github.com/Rupesh4604/my-productivity-hub.git](https://github.com/Rupesh4604/my-productivity-hub.git)
git clone https://github.com/Rupesh4604/my-productivity-hub.git
cd ProdHub
```

2. **Create an Environment File**
Create a file named `.env` in the root of the project. This file will hold your secret keys. Copy the contents of `.env.local` or add the following variables, replacing the placeholder values with your actual credentials:
Create a file named `.env` in the root of the project. Copy the contents of `.env.local` or add the following variables, replacing the placeholder values with your actual credentials:

```env
REACT_APP_FIREBASE_API_KEY=AIzaSy...
Expand All @@ -177,20 +287,16 @@ This project is fully containerized, allowing you to run it in a consistent and
```

3. **Build and Run the Container**
Open your terminal in the project root and run the following command:

```bash
docker-compose up --build
```

This command will build the Docker image based on the `Dockerfile` and then start the container.

4. **Access the Application**
Once the container is running, open your web browser and navigate to:
[**http://localhost:3000**](http://localhost:3000)

You should see the ProdHub application running live! To stop the application, press `Ctrl + C` in your terminal.
Once the container is running, open your browser at [**http://localhost:3000**](http://localhost:3000).
To stop, press `Ctrl + C` in your terminal.

---

**Start your journey with ProdHub today.**

Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "my-productivity-hub",
"version": "0.1.0",
"private": true,
"homepage": ".",
"dependencies": {
"@react-oauth/google": "^0.12.2",
"@testing-library/dom": "^10.4.0",
Expand All @@ -18,6 +19,7 @@
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"build:extension": "react-scripts build && node -e \"require('fs').copyFileSync('./build/manifest.extension.json', './build/manifest.json')\"",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
Expand Down
Binary file added prodhub-extension.zip
Binary file not shown.
3 changes: 3 additions & 0 deletions public/background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
chrome.sidePanel
.setPanelBehavior({ openPanelOnActionClick: true })
.catch((error) => console.error(error));
36 changes: 36 additions & 0 deletions public/manifest.extension.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "ProdHub Chrome Extension",
"version": "1.0",
"manifest_version": 3,
"description": "ProdHub – your all-in-one side-panel productivity hub. Manage tasks, habits, goals, and your schedule without ever leaving your current tab.",
"background": {
"service_worker": "background.js"
},
"permissions": [
"sidePanel",
"identity"
],
"oauth2": {
"client_id": "357244560688-4ibqpt07g54ns83qtimb2rtsa3p42uur.apps.googleusercontent.com",
"scopes": [
"profile",
"email",
"openid"
]
},
"host_permissions": [
"<all_urls>"
],
Comment on lines +21 to +23
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of <all_urls> in host_permissions is extremely broad and generally discouraged unless the extension specifically needs to interact with any website the user visits. For a productivity hub that primarily interacts with Firebase and Google APIs, it is a security best practice to narrow these permissions to specific domains (e.g., https://*.firebaseio.com/*, https://generativelanguage.googleapis.com/*). Broad permissions can also lead to longer review times or rejection during the Chrome Web Store publishing process.

"action": {
"default_title": "Open ProdHub Panel",
"default_icon": "logo192.png"
},
"side_panel": {
"default_path": "index.html"
},
"icons": {
"128": "logo192.png",
"192": "logo192.png",
"512": "logo512.png"
}
}
38 changes: 29 additions & 9 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import AllTasksView from './features/tasks/AllTasksView';
import ScheduleView from './features/schedule/ScheduleView';
import HabitTrackerView from './features/habits/HabitTrackerView';
import WeeklyReviewView from './features/review/WeeklyReviewView';
import { Menu, Book } from 'lucide-react';

function HubApp({ user, handleSignOut }) {
const [projects, setProjects] = useState([]);
Expand All @@ -22,6 +23,7 @@ function HubApp({ user, handleSignOut }) {
const [habitEntries, setHabitEntries] = useState([]);
const [activeView, setActiveView] = useState('dashboard');
const [selectedProjectId, setSelectedProjectId] = useState(null);
const [isSidebarOpen, setIsSidebarOpen] = useState(false);

const [syncedEvents, setSyncedEvents] = useState([]);
const [tokenClient, setTokenClient] = useState(null);
Expand Down Expand Up @@ -101,18 +103,36 @@ function HubApp({ user, handleSignOut }) {
const handleSetView = (view, projectId = null) => {
setActiveView(view);
setSelectedProjectId(projectId);
setIsSidebarOpen(false); // Auto-close sidebar on mobile
};

return (
<div className="bg-gray-900 text-gray-100 min-h-screen font-sans flex">
<Sidebar
onViewChange={handleSetView}
projects={projects}
goals={goals}
userId={user.uid}
handleSignOut={handleSignOut}
/>
<main className="flex-1 p-4 sm:p-6 lg:p-8 overflow-y-auto">
<div className="bg-gray-900 text-gray-100 min-h-screen font-sans flex flex-col md:flex-row">
{/* Mobile Header */}
<div className="md:hidden flex items-center justify-between p-4 border-b border-gray-700/50 bg-gray-900">
<h1 className="text-xl font-bold text-blue-400 flex items-center gap-2">
<Book size={20} /> ProdHub
</h1>
<button
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
className="text-gray-300 hover:text-white p-2 rounded-md hover:bg-gray-800 transition-colors"
>
<Menu size={24} />
</button>
</div>

{/* Sidebar Container */}
<div className={`${isSidebarOpen ? 'block' : 'hidden'} md:block md:w-64 flex-shrink-0 h-[calc(100vh-73px)] md:h-screen w-full`}>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using a hardcoded magic number like 73px for layout calculations is fragile. This value likely represents the height of the mobile header, but if that header's content, padding, or font size changes, this calculation will break. Consider using a more robust CSS layout strategy, such as making the parent container a flexbox column and letting the sidebar container take the remaining height with flex-1.

<Sidebar
onViewChange={handleSetView}
projects={projects}
goals={goals}
userId={user.uid}
handleSignOut={handleSignOut}
/>
</div>

<main className={`${isSidebarOpen ? 'hidden md:block' : 'block'} flex-1 p-4 sm:p-6 lg:p-8 overflow-y-auto max-h-screen`}>
{activeView === 'dashboard' && (
<Dashboard
projects={projects}
Expand Down
Loading
Loading