# Project Management A full-featured, open-source project management system built with Django. It helps teams organize, track, and manage their work through an intuitive Kanban board interface with ticket tracking, epics, and real-time collaboration features. Whether you're running a software development team, a creative agency, or any project-driven organization, this tool replaces spreadsheets and scattered to-do lists with a centralized platform. Teams can create projects with custom ticket prefixes, organize work into epics, track progress with Kanban boards, and stay updated with in-app and email notifications. The built-in role-based access (superadmin, manager, member) ensures the right people have the right permissions. External stakeholders can view project dashboards via shareable read-only links without creating accounts. The UI is fully customizable with 19 color themes, sidebar or top navigation, and dark/light mode preferences — all stored per user. The application follows a modern Django architecture with REST API endpoints (documented via Swagger), JWT authentication, Google OAuth, and a task queue for background processing. It ships with Docker Compose for production-ready MySQL + gunicorn deployment, comprehensive demo data seeding, and a GitHub Actions CI pipeline. --- ## Tech Stack | Layer | Technology | |-------|-----------| | **Backend** | Django 6, Django REST Framework, SimpleJWT, Django Q2 | | **Frontend** | HTMX, Alpine.js, Tailwind CSS v4 (via django-tailwind-cli) | | **Database** | SQLite (dev) / MySQL 8.0 (prod) | | **Task Queue** | Django Q2 (ORM broker, 2 workers) | | **API Docs** | drf-spectacular (Swagger UI + OpenAPI schema) | | **Admin** | django-jazzmin (themed admin panel) | | **Auth** | JWT (access 1h / refresh 30d) + Google OAuth | | **Package Manager** | [uv](https://github.com/astral-sh/uv) | --- ## Features - **Projects** — create, manage, pin projects with colour labels, ticket prefixes, and member roles - **Tickets** — full CRUD, bulk delete, Excel import/export, priority and status management - **Epics** — group tickets into epics with progress tracking (% completion) - **Kanban Board** — drag-and-drop ticket status columns per project - **Notifications** — in-app and email notifications on ticket events (create, update, assign, comment) - **User Management** — role-based access (superadmin / manager / member) with custom user model - **External Access** — share a read-only dashboard link with external users via a secure token - **Project Notes** — attach rich-text notes to projects - **Google OAuth** — sign in with Google - **Bulk Operations** — bulk delete tickets, bulk delete notes - **Column Visibility** — show/hide columns on project detail and list views - **Search & Filter** — search, filter by status/priority, paginated lists - **UI Customization** — 19 color themes, sidebar/top navigation, dark/light mode - **Site Branding** — custom logo, favicon, brand name, copyright name via admin --- ## Quick Start ### Prerequisites - Python 3.13+ - [uv](https://github.com/astral-sh/uv) ### 1. Clone & install ```bash git clone https://github.com/S4NKALP/project-managment.git cd project-managment uv sync ``` ### 2. Configure environment ```bash cp .env.sample .env ``` Minimal `.env`: ```ini DJANGO_SETTINGS_MODULE=config.settings.development SECRET_KEY=your-secret-key BASE_URL=http://localhost:8000 SITE_NAME=Project Management ``` ### 3. Run migrations & create superuser ```bash uv run python manage.py migrate uv run python manage.py createcachetable uv run python manage.py createsuperuser ``` ### 4. Start development server ```bash uv run python manage.py runserver ``` Open **http://localhost:8000** in your browser. Authenticated users are redirected to the dashboard. ### Seed demo data (optional) ```bash uv run python manage.py seed_data # creates priorities + admin user uv run python manage.py demo_data # creates rich demo content ``` --- ## Using `just` (recommended) Install [just](https://github.com/casey/just), a command runner. See all available commands: ```bash just ``` ### Development | Command | Description | |---------|-------------| | `just dev` | Run development server on 0.0.0.0:8000 | | `just dev-server HOST="127.0.0.1" PORT="9000"` | Dev server with custom host/port | | `just shell` | Django shell | | `just shell-plus` | Django shell_plus (IPython) | | `just dbshell` | Database shell | ### Database | Command | Description | |---------|-------------| | `just migrate` | Run all migrations | | `just makemigrations` | Create migrations for all apps | | `just makemigrations-app APP` | Create migrations for a specific app | | `just showmigrations` | Show migration status | | `just reset-db` | Flush DB, recreate migrations, migrate | | `just clear-cache` | Clear database cache | ### Testing & Quality | Command | Description | |---------|-------------| | `just test` | Run Django tests | | `just test-coverage` | Run pytest with coverage (HTML + terminal) | | `just lint` | Ruff lint check | | `just format` | Ruff format | | `just style` | Lint + format | | `just check` | Django system checks | | `just check-deploy` | Security checks (production settings) | | `just ci` | Full CI: ruff check + format check + manage.py check | ### Setup | Command | Description | |---------|-------------| | `just setup` | uv sync → migrations → createcachetable → superuser | | `just setup-complete` | Same as setup + collectstatic | ### Production | Command | Description | |---------|-------------| | `just server` | Start gunicorn (1 worker) | | `just server-prod WORKERS="4"` | Start gunicorn with N workers | | `just server-watch` | Gunicorn with `--reload` | ### Package Management | Command | Description | |---------|-------------| | `just install PACKAGE` | uv add a package | | `just install-dev PACKAGE` | uv add --dev a package | | `just remove PACKAGE` | uv remove a package | | `just pin-deps` | Sync pyproject.toml from uv.lock | | `just clean` | Remove Python cache, coverage, pytest cache | --- ## Project Structure ``` project-managment/ ├── config/ # Django configuration │ ├── settings/ │ │ ├── base.py # Shared settings (shared by dev & prod) │ │ ├── development.py # Dev overrides (SQLite, DEBUG=True) │ │ └── production.py # Prod overrides (MySQL, HTTPS, HSTS) │ ├── urls.py # Root URL configuration │ ├── wsgi.py │ └── asgi.py │ ├── src/ # Application code │ ├── accounts/ # Custom User model, auth, Google OAuth │ ├── projects/ # Projects & members API │ ├── tickets/ # Tickets, statuses, priorities API │ ├── epics/ # Epics API │ ├── notes/ # Project notes API │ ├── notifications/ # In-app & email notifications │ ├── external/ # External token-based read-only access │ └── dashboard/ # All HTML-rendering views │ ├── views/ # Dashboard widgets & charts │ ├── list_views/ # Paginated list views │ ├── page_views/ # CRUD page views (create/edit forms) │ ├── board_views/ # Kanban board views │ ├── context_processors.py # Template context injection │ └── filters.py # Ticket/project filter sets │ ├── templates/ # Django/Jinja HTML templates │ ├── auth/ # Login page │ ├── base.html # Base layout (nav, theme, modals) │ ├── dashboard/ # Dashboard page, partials │ ├── projects/ # Project detail, form, list, board │ ├── tickets/ # Ticket detail, form, list │ ├── epics/ # Epic overview, form │ ├── notifications/ # Notification list, dropdown │ ├── settings/ # UI settings (theme, nav, items per page) │ ├── users/ # User profile, list, form │ └── components/ # Reusable modals, rich text editor │ ├── static/ # Static files (CSS, JS, images) ├── manage.py ├── pyproject.toml # Dependencies, ruff config, project metadata ├── justfile # Task runner commands ├── Dockerfile # Production container (Python 3.13-slim) ├── docker-compose.yml # MySQL + app services ├── docker-entrypoint.sh # Runs migrations on container start └── .env.sample # Environment variable template ``` --- ## API Documentation When running in development mode: | Endpoint | Description | |----------|-------------| | `http://localhost:8000/api/docs/` | Swagger UI (drf-spectacular) | | `http://localhost:8000/api/schema/` | OpenAPI 3 schema (YAML) | ### Key API routes | Method | Endpoint | Description | |--------|----------|-------------| | `POST` | `/api/auth/login/` | JWT login (returns access + refresh tokens) | | `POST` | `/api/auth/token/refresh/` | Refresh access token | | `GET` | `/api/auth/me/` | Current user profile | | `GET/POST` | `/api/projects/` | List / create projects | | `GET/PUT/PATCH/DELETE` | `/api/projects//` | Project detail | | `GET/POST` | `/api/projects//members/` | Project members | | `GET/POST` | `/api/tickets/` | List / create tickets | | `GET/PUT/PATCH/DELETE` | `/api/tickets//` | Ticket detail | | `PATCH` | `/api/tickets//move/` | Move ticket between statuses | | `GET/POST` | `/api/epics/` | List / create epics | | `GET/POST` | `/api/notes/` | List / create notes | | `GET/POST` | `/api/notifications/` | List notifications | | `GET` | `/api/projects/stats/` | Aggregate project statistics | --- ## UI Customization ### Color Themes (19 themes) Users can choose their accent color from 19 options via the UI Settings page (`/settings/ui/`): | Name | Hex | Preview | |------|-----|---------| | Blue | `#3b82f6` | Default | | Emerald | `#10b981` | | | Green | `#22c55e` | | | Indigo | `#6366f1` | | | Orange | `#f97316` | | | Purple | `#a855f7` | | | Red | `#ef4444` | | | Rose | `#f43f5e` | | | Sky | `#0ea5e9` | | | Teal | `#14b8a6` | | | Violet | `#8b5cf6` | | | Amber | `#f59e0b` | | | Yellow | `#eab308` | | | Pink | `#ec4899` | | | Cyan | `#06b6d4` | | | Lime | `#84cc16` | | | Slate | `#64748b` | | | Gray | `#6b7280` | | | Zinc | `#71717a` | | ### Navigation Layout - **Sidebar** (default) — vertical nav on the left - **Top** — horizontal nav bar at the top ### Dark / Light Mode Per-user dark/light mode preference, persisted in localStorage. --- ## Docker Deployment ### Build & run ```bash docker compose up --build ``` This starts: - **MySQL 8.0** (`db` service) with persistent volume - **Django app** (`app` service) behind gunicorn on port 8000 ### Services | Service | Image | Port | |---------|-------|------| | `db` | mysql:8.0 | 3306 | | `app` | (builds from Dockerfile) | 8000 | The app container automatically runs migrations on startup via `docker-entrypoint.sh`. --- ## CI / CD GitHub Actions workflow (`.github/workflows/ci.yml`) runs on every push/PR to `main` and `develop`: | Job | Steps | |-----|-------| | **Lint** | `ruff check` + `ruff format --check` | | **Test** | Django system check → pending migration check → `manage.py test --verbosity=2` | | **Security** | `manage.py check --deploy` | --- ## Management Commands | Command | Description | |---------|-------------| | `python manage.py seed_data` | Seed priorities and admin user (idempotent) | | `python manage.py demo_data` | Create comprehensive demo data (14 users, 8 projects, epics, tickets, comments, notifications) | | `python manage.py demo_data --clear` | Clear existing demo data before re-seeding | --- ## Environment Variables Reference | Variable | Default | Required | Description | |----------|---------|----------|-------------| | `DJANGO_SETTINGS_MODULE` | — | Yes | `config.settings.development` or `config.settings.production` | | `SECRET_KEY` | — | Yes | Django secret key (used in prod) | | `ALLOWED_HOSTS` | `localhost,127.0.0.1` | No | Comma-separated allowed hostnames | | `BASE_URL` | `http://localhost:8000` | Yes | Base URL for email links and redirects | | `SITE_NAME` | `Project Management` | No | Displayed in UI, emails, and page titles | | `TIME_ZONE` | `Asia/Kathmandu` | No | Server timezone | ### Database (Production) | Variable | Default | Description | |----------|---------|-------------| | `DB_NAME` | `project_management` | MySQL database name | | `DB_USER` | `project_user` | MySQL user | | `DB_PASSWORD` | `project_password` | MySQL password | | `DB_HOST` | `localhost` | MySQL host | | `DB_PORT` | `3306` | MySQL port | ### Email (Production) | Variable | Default | Description | |----------|---------|-------------| | `EMAIL_HOST` | `smtp.gmail.com` | SMTP server | | `EMAIL_PORT` | `587` | SMTP port | | `EMAIL_USE_TLS` | `True` | Enable TLS | | `EMAIL_HOST_USER` | — | SMTP username | | `EMAIL_HOST_PASSWORD` | — | SMTP password | ### Google OAuth | Variable | Default | Description | |----------|---------|-------------| | `GOOGLE_CLIENT_ID` | — | Google OAuth client ID | | `GOOGLE_CLIENT_SECRET` | — | Google OAuth secret | | `GOOGLE_REDIRECT_URI` | `http://localhost:8000/api/auth/google/callback/` | OAuth callback URL | ### CORS | Variable | Default | Description | |----------|---------|-------------| | `FRONTEND_URL` | `http://localhost:8000` | Allowed CORS origin (production) | --- ## Development Details ### Settings Profiles | Profile | File | Database | Debug | Static Files | |---------|------|----------|-------|--------------| | Development | `config.settings.development` | SQLite (WAL mode) | `True` | Django static | | Production | `config.settings.production` | MySQL | `False` | Whitenoise (compressed, manifest) | ### Authentication - JWT tokens via `djangorestframework-simplejwt` (access: 1h, refresh: 30d, rotating) - Session-based auth for browser (Django's `SessionMiddleware` + `cached_db` backend) - Google OAuth for social login - REST API uses `TokenAuthentication` (SimpleJWT) + `SessionAuthentication` ### Task Queue (Django Q2) | Setting | Value | |---------|-------| | Workers | 2 | | Timeout | 60s | | Retry | 120s | | Poll interval | 2s | | Broker | ORM (database-backed) | ### Caching Database-backed cache (`django_cache` table). Used for site branding (5 min TTL) and sessions (`cached_db` backend). ### Performance (Dev SQLite) SQLite is configured with WAL mode, memory-mapped I/O, and performance pragmas for development.