Where to Find the Source Code for the Core Logic of Plane: A Complete Developer's Guide

The source code for the core logic of Plane resides in the Django backend under apps/api/plane, specifically within the domain models (db/models/), API serializers (app/serializers/), and view controllers (web/views.py).

Plane is an open-source project management platform structured as a mono-repository combining a Django REST API, shared TypeScript packages, and a React UI. If you are extending functionality, debugging, or integrating with Plane programmatically, locating the source code for the core logic of Plane is essential for understanding how workspaces, issues, and projects are managed. The authoritative business rules live entirely within the Python backend; frontend packages consume this API but do not implement core logic.

High-Level Backend Architecture

The makeplane/plane repository organizes its Django application under apps/api/plane. This directory contains the complete stack responsible for workspaces, projects, issues, cycles, and permissions, following a layered architecture:

  • Domain Models (apps/api/plane/db/models/) – Define database schema, relationships, and business methods.
  • Serializers (apps/api/plane/app/serializers/) – Handle validation and conversion between Django models and JSON payloads.
  • Views (apps/api/plane/web/views.py) – Process HTTP requests, enforce permissions, and orchestrate business rules.
  • URL Routing (apps/api/plane/api/urls/) – Map REST endpoints to view functions (e.g., apps/api/plane/api/urls/work_item.py).
  • Utilities (apps/api/plane/utils/) – Provide reusable filters, pagination, and export logic.
  • Middleware (apps/api/plane/middleware/) – Execute request-level authentication and logging.

The frontend packages (packages/ui, packages/editor, etc.) are React-based clients that consume the JSON API exposed by these layers.

Domain Models: The Database Layer

The heart of Plane's data logic lives in apps/api/plane/db/models/. Files such as issue.py and project.py define Django ORM models with custom save() methods, clean() validation, and manager helpers that enforce business rules.

When you create an issue, the logic in apps/api/plane/db/models/issue.py triggers auto-assignment of default statuses and updates related cycle counters. Workspace hierarchy and project ownership rules are enforced in apps/api/plane/db/models/project.py. These models ensure data integrity regardless of which client accesses the API.

Key Model Files

API Layer: Serializers and Views

Incoming requests are processed by Django Rest Framework (DRF) components located in apps/api/plane/app/serializers/ and apps/api/plane/web/views.py.

Serializers in apps/api/plane/app/serializers/issue.py validate incoming JSON payloads, transforming them into Python objects before database insertion. They also serialize model instances back to JSON for API responses.

Views in apps/api/plane/web/views.py (including class-based ViewSets like IssueViewSet) orchestrate the request flow. They check permissions, instantiate the appropriate serializer, call model methods, and return formatted responses. The URL configuration in apps/api/plane/api/urls/work_item.py maps endpoints such as /api/workspaces/<id>/issues/ to these view components.

Utilities, Middleware, and Cross-Cutting Concerns

Cross-cutting concerns are modularized to keep views and models clean.

The utility layer at apps/api/plane/utils/ contains reusable components. The apps/api/plane/utils/filters/filter_backend.py file provides advanced query filtering used across list endpoints, while apps/api/plane/utils/exporters/exporter.py handles CSV and JSON data exports.

Middleware in apps/api/plane/middleware/ intercepts requests before they reach views. The apps/api/plane/middleware/api_authentication.py file specifically handles token-based API authentication, while other modules manage request logging and body-size validation.

Request Flow Through the Core Logic

When a client creates an issue via the REST API, the request traverses the following path through the source code:

  1. URL Resolution – apps/api/plane/api/urls/work_item.py matches the endpoint to the IssueViewSet.
  2. View Handling – The view in apps/api/plane/web/views.py receives the request and checks permissions.
  3. Serialization – apps/api/plane/app/serializers/issue.py validates the incoming payload.
  4. Model Execution – The validated data instantiates or modifies an Issue model from apps/api/plane/db/models/issue.py, triggering custom save() logic.
  5. Utility Integration – Filter backends or export utilities from apps/api/plane/utils/ process the queryset as needed.
  6. Response – The serializer renders the final JSON, which the view returns to the client.

