2026-03-05 11:53:28 -06:00
# FabDash
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
**Fabrication Dashboard** — A sleek, modern project management & scheduling application.
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00

2026-03-05 11:53:28 -06:00


2026-03-05 11:59:14 -06:00

2026-03-05 11:53:28 -06:00
---
## Table of Contents
- [Overview ](#overview )
- [Tech Stack ](#tech-stack )
- [Project Structure ](#project-structure )
- [Features ](#features )
- [API Reference ](#api-reference )
2026-03-05 11:59:14 -06:00
- [Docker Deployment ](#docker-deployment )
2026-03-05 12:13:22 -06:00
- [Unraid Installation ](#unraid-installation )
2026-03-05 11:59:14 -06:00
- [Local Development ](#local-development )
2026-03-05 11:53:28 -06:00
- [Environment Variables ](#environment-variables )
- [Database Schema ](#database-schema )
- [Roadmap ](#roadmap )
2026-03-05 11:59:14 -06:00
2026-03-05 11:53:28 -06:00
---
## Overview
2026-03-05 12:13:22 -06:00
FabDash is a self-hosted project management dashboard built for fabrication teams. It features a large interactive calendar, multi-deliverable project tracking, drag-and-drop scheduling, and a per-project timeline Focus View. All wrapped in a dark/gold UI and deployed as a single Docker container.
2026-03-05 11:53:28 -06:00
---
## Tech Stack
2026-03-05 12:13:22 -06:00
| Layer | Technology |
|---|---|
| Frontend | React 18, Vite, Tailwind CSS |
| Calendar | FullCalendar v6 (daygrid, timegrid, interaction) |
| Focus View | Custom horizontal timeline with react-chrono |
| State | Zustand |
| HTTP | Axios |
| Backend | Flask 3, Flask-SQLAlchemy, Flask-Migrate, Flask-CORS |
| Database | SQLite (persisted via Docker volume) |
| Server | Gunicorn (production) |
2026-03-05 11:53:28 -06:00
---
## Project Structure
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
fabdash/
2026-03-05 11:59:14 -06:00
├── Dockerfile
├── docker-compose.yml
2026-03-05 11:53:28 -06:00
├── .env.example
├── .gitignore
2026-03-05 11:59:14 -06:00
├── README.md
│
├── backend/
│ ├── run.py
│ ├── config.py
│ ├── requirements.txt
│ └── app/
│ ├── __init __ .py
│ ├── extensions.py
│ ├── models.py
│ └── routes/
2026-03-05 12:13:22 -06:00
│ ├── __init __ .py
2026-03-05 11:59:14 -06:00
│ ├── projects.py
│ └── deliverables.py
│
└── frontend/
├── package.json
├── vite.config.js
├── tailwind.config.js
2026-03-05 12:13:22 -06:00
├── postcss.config.js
2026-03-05 11:59:14 -06:00
├── index.html
└── src/
├── main.jsx
├── App.jsx
├── api/
│ ├── projects.js
│ └── deliverables.js
├── components/
│ ├── Calendar/
2026-03-05 12:13:22 -06:00
│ │ └── MainCalendar.jsx
2026-03-05 11:59:14 -06:00
│ ├── Projects/
│ │ ├── ProjectList.jsx
│ │ ├── ProjectCard.jsx
│ │ └── ProjectModal.jsx
│ ├── Deliverables/
2026-03-05 12:13:22 -06:00
│ │ └── DeliverableModal.jsx
2026-03-05 11:59:14 -06:00
│ ├── FocusView/
│ │ ├── FocusDrawer.jsx
│ │ ├── FocusTimeline.jsx
│ │ └── DeliverableCard.jsx
│ └── UI/
│ ├── Button.jsx
│ ├── Badge.jsx
│ ├── Modal.jsx
│ └── Drawer.jsx
├── store/
│ ├── useProjectStore.js
│ └── useFocusStore.js
├── utils/
│ ├── dateHelpers.js
│ └── statusHelpers.js
└── styles/
└── globals.css
```
2026-03-05 11:53:28 -06:00
---
2026-03-05 12:13:22 -06:00
## Features
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
- **Large calendar view** — Month, Week, and Day modes via FullCalendar
- **Drag-and-drop** — Move deliverables to new dates; backend updates instantly
- **Multi-deliverable projects** — Add unlimited deliverables per project, each with its own due date and status
- **Color-coded projects** — 12-swatch palette + custom hex; colors appear on calendar events and sidebar cards
- **Deliverable Focus View** — Click any calendar event to open a slide-up drawer showing the full project timeline, with the selected deliverable highlighted in gold
- **Status tracking** — Upcoming / In Progress / Completed / Overdue badges per deliverable
- **Dark/gold theme** — Dark surfaces with gold as the primary accent throughout
- **Full persistence** — SQLite database via Flask-SQLAlchemy, mounted as a Docker volume
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
---
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
## API Reference
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
### Projects
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
| Method | Endpoint | Description |
|---|---|---|
| `GET` | `/api/projects` | List all projects with nested deliverables |
| `POST` | `/api/projects` | Create project (with optional deliverables inline) |
| `GET` | `/api/projects/:id` | Get single project |
| `PATCH` | `/api/projects/:id` | Update name, color, or description |
| `DELETE` | `/api/projects/:id` | Delete project + cascade deliverables |
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
### Deliverables
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
| 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 |
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
---
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
## Docker Deployment
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
FabDash uses a **multi-stage Docker build ** :
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
1. Stage 1 compiles the React/Vite frontend into static files
2. Stage 2 copies those files into Flask's `static/` folder
3. Gunicorn serves the Flask API at `/api/*` and the React SPA at `/*`
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
No Nginx, no separate containers, no reverse proxy required.
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
```bash
git clone https://github.com/yourname/fabdash.git
cd fabdash
cp .env.example .env
# Edit .env and set a strong SECRET_KEY
docker compose up -d --build
# App available at http://your-host:8080
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
---
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
## Unraid Installation
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
FabDash is designed to run cleanly on Unraid via a Docker Compose build from source.
Two methods are provided below — **Terminal (recommended) ** and **Unraid Docker GUI ** .
2026-03-05 11:53:28 -06:00
---
2026-03-05 12:13:22 -06:00
### Method 1 — Terminal via SSH (Recommended)
This method builds the image directly on your Unraid server and uses `docker compose` to manage the container.
#### Step 1 — Enable SSH on Unraid
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
Go to **Settings → Management Access → SSH ** and ensure SSH is enabled.
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
#### Step 2 — SSH into your Unraid server
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
```bash
ssh root@YOUR_UNRAID_IP
2026-03-05 11:59:14 -06:00
```
2026-03-05 12:13:22 -06:00
#### Step 3 — Clone the repository
```bash
cd /mnt/user/appdata
git clone https://github.com/yourname/fabdash.git
cd fabdash
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
#### Step 4 — Create your environment file
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
```bash
cp .env.example .env
nano .env
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
Set a strong `SECRET_KEY` :
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
```env
SECRET_KEY=your-strong-random-secret-key-here
FLASK_ENV=production
DATABASE_URL=sqlite:////app/data/fabdash.db
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
Press `Ctrl+X` , then `Y` to save.
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
#### Step 5 — Build and start the container
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
```bash
docker compose up -d --build
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
The build will take 2– 4 minutes the first time (downloading Node and Python layers, compiling the React app).
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
#### Step 6 — Access FabDash
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
Open your browser and navigate to:
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
```
http://YOUR_UNRAID_IP:8080
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
#### Useful Commands
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
```bash
# View live logs
docker compose logs -f fabdash
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
# Stop the container
docker compose down
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
# Rebuild after a git pull (update)
git pull
docker compose up -d --build
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
# Open a shell inside the container
docker exec -it fabdash bash
# Run database migrations (after schema changes)
docker exec -it fabdash flask db upgrade
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
---
2026-03-05 12:13:22 -06:00
### Method 2 — Unraid Docker GUI (Manual Container)
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
Use this method if you have already built and pushed the FabDash image to a registry (Docker Hub or GHCR). If you are running from source, use Method 1.
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
#### Step 1 — Push image to a registry (on your dev machine)
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
```bash
docker build -t yourdockerhubuser/fabdash:latest .
docker push yourdockerhubuser/fabdash:latest
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
#### Step 2 — Add container via Unraid Docker tab
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
1. In Unraid, go to the **Docker ** tab
2. Click **Add Container **
3. Switch to **Advanced View ** (toggle top-right)
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
Fill in the fields:
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
| Field | Value |
|---|---|
| **Name ** | `fabdash` |
| **Repository ** | `yourdockerhubuser/fabdash:latest` |
| **Network Type ** | Bridge |
| **Port ** | Host: `8080` → Container: `8080` (TCP) |
| **Path ** | Host: `/mnt/user/appdata/fabdash/data` → Container: `/app/data` |
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
#### Step 3 — Add Environment Variables
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
Click **Add another Path, Port, Variable... ** and add:
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
| Key | Value |
|---|---|
| `SECRET_KEY` | `your-strong-random-key` |
| `FLASK_ENV` | `production` |
| `DATABASE_URL` | `sqlite:////app/data/fabdash.db` |
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
#### Step 4 — Apply
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
Click **Apply ** . Unraid will pull the image and start the container. Access at:
2026-03-05 11:59:14 -06:00
```
2026-03-05 12:13:22 -06:00
http://YOUR_UNRAID_IP:8080
2026-03-05 11:59:14 -06:00
```
2026-03-05 12:13:22 -06:00
#### Updating the Container (GUI method)
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
1. SSH into Unraid
2. Run: `docker pull yourdockerhubuser/fabdash:latest`
3. In the Docker tab, click the FabDash container icon → **Update **
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
---
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
### Data Persistence on Unraid
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
Your SQLite database is stored at:
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
```
/mnt/user/appdata/fabdash/data/fabdash.db
2026-03-05 11:59:14 -06:00
```
2026-03-05 12:13:22 -06:00
This path survives container restarts, image rebuilds, and Unraid reboots. Back it up with Unraid's **Appdata Backup ** plugin or manually:
2026-03-05 11:59:14 -06:00
```bash
2026-03-05 12:13:22 -06:00
cp /mnt/user/appdata/fabdash/data/fabdash.db /mnt/user/backups/fabdash-$(date +%Y%m%d).db
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
---
2026-03-05 11:59:14 -06:00
## Local Development
2026-03-05 12:13:22 -06:00
Run backend and frontend separately to get Vite hot-module reloading:
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
**Terminal 1 — Flask:**
2026-03-05 11:59:14 -06:00
```bash
2026-03-05 11:53:28 -06:00
cd backend
2026-03-05 11:59:14 -06:00
python -m venv venv
2026-03-05 12:13:22 -06:00
source venv/bin/activate # Windows: venv\Scripts\activate
2026-03-05 11:59:14 -06:00
pip install -r requirements.txt
2026-03-05 12:13:22 -06:00
export FLASK_ENV=development
2026-03-05 11:53:28 -06:00
flask run --port 5000
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
**Terminal 2 — React:**
2026-03-05 11:59:14 -06:00
```bash
2026-03-05 11:53:28 -06:00
cd frontend
2026-03-05 11:59:14 -06:00
npm install
2026-03-05 12:13:22 -06:00
npm run dev # http://localhost:5173
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
Vite proxies `/api/*` calls to Flask on port 5000 automatically via `vite.config.js` .
2026-03-05 11:53:28 -06:00
---
## Environment Variables
2026-03-05 12:13:22 -06:00
| Variable | Default | Description |
|---|---|---|
| `SECRET_KEY` | * (required) * | Flask session secret — use a long random string |
| `FLASK_ENV` | `production` | Set to `development` for debug mode |
| `DATABASE_URL` | `sqlite:////app/data/fabdash.db` | Full SQLite path (4 slashes = absolute path) |
2026-03-05 11:53:28 -06:00
---
## Database Schema
2026-03-05 11:59:14 -06:00
```sql
2026-03-05 11:53:28 -06:00
CREATE TABLE projects (
2026-03-05 11:59:14 -06:00
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
color TEXT NOT NULL DEFAULT '#C9A84C ',
2026-03-05 11:53:28 -06:00
description TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE deliverables (
2026-03-05 11:59:14 -06:00
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')),
2026-03-05 11:53:28 -06:00
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
2026-03-05 11:59:14 -06:00
CREATE INDEX idx_deliverables_project ON deliverables(project_id);
2026-03-05 11:53:28 -06:00
CREATE INDEX idx_deliverables_due_date ON deliverables(due_date);
2026-03-05 11:59:14 -06:00
```
2026-03-05 11:53:28 -06:00
---
## Roadmap
2026-03-05 12:13:22 -06:00
### v1.0 — Core Release *(current)*
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
- [x] Dark/gold Tailwind design system
- [x] FullCalendar with Month / Week / Day views
2026-03-05 11:53:28 -06:00
- [x] Drag-and-drop deliverable rescheduling
2026-03-05 12:13:22 -06:00
- [x] Multi-deliverable project creation with inline rows
2026-03-05 11:59:14 -06:00
- [x] Add / Edit / Delete for projects and deliverables
2026-03-05 12:13:22 -06:00
- [x] Deliverable Focus View (slide-up drawer + horizontal timeline)
- [x] Active deliverable gold highlight in Focus View
2026-03-05 11:53:28 -06:00
- [x] Status badges (Upcoming / In Progress / Completed / Overdue)
2026-03-05 12:13:22 -06:00
- [x] Flask REST API + SQLite persistence
2026-03-05 11:53:28 -06:00
- [x] Cascade delete (project → deliverables)
2026-03-05 12:13:22 -06:00
- [x] Single Docker container deployment
- [x] Unraid installation guide (Terminal + GUI)
2026-03-05 11:53:28 -06:00
### v1.1 — Polish & UX
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
- [ ] Keyboard shortcuts (`N` = new project, `Esc` = close, arrow keys = calendar nav)
- [ ] 30-second undo toast for drag-and-drop moves
- [ ] Animated modal/drawer enter and exit transitions
- [ ] Hover tooltip on calendar events (preview without opening Focus View)
- [ ] Responsive layout with collapsible sidebar
- [ ] Empty state illustrations
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
### v1.2 — Calendar Enhancements
2026-03-05 11:59:14 -06:00
- [ ] Agenda sidebar showing all upcoming deliverables across projects
2026-03-05 12:13:22 -06:00
- [ ] Click empty date → pre-filled Add Deliverable modal with project selector
2026-03-05 11:59:14 -06:00
- [ ] Date range selection for bulk deliverable creation
2026-03-05 12:13:22 -06:00
- [ ] "Today" jump button
- [ ] Week numbers in calendar header
2026-03-05 11:53:28 -06:00
2026-03-05 12:13:22 -06:00
### v2.0 — Auth & Multi-user
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
- [ ] User login (Flask-Login + JWT)
- [ ] Multi-user support with project ownership
2026-03-05 11:59:14 -06:00
- [ ] Role-based access per project (Owner / Editor / Viewer)
2026-03-05 12:13:22 -06:00
- [ ] Activity log per project
- [ ] Comment threads on deliverables
2026-03-05 11:53:28 -06:00
### v2.1 — Notifications & Integrations
2026-03-05 11:59:14 -06:00
2026-03-05 11:53:28 -06:00
- [ ] In-app notification center for approaching due dates
2026-03-05 12:13:22 -06:00
- [ ] Email reminders at configurable intervals (Flask-Mail)
2026-03-05 11:53:28 -06:00
- [ ] iCal / Google Calendar export per project
2026-03-05 12:13:22 -06:00
- [ ] Slack webhook for deliverable status changes
- [ ] CSV import/export for bulk setup
2026-03-05 11:53:28 -06:00
### v2.2 — Advanced Views
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
- [ ] Gantt view alternate layout
- [ ] Kanban board (columns by status)
- [ ] Cross-project timeline view
2026-03-05 11:59:14 -06:00
- [ ] Workload heatmap showing deliverable density per day
2026-03-05 11:53:28 -06:00
- [ ] Archived projects with searchable history
### v3.0 — Intelligence Layer
2026-03-05 11:59:14 -06:00
2026-03-05 12:13:22 -06:00
- [ ] AI scheduling suggestions based on project cadence
- [ ] Conflict detection — flag overloaded days
2026-03-05 11:59:14 -06:00
- [ ] Natural language input ("Add final draft due next Friday to CODA")
2026-03-05 11:53:28 -06:00
---
*Built with intention. No subscriptions. No bloat. Just your fabrication workflow.*