629 lines
20 KiB
Markdown
629 lines
20 KiB
Markdown
# FabDash
|
||
|
||
**Fabrication Dashboard** — A sleek, modern project management & scheduling application built for fabrication workflows.
|
||
|
||

|
||

|
||

|
||

|
||
|
||
---
|
||
|
||
## Table of Contents
|
||
|
||
- [Overview](#overview)
|
||
- [Tech Stack](#tech-stack)
|
||
- [Project Structure](#project-structure)
|
||
- [Features](#features)
|
||
- [Interaction Reference](#interaction-reference)
|
||
- [API Reference](#api-reference)
|
||
- [Component Architecture](#component-architecture)
|
||
- [Unraid Installation](#unraid-installation)
|
||
- [Updating FabDash on Unraid](#updating-fabdash-on-unraid)
|
||
- [Local Development](#local-development)
|
||
- [Environment Variables](#environment-variables)
|
||
- [Database Schema](#database-schema)
|
||
- [Roadmap](#roadmap)
|
||
|
||
---
|
||
|
||
## Overview
|
||
|
||
FabDash is a self-hosted, full-stack project management dashboard built for fabrication teams. It features a large interactive calendar, multi-deliverable project tracking, drag-and-drop scheduling, a per-project timeline Focus View, and a rich right-click context menu system. All wrapped in a dark/gold UI and deployed as a single Docker container with no external dependencies.
|
||
|
||
---
|
||
|
||
## Tech Stack
|
||
|
||
### Frontend
|
||
|
||
| Package | Version | Purpose |
|
||
|---|---|---|
|
||
| React | ^18.3.1 | UI framework |
|
||
| Vite | ^5.4.11 | Build tool and dev server |
|
||
| Tailwind CSS | ^3.4.15 | Utility-first styling |
|
||
| @fullcalendar/core | 6.1.15 | FullCalendar core (pinned) |
|
||
| @fullcalendar/react | 6.1.15 | Calendar component |
|
||
| @fullcalendar/daygrid | 6.1.15 | Month/week grid view |
|
||
| @fullcalendar/timegrid | 6.1.15 | Time-slot view |
|
||
| @fullcalendar/interaction | 6.1.15 | Drag-and-drop, click events |
|
||
| react-chrono | 2.6.0 | Focus View timeline (pinned — last React 18 compatible) |
|
||
| Zustand | ^4.5.5 | Global state management |
|
||
| Axios | ^1.7.9 | HTTP client |
|
||
| date-fns | ^3.6.0 | Date formatting |
|
||
|
||
> **Note:** All FullCalendar packages are pinned to exactly `6.1.15` to prevent version mismatch errors during Docker builds. `react-chrono` is pinned to `2.6.0` — versions ≥ 2.7.0 require React 19.
|
||
|
||
### Backend
|
||
|
||
| Package | Version | Purpose |
|
||
|---|---|---|
|
||
| Flask | 3.1.0 | REST API + static file serving |
|
||
| Flask-SQLAlchemy | 3.1.1 | ORM for SQLite |
|
||
| Flask-Migrate | 4.0.7 | Schema migration support |
|
||
| Flask-CORS | 5.0.0 | Cross-origin support (dev) |
|
||
| Gunicorn | 23.0.0 | Production WSGI server |
|
||
|
||
### Database
|
||
|
||
- **SQLite** — Zero-config, file-based persistence at `/app/data/fabdash.db`
|
||
- Mounted as a named Docker volume so data survives all container restarts and rebuilds
|
||
- **Inline migrations** — New columns are applied automatically on startup via `_run_migrations()` in `app/__init__.py`; no manual migration commands required
|
||
|
||
---
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
fabdash/
|
||
├── Dockerfile
|
||
├── docker-compose.yml
|
||
├── .env.example
|
||
├── .gitignore
|
||
├── README.md
|
||
│
|
||
├── backend/
|
||
│ ├── run.py
|
||
│ ├── config.py
|
||
│ ├── requirements.txt
|
||
│ └── app/
|
||
│ ├── __init__.py # App factory + inline migrations
|
||
│ ├── extensions.py
|
||
│ ├── models.py # Project + Deliverable models
|
||
│ └── routes/
|
||
│ ├── __init__.py
|
||
│ ├── projects.py
|
||
│ └── deliverables.py
|
||
│
|
||
└── frontend/
|
||
├── package.json
|
||
├── vite.config.js # optimizeDeps for FullCalendar
|
||
├── tailwind.config.js
|
||
├── postcss.config.js
|
||
├── index.html
|
||
└── src/
|
||
├── main.jsx
|
||
├── App.jsx
|
||
├── api/
|
||
│ ├── projects.js
|
||
│ └── deliverables.js
|
||
├── components/
|
||
│ ├── Calendar/
|
||
│ │ └── MainCalendar.jsx # dblclick + right-click on events
|
||
│ ├── Projects/
|
||
│ │ ├── ProjectList.jsx
|
||
│ │ ├── ProjectCard.jsx # dblclick + right-click, Drive link
|
||
│ │ └── ProjectModal.jsx # Drive URL input field
|
||
│ ├── Deliverables/
|
||
│ │ └── DeliverableModal.jsx
|
||
│ ├── FocusView/
|
||
│ │ ├── FocusDrawer.jsx
|
||
│ │ ├── FocusTimeline.jsx # Click any card to activate
|
||
│ │ └── DeliverableCard.jsx # dblclick + right-click, status menu
|
||
│ └── UI/
|
||
│ ├── Button.jsx
|
||
│ ├── Badge.jsx
|
||
│ ├── Modal.jsx
|
||
│ ├── Drawer.jsx
|
||
│ └── ContextMenu.jsx # Floating right-click menu
|
||
├── store/
|
||
│ ├── useProjectStore.js
|
||
│ └── useFocusStore.js # setActiveDeliverable action
|
||
├── utils/
|
||
│ ├── dateHelpers.js
|
||
│ └── statusHelpers.js
|
||
└── styles/
|
||
└── globals.css
|
||
```
|
||
|
||
---
|
||
|
||
## Features
|
||
|
||
### Calendar
|
||
|
||
- **Large full-width calendar** — Month, Week, and Day views via FullCalendar
|
||
- **Drag-and-drop rescheduling** — Move any deliverable to a new date; backend patches immediately
|
||
- **Click empty date cell** — Opens Add Deliverable modal pre-filled with that date
|
||
- **Single-click event** — Opens Deliverable Focus View
|
||
- **Double-click event** — Opens Edit Deliverable modal directly
|
||
- **Right-click event** — Context menu (Edit, Focus View, Open Drive, Delete)
|
||
|
||
### Projects
|
||
|
||
- **Multi-deliverable projects** — Add unlimited deliverables per project, each with its own title, due date, and status
|
||
- **Inline creation** — Add all deliverables while creating the project in a single form submission
|
||
- **Color coding** — 12-swatch palette + custom hex input; color appears on calendar events and sidebar cards
|
||
- **Google Drive link** — Optional Drive folder URL stored per project; appears as a button on the project card and in context menus
|
||
- **Double-click project header** — Opens Edit Project modal instantly
|
||
- **Right-click project header** — Context menu (Edit, Open Drive, Delete)
|
||
|
||
### Deliverables
|
||
|
||
- **Status tracking** — Upcoming / In Progress / Completed / Overdue
|
||
- **Auto-overdue detection** — Any deliverable whose due date has passed is automatically returned as `overdue` by the API unless it is marked `completed`. Logic is computed at read time — no cron job needed
|
||
- **Double-click sidebar row** — Opens Edit Deliverable modal
|
||
- **Right-click sidebar row** — Context menu (Edit, Focus View, Delete)
|
||
|
||
### Deliverable Focus View
|
||
|
||
- **Slide-up drawer** — Triggered by clicking any calendar event or sidebar deliverable
|
||
- **Horizontal timeline** — All deliverables for the project rendered in date order
|
||
- **Active card highlighting** — Clicked deliverable glows in gold with a "Selected" badge
|
||
- **Click any card** — Switches the active/selected card without closing the drawer
|
||
- **Double-click any card** — Opens Edit Deliverable modal
|
||
- **Right-click any card** — Context menu with quick status change (all 4 statuses), Edit, and Delete
|
||
|
||
### Right-Click Context Menu
|
||
|
||
A custom floating `ContextMenu` component appears at the cursor position and auto-adjusts to stay within the viewport. It closes on outside click or `Escape`. Available everywhere:
|
||
|
||
| Trigger | Menu Items |
|
||
|---|---|
|
||
| Calendar event | Edit Deliverable, Open Focus View, Open Drive*, Delete |
|
||
| Sidebar project header | Edit Project, Open Drive*, Delete Project |
|
||
| Sidebar deliverable row | Edit Deliverable, Open Focus View, Delete |
|
||
| Focus View card | Edit Deliverable, Mark Upcoming/In Progress/Completed/Overdue, Delete |
|
||
|
||
*Only shown when a Drive URL is set on the project.
|
||
|
||
### Theme & Design System
|
||
|
||
```js
|
||
// tailwind.config.js — custom tokens
|
||
colors: {
|
||
gold: '#C9A84C', // Primary accent
|
||
'gold-light': '#E8C96A',
|
||
'gold-muted': '#8A6E2F',
|
||
surface: '#111111', // Page background
|
||
'surface-raised': '#1A1A1A', // Sidebar, drawer
|
||
'surface-elevated': '#242424', // Cards
|
||
'surface-border': '#2E2E2E', // Borders
|
||
'text-primary': '#F5F5F5',
|
||
'text-muted': '#888888',
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Interaction Reference
|
||
|
||
| Location | Single Click | Double Click | Right Click |
|
||
|---|---|---|---|
|
||
| Calendar event | Open Focus View | Edit Deliverable modal | Context menu |
|
||
| Calendar empty cell | Add Deliverable (pre-filled date) | — | — |
|
||
| Sidebar project header | — | Edit Project modal | Context menu |
|
||
| Sidebar deliverable row | Open Focus View | Edit Deliverable modal | Context menu |
|
||
| Focus View card | Select / activate | Edit Deliverable modal | Context menu |
|
||
| Focus View active card Edit button | Edit Deliverable modal | — | — |
|
||
|
||
---
|
||
|
||
## API Reference
|
||
|
||
### Projects
|
||
|
||
| Method | Endpoint | Description |
|
||
|---|---|---|
|
||
| `GET` | `/api/projects` | List all projects with nested deliverables |
|
||
| `POST` | `/api/projects` | Create project (with optional inline deliverables) |
|
||
| `GET` | `/api/projects/:id` | Get single project |
|
||
| `PATCH` | `/api/projects/:id` | Update name, color, description, or drive_url |
|
||
| `DELETE` | `/api/projects/:id` | Delete project + cascade deliverables |
|
||
|
||
### Deliverables
|
||
|
||
| Method | Endpoint | Description |
|
||
|---|---|---|
|
||
| `GET` | `/api/deliverables?project_id=:id` | List deliverables for a project |
|
||
| `POST` | `/api/deliverables` | Create deliverable |
|
||
| `PATCH` | `/api/deliverables/:id` | Update title, due_date, or status |
|
||
| `DELETE` | `/api/deliverables/:id` | Delete deliverable |
|
||
|
||
**Example — Create Project:**
|
||
|
||
```json
|
||
POST /api/projects
|
||
{
|
||
"name": "CODA",
|
||
"color": "#4A90D9",
|
||
"description": "ADA Call Column and Shelter Equipment Box",
|
||
"drive_url": "https://drive.google.com/drive/folders/your-folder-id",
|
||
"deliverables": [
|
||
{ "title": "Cut Extrusion to Length", "due_date": "2026-03-05", "status": "in_progress" },
|
||
{ "title": "Cut Faceplates and Top Plates", "due_date": "2026-03-06", "status": "upcoming" },
|
||
{ "title": "Fabricate Shelter Assembly Box", "due_date": "2026-03-11", "status": "upcoming" }
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Component Architecture
|
||
|
||
```
|
||
App
|
||
├── Sidebar
|
||
│ ├── ProjectList
|
||
│ │ └── ProjectCard (× N) ← dblclick + right-click
|
||
│ │ ├── DeliverableRow (× N) ← dblclick + right-click
|
||
│ │ ├── DeliverableModal (local)
|
||
│ │ └── ContextMenu (local)
|
||
│ └── Button ["+ Project"]
|
||
│
|
||
├── MainCalendar ← FullCalendar + eventDidMount
|
||
│ ├── FullCalendar events ← dblclick + right-click via DOM
|
||
│ ├── DeliverableModal
|
||
│ └── ContextMenu
|
||
│
|
||
└── FocusDrawer (slide-up)
|
||
├── FocusTimeline
|
||
│ └── DeliverableCard (× N) ← click=select, dblclick=edit, right-click=menu
|
||
│ └── ContextMenu (local)
|
||
└── DeliverableModal
|
||
```
|
||
|
||
---
|
||
|
||
## Unraid Installation
|
||
|
||
FabDash is installed by cloning the repo and building the Docker image locally on your Unraid server via SSH, then managing the container through the Unraid Docker GUI.
|
||
|
||
---
|
||
|
||
### Step 1 — Enable SSH on Unraid
|
||
|
||
Go to **Settings → Management Access** and confirm SSH is enabled. Note your Unraid server's local IP address from the dashboard header.
|
||
|
||
---
|
||
|
||
### Step 2 — SSH into Unraid and Clone the Repo
|
||
|
||
```bash
|
||
ssh root@YOUR_UNRAID_IP
|
||
cd /mnt/user/appdata
|
||
git clone https://github.com/yourname/fabdash.git
|
||
cd fabdash
|
||
```
|
||
|
||
---
|
||
|
||
### Step 3 — Build the Docker Image
|
||
|
||
Builds the image on your Unraid server and tags it `fabdash:latest`.
|
||
First build takes 3–5 minutes (downloads Node + Python layers, compiles React).
|
||
|
||
```bash
|
||
docker build -t fabdash:latest .
|
||
```
|
||
|
||
Verify the image exists:
|
||
|
||
```bash
|
||
docker images | grep fabdash
|
||
```
|
||
|
||
---
|
||
|
||
### Step 4 — Create the Data Directory
|
||
|
||
```bash
|
||
mkdir -p /mnt/user/appdata/fabdash/data
|
||
```
|
||
|
||
---
|
||
|
||
### Step 5 — Add the Container via Unraid Docker GUI
|
||
|
||
1. Go to the **Docker** tab in Unraid
|
||
2. Click **Add Container** at the bottom
|
||
3. Toggle **Advanced View** in the top-right of the form
|
||
|
||
#### Basic Settings
|
||
|
||
| Field | Value |
|
||
|---|---|
|
||
| **Name** | `fabdash` |
|
||
| **Repository** | `fabdash:latest` |
|
||
| **Docker Hub URL** | *(leave blank — local image)* |
|
||
| **Network Type** | `Bridge` |
|
||
| **Console shell command** | `bash` |
|
||
| **Privileged** | `Off` |
|
||
|
||
#### Port Mapping
|
||
|
||
Click **Add another Path, Port, Variable, Label or Device** → **Port**:
|
||
|
||
| Field | Value |
|
||
|---|---|
|
||
| **Name** | `Web UI` |
|
||
| **Container Port** | `8080` |
|
||
| **Host Port** | `8080` |
|
||
| **Connection Type** | `TCP` |
|
||
|
||
> Change Host Port if `8080` is already in use. Access FabDash at `http://YOUR_UNRAID_IP:8080`
|
||
|
||
#### Volume / Path Mapping
|
||
|
||
Click **Add another Path, Port, Variable, Label or Device** → **Path**:
|
||
|
||
| Field | Value |
|
||
|---|---|
|
||
| **Name** | `AppData` |
|
||
| **Container Path** | `/app/data` |
|
||
| **Host Path** | `/mnt/user/appdata/fabdash/data` |
|
||
| **Access Mode** | `Read/Write` |
|
||
|
||
> Your database (`fabdash.db`) lives here and survives all rebuilds and reboots.
|
||
|
||
#### Environment Variables
|
||
|
||
Add each as **Variable**:
|
||
|
||
| Name | Key | Value |
|
||
|---|---|---|
|
||
| Secret Key | `SECRET_KEY` | *(generate below)* |
|
||
| Flask Environment | `FLASK_ENV` | `production` |
|
||
| Database URL | `DATABASE_URL` | `sqlite:////app/data/fabdash.db` |
|
||
|
||
Generate a strong `SECRET_KEY` from the Unraid terminal:
|
||
|
||
```bash
|
||
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 48 | head -n 1
|
||
```
|
||
|
||
#### Extra Parameters
|
||
|
||
| Field | Value |
|
||
|---|---|
|
||
| **Extra Parameters** | `--restart unless-stopped` |
|
||
|
||
---
|
||
|
||
### Step 6 — Apply and Launch
|
||
|
||
Click **Apply**. The container starts using your locally built image.
|
||
|
||
Open your browser: **`http://YOUR_UNRAID_IP:8080`**
|
||
|
||
---
|
||
|
||
### Step 7 — Verify (Optional)
|
||
|
||
Check logs from the Unraid Docker tab → click `fabdash` → **Logs**, or via SSH:
|
||
|
||
```bash
|
||
docker logs fabdash --tail 50
|
||
```
|
||
|
||
A healthy startup looks like:
|
||
|
||
```
|
||
[INFO] Starting gunicorn 23.0.0
|
||
[INFO] Listening at: http://0.0.0.0:8080
|
||
[INFO] Worker booting (pid: ...)
|
||
```
|
||
|
||
---
|
||
|
||
## Updating FabDash on Unraid
|
||
|
||
### Step 1 — Pull latest code and rebuild
|
||
|
||
```bash
|
||
ssh root@YOUR_UNRAID_IP
|
||
cd /mnt/user/appdata/fabdash
|
||
git pull
|
||
docker build -t fabdash:latest .
|
||
```
|
||
|
||
### Step 2 — Restart via Unraid Docker GUI
|
||
|
||
Go to **Docker** tab → click the `fabdash` container icon → **Restart**
|
||
|
||
The container reloads with the new image. Your database is untouched.
|
||
New schema columns (if any) are applied automatically on startup.
|
||
|
||
### Step 3 — Verify
|
||
|
||
```bash
|
||
docker logs fabdash --tail 20
|
||
```
|
||
|
||
---
|
||
|
||
## Data Backup
|
||
|
||
Your database lives at:
|
||
|
||
```
|
||
/mnt/user/appdata/fabdash/data/fabdash.db
|
||
```
|
||
|
||
**Manual backup:**
|
||
|
||
```bash
|
||
cp /mnt/user/appdata/fabdash/data/fabdash.db \
|
||
/mnt/user/backups/fabdash-$(date +%Y%m%d-%H%M).db
|
||
```
|
||
|
||
**Automated backup:** Use the **Appdata Backup/Restore** plugin from Unraid Community Applications to schedule regular backups of `/mnt/user/appdata/fabdash/`.
|
||
|
||
---
|
||
|
||
## Local Development
|
||
|
||
**Terminal 1 — Flask backend:**
|
||
|
||
```bash
|
||
cd backend
|
||
python -m venv venv
|
||
source venv/bin/activate # Windows: venv\Scripts\activate
|
||
pip install -r requirements.txt
|
||
export FLASK_ENV=development
|
||
flask run --port 5000
|
||
```
|
||
|
||
**Terminal 2 — React frontend:**
|
||
|
||
```bash
|
||
cd frontend
|
||
npm install --legacy-peer-deps
|
||
npm run dev # http://localhost:5173
|
||
```
|
||
|
||
Vite proxies all `/api/*` requests to Flask on port 5000 via `vite.config.js`. No CORS configuration needed in development.
|
||
|
||
---
|
||
|
||
## Environment Variables
|
||
|
||
| Variable | Required | Default | Description |
|
||
|---|---|---|---|
|
||
| `SECRET_KEY` | **Yes** | — | Flask session secret. Use a long random string |
|
||
| `FLASK_ENV` | No | `production` | Set to `development` for debug mode and auto-reload |
|
||
| `DATABASE_URL` | No | `sqlite:////app/data/fabdash.db` | Full SQLite path (4 slashes = absolute path) |
|
||
|
||
---
|
||
|
||
## Database Schema
|
||
|
||
```sql
|
||
CREATE TABLE projects (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
name TEXT NOT NULL,
|
||
color TEXT NOT NULL DEFAULT '#C9A84C',
|
||
description TEXT,
|
||
drive_url VARCHAR(500),
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
CREATE TABLE deliverables (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||
title TEXT NOT NULL,
|
||
due_date DATE NOT NULL,
|
||
status TEXT NOT NULL DEFAULT 'upcoming'
|
||
CHECK(status IN ('upcoming','in_progress','completed','overdue')),
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
CREATE INDEX idx_deliverables_project ON deliverables(project_id);
|
||
CREATE INDEX idx_deliverables_due_date ON deliverables(due_date);
|
||
```
|
||
|
||
> `drive_url` is applied to existing databases automatically via the inline migration in `app/__init__.py` — no manual SQL required.
|
||
|
||
### Auto-Overdue Logic
|
||
|
||
The `Deliverable.effective_status()` method is called on every API read:
|
||
|
||
```python
|
||
def effective_status(self):
|
||
if self.status != 'completed' and self.due_date < date.today():
|
||
return 'overdue'
|
||
return self.status
|
||
```
|
||
|
||
- Past-due + not completed → returns `overdue` to the frontend
|
||
- `completed` deliverables are never auto-downgraded regardless of date
|
||
- The stored database value is never modified by this logic
|
||
|
||
---
|
||
|
||
## Roadmap
|
||
|
||
### v1.0 — Core Release *(current)*
|
||
|
||
- [x] Dark/gold Tailwind design system
|
||
- [x] FullCalendar — Month, Week, and Day views
|
||
- [x] Drag-and-drop deliverable rescheduling
|
||
- [x] Multi-deliverable project creation with inline rows
|
||
- [x] Add / Edit / Delete for projects and deliverables
|
||
- [x] Color-coded projects (12-swatch palette + custom hex)
|
||
- [x] Google Drive folder link per project
|
||
- [x] Deliverable Focus View — slide-up drawer, horizontal timeline
|
||
- [x] Click any Focus View card to activate/select it
|
||
- [x] Active deliverable gold highlight in Focus View
|
||
- [x] Status badges — Upcoming / In Progress / Completed / Overdue
|
||
- [x] Auto-overdue detection (computed at API read time, no cron job)
|
||
- [x] Right-click context menus — calendar events, sidebar rows, Focus View cards
|
||
- [x] Double-click shortcuts — events, sidebar rows, project header, Focus View cards
|
||
- [x] Quick status change from Focus View right-click menu
|
||
- [x] Flask REST API + SQLite persistence
|
||
- [x] Cascade delete (project → deliverables)
|
||
- [x] Inline schema migrations (no manual flask db upgrade needed)
|
||
- [x] Single Docker container deployment (multi-stage build)
|
||
- [x] Unraid installation — local build + Docker GUI management
|
||
|
||
### v1.1 — Polish & UX
|
||
|
||
- [ ] Keyboard shortcuts (`N` = new project, `Esc` = close modal/drawer, arrow keys = calendar nav)
|
||
- [ ] 30-second undo toast for drag-and-drop moves
|
||
- [ ] Animated modal and drawer enter/exit transitions
|
||
- [ ] Hover tooltip on calendar events (preview without opening Focus View)
|
||
- [ ] Responsive layout with collapsible sidebar
|
||
- [ ] Empty state illustrations
|
||
|
||
### v1.2 — Calendar Enhancements
|
||
|
||
- [ ] Agenda sidebar showing all upcoming deliverables across projects
|
||
- [ ] Date range selection for bulk deliverable creation
|
||
- [ ] "Today" jump button
|
||
- [ ] Week numbers in calendar header
|
||
- [ ] Mini calendar thumbnail for quick date navigation
|
||
|
||
### v2.0 — Auth & Multi-user
|
||
|
||
- [ ] User login (Flask-Login + JWT)
|
||
- [ ] Multi-user support with project ownership
|
||
- [ ] Role-based access per project (Owner / Editor / Viewer)
|
||
- [ ] Activity log per project
|
||
- [ ] Comment threads on deliverables
|
||
|
||
### v2.1 — Notifications & Integrations
|
||
|
||
- [ ] In-app notification center for approaching due dates
|
||
- [ ] Email reminders at configurable intervals (Flask-Mail)
|
||
- [ ] iCal / Google Calendar export per project
|
||
- [ ] Slack webhook for deliverable status changes
|
||
- [ ] CSV import/export for bulk project setup
|
||
|
||
### v2.2 — Advanced Views
|
||
|
||
- [ ] Gantt view alternate layout
|
||
- [ ] Kanban board (columns by status)
|
||
- [ ] Cross-project timeline view
|
||
- [ ] Workload heatmap — deliverable density per day
|
||
- [ ] Archived projects with searchable history
|
||
|
||
### v3.0 — Intelligence Layer
|
||
|
||
- [ ] AI-assisted scheduling suggestions based on project cadence
|
||
- [ ] Conflict detection — flag overloaded days
|
||
- [ ] Natural language deliverable input ("Add final draft due next Friday to CODA")
|
||
|
||
---
|
||
|
||
*Built with intention. No subscriptions. No bloat. Just your fabrication workflow.*
|