Skip to content

Introduction

Planner is a full-featured project management platform built on a modern TypeScript stack. It supports multi-tenant organizations, teams, projects, tasks with a rich lifecycle, real-time chat, WebSocket notifications, and granular role-based access control.

Architecture

Monorepo Structure

The project uses pnpm workspaces with Turborepo for build orchestration:

planner/
├── apps/
│   ├── backend/         # NestJS API (port 4000)
│   ├── frontend/        # Vue 3 SPA (port 3000)
│   ├── website/         # Nuxt 4 marketing site (port 8080)
│   └── docs/            # VitePress documentation (port 8081)
├── mobile/               # Mobile apps (separate repo)
│   ├── ios/              # iOS (Swift)
│   └── android/          # Android (Kotlin)
├── packages/
│   ├── shared-types/    # @planner/shared-types
│   ├── shared-utils/    # @planner/shared-utils
│   ├── shared-i18n/     # @planner/shared-i18n
│   └── ui-kit/          # @planner/ui-kit
├── docker/              # Dockerfiles for each app
├── docker-compose.yml   # Docker Compose for development
├── docker-compose.prod.yml  # Docker Compose for production
├── turbo.json           # Turborepo pipeline config
├── pnpm-workspace.yaml
└── package.json

Frontend Architecture (Vue 3)

  • Routing: Vue Router with lazy-loaded views, nested layouts (AdminLayout, OrgLayout, TeamLayout)
  • State: Pinia setup stores with storeToRefs for reactive bindings
  • UI: PrimeVue 4 with Aura theme (emerald primary, gray surface)
  • Real-time: Socket.IO client connects on auth, joins user rooms
  • i18n: vue-i18n@9 with Composition API, EN/RU locales stored in localStorage

Backend Architecture (NestJS)

  • Modules: Feature-based modules (Auth, Users, Organizations, Teams, Projects, Tasks, Comments, Chat, Notifications, TaskHistory, Invitations, Events, VideoChat, RBAC, Quotas, Plans, Storage, Email, Health, Admin)
  • Auth: JWT access token (15 min) + refresh token (7 days) with passport-jwt strategy. Email verification required before first login. Refresh tokens stored as SHA-256 hash with rotation and reuse detection
  • Security headers: CSP, HSTS (production), CORS whitelist via helmet
  • Rate limiting: Per-endpoint limits (register 5/min, login 10/min, etc.) + global 60/min via Redis. Account lockout after 5 failed attempts
  • Password policy: 8-128 chars, requires uppercase + lowercase + digit + special character, hashed with bcrypt (cost 10)
  • Permissions: Custom @Permissions() decorator + PermissionsGuard — checks requiredPermissions against user's effective permissions
  • Real-time: NotificationsGateway (namespace /notifications) — sends to user:<id> rooms
  • Database: PostgreSQL with Prisma ORM, prisma migrate for production, prisma db push for local dev
  • Swagger UI: Auto-generated API documentation available at /api/docs (development only)

Key Design Decisions

Notifications Module

  • @Global() — all services inject NotificationsService directly
  • NotificationsService.create() — fire-and-forget (not awaited) to avoid slowing main operations
  • WebSocket gateway (/notifications) authenticates via handshake.auth.token using JwtService

Tasks — Project-scoped

  • projectId on Task model is required with cascade delete from Project
  • CRUD via ProjectTasksController at /projects/:id/tasks (PROJECT scope permissions)
  • Task comments via ProjectTaskCommentsController at /projects/:id/tasks/:taskId/comments
  • Task history is automatically logged on create/update/status change/assign/delete

Permission System

  • 30+ granular permissions across 6 scopes: GLOBAL, ORGANIZATION, TEAM, PROJECT, TASK, CHAT
  • Custom roles can combine any set of permissions
  • User groups for bulk role assignment
  • Effective permissions are aggregated from user's roles at global, org, team, and project levels