Project Management System Development

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.
Development and maintenance of all types of websites:
Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:
Development stages
Latest works
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    847
  • image_website-sbh_0.png
    Website development for SBH Partners
    999
  • image_website-_0.png
    Website development for Red Pear
    451

Project management system development

PM systems range from universal SaaS (Jira, Asana) to custom solutions. Building custom makes sense when: non-standard workflows, strict data requirements, integration with internal systems. Key entities: Project → Milestone → Task → Subtask, plus cross-cutting: User, Team, Comment, Attachment, TimeLog, Activity.

Architectural decisions

Monolith vs microservices: for projects up to 50,000 active users, modular monolith is right. Microservices justified when components scale independently. 90% of PM systems stay as monoliths.

Event-driven inside monolith: task status changes, assignee changes, deadline shifts — all events triggering side effects (notifications, dashboard updates, activity logs) without direct coupling. Use internal event bus.

Data model

Support arbitrary task hierarchy. Use adjacency list with materialized path instead of pure Nested Sets:

CREATE TABLE tasks (
  id          BIGSERIAL PRIMARY KEY,
  project_id  BIGINT NOT NULL REFERENCES projects(id),
  parent_id   BIGINT REFERENCES tasks(id),
  path        LTREE NOT NULL,           -- PostgreSQL ltree: '1.5.23'
  title       VARCHAR(500) NOT NULL,
  status      task_status NOT NULL DEFAULT 'todo',
  priority    SMALLINT NOT NULL DEFAULT 2,
  assignee_id BIGINT REFERENCES users(id),
  due_date    DATE,
  estimate    INTEGER,                  -- in minutes
  created_at  TIMESTAMPTZ DEFAULT now()
);

CREATE INDEX tasks_path_gist ON tasks USING GIST (path);

Extension ltree enables queries like "all subtasks of task 5" with: WHERE path <@ '1.5'.

Task dependencies — separate table:

CREATE TABLE task_dependencies (
  task_id       BIGINT REFERENCES tasks(id),
  depends_on_id BIGINT REFERENCES tasks(id),
  type          dep_type NOT NULL,     -- 'blocks', 'required_by', 'related'
  PRIMARY KEY (task_id, depends_on_id)
);

Check for cycles before saving — depth-first traversal or recursive query.

Workflows and state machines

Workflows are main reason companies build custom PM. Approach: configurable workflows per issue type. Each type (Task, Bug, Epic) has own state machine:

'bug' => [
    'states' => ['new', 'triaged', 'in_progress', 'in_review', 'resolved', 'closed', 'reopened'],
    'transitions' => [
        'triage'   => ['from' => ['new'],         'to' => 'triaged'],
        'start'    => ['from' => ['triaged'],      'to' => 'in_progress'],
        'review'   => ['from' => ['in_progress'],  'to' => 'in_review'],
        'resolve'  => ['from' => ['in_review'],    'to' => 'resolved'],
        'close'    => ['from' => ['resolved'],     'to' => 'closed'],
        'reopen'   => ['from' => ['resolved', 'closed'], 'to' => 'reopened'],
    ],
],

Store config in DB (JSON), edit via visual workflow builder — drag-and-drop states.

Real-time updates

PM without realtime is solo work. Use WebSocket stack:

  • Server: Laravel Reverb, Soketi (Pusher-compatible), or Ably
  • Channels: private project channels private-project.{id}, task channels private-task.{id}
  • Presence: shows who's viewing task — important for collaborative editing
// Frontend: Laravel Echo + React
const channel = window.Echo.private(`project.${projectId}`);
channel
  .listen('.task.updated', (e) => {
    queryClient.invalidateQueries(['tasks', e.task.id]);
  })
  .listen('.comment.created', (e) => {
    setComments(prev => [...prev, e.comment]);
  });

Views: Kanban, list, Gantt, calendar

Kanban: columns = workflow statuses. Drag-and-drop via @dnd-kit/core. Virtualize lists > 50 cards (TanStack Virtual).

List with hierarchy: tree-table with expanding subtasks. Server-side sort/filter.

Gantt: complex component. Build on frappe-gantt or @dhtmlx/gantt. Challenge: display dependencies as arrows and auto-recalc dates on duration change.

Calendar: FullCalendar with custom event rendering.

Time tracking

Optional module: embedded time tracker.

CREATE TABLE time_logs (
  id          BIGSERIAL PRIMARY KEY,
  task_id     BIGINT NOT NULL REFERENCES tasks(id),
  user_id     BIGINT NOT NULL REFERENCES users(id),
  started_at  TIMESTAMPTZ NOT NULL,
  stopped_at  TIMESTAMPTZ,
  duration    INTEGER GENERATED ALWAYS AS (
                EXTRACT(EPOCH FROM (stopped_at - started_at))::INTEGER
              ) STORED,
  description TEXT
);

Global UI timer storing state {taskId, startedAt} in localStorage + server sync.

Permissions and access control

RBAC with project-scope roles:

System roles: admin, member
Project roles: owner, manager, developer, viewer, external

Each role has permissions: task:create, task:assign, task:delete, project:settings, member:invite. Use spatie/laravel-permission with custom scoped roles.

Guest access: external users see only selected tasks or read-only. Separate token type with limited permissions.

Notifications

Multi-channel with subscription settings:

Event Email Push In-app Slack
Task assigned optional
Deadline 24h away
Comment mention optional

User manages in profile settings. Queue notifications via Laravel Queues, batch emails (not 50 if 50 events in 5 min — group as digest).

Search

Global search across tasks, projects, comments, files. Requires instant response, morphology, comment content search.

PostgreSQL FTS via tsvector works up to ~200K tasks. Beyond that: OpenSearch with Tika for extracting text from PDFs/DOCX.

Analytics and reporting

  • Velocity: average closure rate per sprint
  • Bottleneck: tasks stuck longest in specific status
  • Time report: who logged what time, by project
  • Custom dashboards: drag-and-drop widgets, save per user profile, cache (Redis, 5min TTL)

Integrations

  • Git repos (GitHub, GitLab): auto status change on commit (closes #123), linkback from PR
  • CI/CD: deploy status in task card
  • Slack / Teams: notifications, create task from message via slash command
  • Confluence / Notion: bidirectional links
  • Calendars: sync deadlines to Google Calendar / Outlook via CalDAV

Build via OAuth 2.0 + webhooks + REST/GraphQL API. Store tokens encrypted.

Performance issues

  • N+1 on task list: each task — assignee, tags, last comment. Eager load with with() or DataLoader.
  • Project progress recalc: don't COUNT every request. Denormalize: completed_tasks_count field in projects table, update via DB trigger or app event.
  • Large lists: cursor-based pagination instead of offset. Cursor by (created_at, id) for stable behavior with concurrent adds.

Timeline

Stage Content Duration
Design Workflows, roles, integrations, wireframes 3–4 weeks
Core Projects, tasks, workflows, permissions 6–8 weeks
UI: list + Kanban Basic views 4–5 weeks
Realtime + notifications WebSocket, email, push 2–3 weeks
Gantt + calendar Complex views 3–4 weeks
Time tracking Timer, logs, reports 2 weeks
Integrations (2–3) Git + Slack + Calendar 3–4 weeks
Testing, launch E2E, load testing 2–3 weeks

Full project: 22–32 weeks. Iterative launch possible at 10–12 weeks — core without Gantt and integrations.