This pipeline ensures that all business rules execute within the Django layer, guaranteeing consistency across web, CLI, or third-party integrations.

Practical Code Examples

Creating an Issue via the REST API

You can interact with the core logic directly using standard HTTP requests:

curl -X POST https://api.plane.so/api/workspaces/<workspace-id>/issues/ \
  -H "Authorization: Bearer <your-api-token>" \
  -H "Content-Type: application/json" \
  -d '{
        "name": "Example issue",
        "description_text": "Detailed description",
        "project": "<project-id>",
        "priority": "high"
      }'

Behind the scenes, this hits the URL configuration in apps/api/plane/api/urls/work_item.py, invokes the IssueViewSet, validates through apps/api/plane/app/serializers/issue.py, and persists via apps/api/plane/db/models/issue.py.

Direct ORM Access for Administrative Scripts

For data migrations or administrative tasks, access the core logic directly:

from plane.db.models import Issue, Project, Workspace

# Assume you have a Workspace instance already

workspace = Workspace.objects.get(id="ws_123")
project   = Project.objects.get(id="prj_456", workspace=workspace)

new_issue = Issue.objects.create(
    name="Programmatic issue",
    description_text="Created from a script",
    project=project,
    priority="medium",
)

print(f"Issue created with id: {new_issue.id}")

This references apps/api/plane/db/models/issue.py and apps/api/plane/db/models/project.py directly, bypassing the HTTP layer while maintaining all model-level business rules.

Exporting Issues Using Utility Classes

The utility layer provides standardized export functionality:

from plane.utils.exporters.exporter import Exporter
from plane.db.models import Issue

issues_qs = Issue.objects.filter(workspace_id="ws_123")
csv_bytes = Exporter.export_to_csv(issues_qs)

with open("issues.csv", "wb") as f:
    f.write(csv_bytes)

This utilizes the export logic defined in apps/api/plane/utils/exporters/exporter.py, ensuring consistent data formatting across the application.

Summary

  • The source code for the core logic of Plane is located in the Django backend at apps/api/plane, separate from the frontend packages.
  • Domain models in apps/api/plane/db/models/ encapsulate data integrity, relationships, and business methods.
  • Serializers in apps/api/plane/app/serializers/ and views in apps/api/plane/web/views.py form the API contract and request handling layer.
  • Utilities and middleware in apps/api/plane/utils/ and apps/api/plane/middleware/ handle cross-cutting concerns like filtering, exports, and authentication.
  • The request lifecycle consistently flows from URL routing → View → Serializer → Model, ensuring server-side execution of all business rules.
  • Commercial features are isolated in apps/api/plane/license/ to separate SaaS logic from the open-source core.

Frequently Asked Questions

Where is the main entry point for Plane's API backend?

The main entry point is the Django application configured in apps/api/plane. Within this module, apps/api/plane/api/urls/ defines the REST endpoint mappings, while apps/api/plane/web/views.py contains the ViewSets that serve as primary request handlers. The WSGI/ASGI configuration files at the project root delegate incoming requests to this application.

Does Plane's frontend contain any business logic?

No. The frontend packages located in packages/ui and packages/editor are React-based clients that consume the JSON API exposed by the Django backend. All validation, business rules, and data integrity checks reside server-side in apps/api/plane to ensure consistency across all clients, including the web UI, CLI tools, or third-party integrations.

How are database migrations handled in Plane's core logic?

Django migrations are managed alongside the models in apps/api/plane/db/models/. When you modify files like apps/api/plane/db/models/issue.py or apps/api/plane/db/models/project.py, you generate migrations using Django's makemigrations command. These migration files are stored in apps/api/plane/db/migrations/ and version-control schema changes alongside the model logic.

What is the purpose of the apps/api/plane/license/ directory?

This directory contains the SaaS-specific logic for Plane's commercial offerings. It manages instance registration, subscription status, and feature gating. While the core project management logic resides in other apps, this module ensures that enterprise features are properly licensed, as implemented in apps/api/plane/license/models/instance.py.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →