Self-hosted Scrum tool, faithful to the Scrum Guide
Languages: English | Deutsch | Español | Français | Italiano
Scrumooth is a self-hosted Scrum tool that faithfully implements the Scrum Guide. Lightweight by design, it guides teams through the full Scrum lifecycle — from product goal and backlog to sprint review and retrospective — without the complexity of heavy SaaS platforms. Deploy it on your own infrastructure, keep your data under your control, and never pay per user.
- Live Demo
- Features
- Tech Stack
- Quick Start
- Prerequisites
- Installation
- Testing
- Code Quality
- Database Management
- Docker Support
- Deployment
- Documentation
- Troubleshooting
- Roadmap
- Contributing
- License
Try Scrumooth instantly in your browser — no installation required. The demo runs with mock data (no backend needed) so you can explore the full Scrum lifecycle right away.
👉 Launch the Live Demo on GitHub Pages
Note: The demo uses in‑memory mock data — any changes you make are local to your browser session and reset on refresh. For persistent data and multi‑user collaboration, follow the Installation guide to self‑host your own instance.
- Product Goal - Strategic alignment and goal tracking
- Product Backlog - MoSCoW prioritization (Must, Should, Could, Won't)
- Sprint Planning - Configurable sprint durations and capacity planning
- Sprint Execution - Interactive Kanban board with drag-and-drop
- Daily Scrum - Daily standup tracking and updates
- Impediment - Blocker identification and resolution tracking
- Increment - Product increment management
- Sprint Review - Review meeting management and documentation
- Sprint Retrospective - Team reflection and continuous improvement
- Dashboard & Reporting - Real-time metrics and visualizations
- Workflow Engine - Role-based permissions and state transitions
- Definition of Done/Ready - Customizable checklists
- Team Communication - Built-in notifications and messaging
- Audit Logging - Comprehensive action tracking
- Runtime: Node.js 24+
- Framework: Express.js 5
- Language: TypeScript (strict mode)
- Database: PostgreSQL 18+ with Prisma ORM 7
- Authentication: JWT with bcrypt
- Validation: Zod
- Scheduled Jobs: node-cron
- Email: Nodemailer (SMTP, SendGrid, AWS SES providers)
- Logging: Winston with rotating file transports
- Framework: React 19 with Vite
- Language: TypeScript (strict mode)
- Routing: React Router 6
- State Management: TanStack Query (React Query) + Zustand
- Visualization: Chart.js
- Styling: CSS Modules with Design Tokens
- Error Tracking: Sentry (optional, via
VITE_SENTRY_DSN)
- TypeScript types and interfaces
- Constants and enumerations
- Utility functions
- Unit / Integration: Vitest
- End-to-End: Playwright (frontend) + Vitest (backend)
- Load Testing: k6 (10 pre-built scenarios)
- Linting: ESLint + Stylelint
- Formatting: Prettier
- Git Hooks: Husky + lint-staged
scrumooth/
├── packages/
│ ├── backend/ # Express.js REST API
│ │ ├── src/
│ │ │ ├── controllers/ # API route handlers
│ │ │ ├── services/ # Business logic layer
│ │ │ ├── middleware/ # Express middleware
│ │ │ ├── routes/ # API route definitions
│ │ │ ├── utils/ # Utility functions
│ │ │ └── __tests__/ # Unit, integration, and e2e tests
│ │ ├── prisma/ # Database schema and migrations
│ │ ├── Dockerfile # Production image
│ │ └── Dockerfile.dev # Development image
│ ├── frontend/ # React + Vite frontend
│ │ ├── src/
│ │ │ ├── components/ # React components
│ │ │ ├── pages/ # Route-level pages
│ │ │ ├── hooks/ # Custom React hooks
│ │ │ ├── services/ # API client services
│ │ │ ├── stores/ # Zustand stores
│ │ │ └── styles/ # CSS and design tokens
│ │ ├── e2e/ # Playwright end-to-end tests
│ │ ├── Dockerfile # Production image
│ │ └── Dockerfile.dev # Development image
│ └── shared/ # Shared types, constants, utilities
├── docs/
│ ├── api/ # REST API reference
│ ├── architecture/ # System design, data model, security
│ ├── deployment/ # Deployment guides
│ └── user-guide/ # User documentation and guides
├── k6/ # Load testing scenarios (k6)
│ └── scripts/scenarios/ # pre-built load test scenarios
├── scripts/ # Build and utility scripts
├── .github/workflows/ # CI, Release, and GitHub Pages deployment
├── docker-compose.yml # Production Docker Compose
├── docker-compose.dev.yml # Development Docker Compose
├── CHANGELOG.md # Version history
├── SECURITY.md # Security policy and reporting
├── CONTRIBUTING.md # Contributing guidelines
├── CODE_OF_CONDUCT.md # Community code of conduct
└── THIRD-PARTY-NOTICES.md # Third-party license attributions
The fastest way to run a local instance is with Docker Compose:
git clone https://github.com/orbivort/scrumooth.git
cd scrumooth
cp packages/backend/.env.production.example packages/backend/.env.production
docker compose up -dThis starts the Caddy reverse proxy, backend, frontend, and PostgreSQL. Once running, open http://localhost (HTTPS is enabled by default on port 443). For a full manual setup (without Docker), see Installation.
Note: The production compose stack requires
packages/backend/.env.production. If you prefer a fully pre-configured, hot-reloading development environment, usedocker compose -f docker-compose.dev.yml upinstead.
- Node.js v24.19.0 or higher
- pnpm v11.21.0 or higher
- PostgreSQL v18 or higher
- Docker & Docker Compose (optional, for the Quick Start)
git clone https://github.com/orbivort/scrumooth.git
cd scrumoothThis project uses pnpm as its package manager. The project enforces pnpm through preinstall scripts.
pnpm installCopy the example environment files and configure your settings:
# Backend configuration
cp packages/backend/.env.example packages/backend/.env
# Frontend configuration
cp packages/frontend/.env.example packages/frontend/.envEdit the environment files with your configuration:
Backend (packages/backend/.env):
# Database Configuration
DATABASE_URL=postgresql://postgres:password@localhost:5432/scrumooth
# JWT Configuration (generate with: openssl rand -hex 64)
JWT_SECRET=your-64-character-secret-key-here
# CORS Configuration
CORS_ORIGIN=http://localhost:5173
# Optional: restrict new-account registration to specific email domains.
# Leave empty/unset for open registration. Enforced server-side (HTTP 403 on
# disallowed domains). Tenant-control gate only, not email verification.
REGISTRATION_ALLOWED_EMAIL_DOMAINS=example.com,example.euFrontend (packages/frontend/.env):
# Backend API URL
VITE_API_URL=http://localhost:5001/api/v1
# Use mock API (set to false for real backend)
VITE_USE_MOCK_API=falseGenerate the Prisma client, then create your database schema. For local development you can use either approach:
# Generate Prisma client (always required)
pnpm run db:generate
# Option A: Push schema directly (fast iteration, no migration files)
pnpm run db:push
# Option B: Create and apply a migration (recommended for tracked changes)
pnpm run db:migrateFor production deployments use pnpm run db:migrate:prod to apply existing migrations without prompting.
pnpm run devThis will start both the backend and frontend servers concurrently. To run them independently:
pnpm run dev:backend # Backend only (http://localhost:5001)
pnpm run dev:frontend # Frontend only (http://localhost:5173)The most common commands for everyday development:
| Task | Command |
|---|---|
| Start backend + frontend | pnpm run dev |
| Start backend only | pnpm run dev:backend |
| Start frontend only | pnpm run dev:frontend |
| Build all packages | pnpm run build |
pnpm run test # All tests
pnpm run test:coverage # With coverage report
pnpm run test:unit # Unit tests only
pnpm run test:integration # Backend integration tests
pnpm run test:e2e # End-to-end (backend Vitest + frontend Playwright)
pnpm run test:watch # Watch modeCoverage thresholds enforced: 80% lines, functions, statements, branches.
Pre-built load test scenarios live under k6/scripts/scenarios/. Copy k6/.env.k6.example to k6/.env.k6, configure your target, then run a scenario such as:
pnpm run loadtest:normal # Realistic everyday load
pnpm run loadtest:peak # Sprint planning rush (worst-case concurrency)
pnpm run loadtest:stress # Push the system until it breaksPrerequisite: Install k6 and ensure your target backend is running. Additional scenarios (endurance, multi-team, daily-scrum, auth, db) are available via the
loadtest:*scripts inpackage.json.
| Task | Command |
|---|---|
| Lint (ESLint) | pnpm run lint |
| Lint & auto-fix | pnpm run lint:fix |
| Lint CSS (Stylelint) | pnpm run lint:css |
| Format (Prettier) | pnpm run format |
| Type check | pnpm run typecheck |
| Security audit | pnpm run audit |
See CONTRIBUTING.md for the full development workflow and quality gates.
pnpm run db:generate # Generate Prisma client (after schema changes)
pnpm run db:migrate # Create and apply a migration (development)
pnpm run db:migrate:prod # Apply migrations in production (non-interactive)
pnpm run db:studio # Open Prisma Studio (database GUI)Additional database commands (db:push, db:reset, db:validate, db:migrate:test) are documented in CONTRIBUTING.md.
The project includes Docker configuration for both development and production deployment.
# Development environment (with hot reload)
docker compose -f docker-compose.dev.yml up
# Production environment (detached)
docker compose up -d
# Tear down
docker compose downNote: All Dockerfiles reference repository-root-relative paths (monorepo workspace files such as
package.json,pnpm-lock.yaml, andpackages/shared/). You must build them from the repository root and use-fto point at the Dockerfile — passing the package directory as the build context will fail.
# Development images (with dev dependencies and watch mode)
docker build -t scrumooth-backend:dev -f packages/backend/Dockerfile.dev .
docker build -t scrumooth-frontend:dev -f packages/frontend/Dockerfile.dev .
# Production images (build from the repo root)
docker build -t scrumooth-backend -f packages/backend/Dockerfile .
docker build -t scrumooth-frontend -f packages/frontend/Dockerfile .Using a registry/apt mirror
If you are behind a network that requires an npm registry or apt mirror, you can set them as build arguments or environment variables:
# Docker Compose
$env:NPM_REGISTRY="https://your_mirror_url"
$env:APT_MIRROR="your_mirror_url"
# Manual build
docker build --build-arg NPM_REGISTRY=https://your_mirror_url --build-arg APT_MIRROR=your_mirror_url .See docs/deployment/DEPLOYMENT.md for full production deployment guidance covering environment configuration, database migration, reverse-proxy setup, and operational best practices.
The main branch is automatically deployed to GitHub Pages via the Deploy to GitHub Pages workflow, using an in-memory mock API (no backend or database required). See the Live Demo above to try it.
| Area | Location |
|---|---|
| User guide | docs/user-guide/ — getting started, core features, Scrum workflows |
| REST API reference | docs/api/ — endpoint groups covering authentication, sprints, backlog, reports, and more |
| System architecture | docs/architecture/ — system design, data model, component design, security architecture |
| Deployment guide | docs/deployment/DEPLOYMENT.md |
| Security policy | SECURITY.md — vulnerability reporting procedure |
| Contributing | CONTRIBUTING.md — guidelines and development workflow |
| Code of conduct | CODE_OF_CONDUCT.md — community standards |
| Release history | CHANGELOG.md |
| Third-party notices | THIRD-PARTY-NOTICES.md |
The shared package must be built before backend/frontend can resolve imports.
pnpm --filter=@scrumooth/shared run buildThis is normally handled automatically by pnpm install and the dev scripts, but is required after a manual pnpm run clean.
The repository enforces pnpm via a preinstall script. Install pnpm globally:
npm install -g [email protected]Verify your DATABASE_URL in packages/backend/.env points to a running PostgreSQL 18+ instance, and that the database exists. Run pnpm run db:validate to validate the Prisma schema against the connection.
Default ports can be overridden via environment variables:
- Backend:
PORTinpackages/backend/.env - Frontend:
VITE_DEV_PORTinpackages/frontend/.env
Check that VITE_API_URL in packages/frontend/.env matches the actual backend address and that CORS_ORIGIN in packages/backend/.env allows the frontend origin.
Set VITE_USE_MOCK_API=true in packages/frontend/.env to use the same mock API that powers the live demo.
Scrumooth is under active development. Upcoming priorities include:
- Enhanced reporting and analytics dashboards
- Additional integrations and webhooks
- Performance and scalability hardening
The project status and latest changes are tracked in the CHANGELOG. Feedback and feature requests are welcome via GitHub Issues.
Contributions are welcome! Please read CONTRIBUTING.md for development workflow, code standards, and the pull request process, and review the CODE_OF_CONDUCT.md before participating.
This project is licensed under the Apache License 2.0.
