Leantime Developer Documentation
A complete guide to the frontend & backend architecture of the open-source project management system built for non-project managers.
Introduction
Leantime is an open-source project management system built specifically for non-project managers and neurodivergent teams. It blends the simplicity of Trello with the power of Jira. The codebase is a monolith with a clean separation between a PHP/Laravel backend and a JavaScript/LESS/Tailwind frontend, bundled by Laravel Mix (Webpack).
License: AGPL-3.0 | Author: Marcel Folaron | Homepage: leantime.io | Support: support@leantime.io
Backend Stack
PHP 8.2+, Laravel 11, MySQL/PDO, Redis for caching, custom event bus, REST + MCP API surface.
Frontend Stack
Vanilla JS + jQuery, HTMX for partial page updates, LESS + Tailwind CSS, Webpack (Laravel Mix) build pipeline.
Integrations
AWS S3, Stripe, LDAP, OIDC, SAML2, CalDAV (SabreDAV), AI via Prism-PHP & NeuronAI, Sentry monitoring.
Architecture Overview
Every HTTP request enters through public/index.php, which bootstraps the Application (a Laravel Foundation app) and delegates to the Bootloader singleton. The bootloader captures the request type, picks the right kernel (HTTP vs CLI), runs middleware, and dispatches to the appropriate domain controller.
// 1. Composer autoloader require __DIR__.'/../vendor/autoload.php'; // 2. Instantiate Laravel-based Application $app = new Leantime\Core\Application(dirname(__DIR__)); // 3. Bootloader picks HTTP or Console kernel Leantime\Core\Bootloader::getInstance()->boot($app);
Directory Structure
PHP / Laravel Backend
Built on Laravel 11 with a custom application bootstrap, domain-driven folder structure, a powerful event bus, and multi-layer middleware stack.
Core Layer app/Core/
Application.php
Extends Illuminate\Foundation\Application. Overrides all path bindings to Leantime's custom layout, registers base service providers (Events, Log, Routing) and fires bootstrap events.
Bootloader.php
Singleton that captures the HTTP request via IncomingRequest::capture(), selects HttpKernel or ConsoleKernel, handles the request, and terminates the lifecycle.
Http / HttpKernel.php
Defines the middleware stack for web, API, and HTMX routes. IncomingRequest auto-detects request type (web, API, CLI, HTMX).
Database/
DatabaseManager extends Laravel's manager. LtPostgresConnection adds PostgreSQL support. DatabaseServiceProvider binds it into the container.
Cache/
Redis-first caching via CacheServiceProvider. Falls back to Laravel's file driver. Used across domain repositories for query caching.
Auth/
AuthenticationServiceProvider wires token-based authentication. RoleResolver resolves user roles. Contracts define AuthenticatableInterface.
Routing/
RouteLoader dynamically discovers and registers routes from all domain modules. FrontcontrollerServiceProvider wires it into Laravel's router.
Mailer.php
Wraps PHPMailer with Leantime-specific templates, SMTP configuration from environment, and HTML-to-Markdown fallback for plain-text emails.
protected $middlewareGroups = [ 'web' => [ InitialHeaders::class, StartSession::class, Localization::class, AuthCheck::class, LoadPlugins::class, SetCacheHeaders::class, ], 'api' => [ RequestRateLimiter::class, VerifyCsrfToken::class, ], ];
Domain Layer app/Domain/
Convention: Every domain module follows the same internal layout: Controllers/ → Services/ → Repositories/ → Models/, with optional Hxcontrollers/ (HTMX partials), Templates/, Js/, and Permissions/ sub-directories.
All 44 Domain Modules
| Module | Description | Key Features |
|---|---|---|
| Tickets | Core task & ticket management | Kanban Gantt Sprints |
| Projects | Project lifecycle management | CRUD Archive |
| Users | User profiles & roles | RBAC Avatars |
| Auth | Authentication flows | Login 2FA LDAP |
| Dashboard | Configurable dashboards | Widgets GridStack |
| Timesheets | Time tracking & logging | Reports CSV |
| Wiki | Knowledge base & docs | TipTap Markdown |
| Calendar | Event & schedule management | FullCalendar iCal |
| Notifications | In-app & email notifications | Queue Real-time |
| Reports | Analytics & reporting | Chart.js PDF |
| Canvas / Goalcanvas | Strategy & goal canvases | Visual Planning |
| Files | File upload & media management | AWS S3 Uppy |
| Comments & Reactions | Threaded comments & emoji reactions | HTMX |
| Oidc / TwoFA / Ldap | SSO & security | SAML2 TOTP |
| Api | REST API surface | Sanctum MCP |
| Plugins | Plugin management UI | Marketplace |
| Queue / Cron | Background job processing | Async Scheduled |
| Ideas / Gamecenter | Idea board & gamification | Engagement |
| Sprints | Agile sprint management | Scrum Velocity |
| Audit | Activity & change audit log | Compliance |
| Setting | System & user settings | Config |
| Tags | Tagging & classification | Cross-domain |
| Clients | Client CRM records | B2B |
| Blueprints | Project & ticket templates | Reusability |
Middleware Stack app/Core/Middleware/
| Middleware | Responsibility |
|---|---|
| AuthCheck.php | Verifies user is authenticated; redirects to login if not. |
| AuthenticateSession.php | Validates session integrity and prevents session fixation attacks. |
| InitialHeaders.php | Sets security headers (CSP, X-Frame-Options, HSTS). |
| Installed.php | Checks that Leantime has been installed; redirects to setup wizard if not. |
| Updated.php | Checks for pending DB migrations and forces the update flow. |
| LoadPlugins.php | Boots enabled plugins into the service container. |
| Localization.php | Sets locale from user profile / browser headers. |
| StartSession.php | Custom session driver with Redis support. |
| RequestRateLimiter.php | Token-bucket rate limiting for API & login endpoints. |
| SetCacheHeaders.php | Adds appropriate Cache-Control headers to responses. |
| TrustProxies.php | Trusts reverse proxy headers (X-Forwarded-For). |
| VerifyCsrfToken.php | CSRF verification (excludes API routes). |
| TrimStrings.php | Trims whitespace from all incoming string inputs. |
| RateLimiter.php | General Laravel rate limiter binding. |
Events System app/Core/Events/
Leantime uses a custom EventDispatcher on top of Laravel's event system. The DispatchesEvents trait is mixed into any class that needs to fire events. Listeners are auto-discovered at boot time — earlier than Laravel's default discovery.
// Dispatch a filter event (returns modified value) $filteredValue = self::applyFilter('leantime.core.tickets.afterSave', $ticket); // Dispatch an action event (fire and forget) self::dispatchEvent('leantime.domain.users.afterCreate', [ 'user' => $newUser ]); // Register a listener (typically in a ServiceProvider) self::addEventListener( 'leantime.core.afterBootingServiceProviders', function() { /* custom setup */ } );
Plugin Integration: Plugins tap into the event bus to extend or override any domain behavior without modifying core files — this is the primary extension point for the plugin marketplace.
API & Authentication
Laravel Sanctum
Token-based API authentication. Every API key is stored as a PersonalAccessToken. Rate limiting is enforced per token via RequestRateLimiter middleware.
Social Login / OIDC
Laravel Socialite supports 13 providers: Google, GitHub, GitLab, Microsoft, Azure, Okta, Keycloak, Auth0, Gitea, Authentik, PropelAuth, EduID, and generic SAML2.
MCP API
Model Context Protocol API powered by laravel/mcp, allowing AI agents to interact with Leantime's data programmatically via a standardized protocol.
Two-Factor Auth
TOTP-based 2FA via robthree/twofactorauth with QR code generation through endroid/qr-code. Enforced per-user or globally by admins.
JavaScript / CSS Frontend
jQuery + Vanilla JS core, HTMX for partial updates, TipTap rich editor, LESS + Tailwind CSS for styling, compiled by Laravel Mix (Webpack 5).
JavaScript Modules public/assets/js/
app.js
Main application entry point. Initialises jQuery, HTMX event hooks, global error handlers, accessibility helpers, and bootstraps the SPA-like navigation model.
htmx.js & htmx-extensions.js
HTMX 1.9 loaded separately (compiled independently so it can be updated without a full rebuild). Extensions add custom swap strategies and loading indicators.
designtokens.js
19 KB of design system tokens exposed to JavaScript — colors, spacing, typography, breakpoints. Keeps CSS variables & JS in sync for chart and canvas rendering.
core/tiptap/
Custom TipTap 2 rich text editor setup with 20+ extensions: tables, task lists, mentions, code blocks (Lowlight), images, formatting toolbar, and floating menus.
core/datePickers.js
Unified date picker abstraction wrapping jQuery UI datepicker with Luxon for timezone-aware parsing and formatting across all form inputs.
core/accessibility.js
12 KB of accessibility helpers: keyboard navigation, focus trapping in modals, skip-link management, ARIA attribute updates, and high-contrast mode detection.
core/modals.js
Global modal system using jQuery nyroModal with HTMX integration. Supports full-page modal loads, form submission inside modals, and focus management.
core/dateHelper.js
10 KB date utility library. Provides relative date formatting, business-day calculations, ISO 8601 parsing, and multi-timezone display helpers using Luxon & Moment.
📦 Compiled JS Bundles
| Bundle File | Contents |
|---|---|
| compiled-frameworks.min.js | jQuery 3.7.1 + Bootstrap JS |
| compiled-framework-plugins.min.js | jQuery UI, Chosen, Growl, TagsInput, touch-punch... |
| compiled-global-component.min.js | Luxon, Moment, Popper, Tippy, Shepherd, SlimSelect, Croppie, Packery, Mermaid, Marked... |
| compiled-app.min.js | app.js + all core/ modules + all Domain/**/*.js (auto-discovered) |
| compiled-htmx.min.js | HTMX 1.9 |
| compiled-tiptap-editor.min.js | TipTap 2 + all extensions (Webpack bundled with tree-shaking) |
| compiled-tiptap-toolbar.min.js | TipTap toolbar UI component |
| compiled-calendar-component.min.js | FullCalendar 6 + iCal + Google Calendar + Luxon adapter |
| compiled-table-component.min.js | DataTables + RowGroup + RowReorder + Buttons |
| compiled-gantt-component.min.js | Frappe Gantt + Snap.svg |
| compiled-chart-component.min.js | Chart.js 3 + Luxon adapter |
| compiled-footer.min.js | Prism.js syntax highlighter |
| html2canvas.min.js + jspdf.umd.min.js | Lazy-loaded for PDF/PNG export (unversioned, stable URL) |
CSS System public/assets/css/ & less/
Layered approach: LESS compiles the core design system (variables, typography, layout), component CSS files provide scoped component styles, and Tailwind CSS adds utility classes. All three are merged into main.{version}.min.css.
structure.css
Core layout grid, sidebar, main content area, page wrapper. The structural backbone of every Leantime page.
nav.css
27 KB of navigation styles — top bar, left sidebar, breadcrumbs, dropdowns, active states and responsive collapse.
kanban.css
37 KB Kanban board styles. Columns, card drag handles, swimlanes, WIP limits indicator, and responsive stacking.
report-deck.css
83 KB — the largest component. Full slide-deck and reporting view, including chart containers, data tables, and print-ready layout.
forms.css
49 KB form styles. Input groups, validation states, custom checkboxes/radios, date pickers, and file upload dropzones.
mobile.css
57 KB responsive overrides. Transforms every view for touch & small screens, including swipeable sidebars and collapsible sections.
tiptap-editor.css
95 KB — the largest single CSS file. Full TipTap rich editor chrome: toolbar, bubble menu, table editing UI, code block themes, and placeholder animations.
accessibility.css
Focus rings, skip links, high-contrast colour overrides, and screen-reader-only utility classes. WCAG 2.1 AA compliant.
All CSS Component Files
| File | Purpose | Size |
|---|---|---|
| style.default.css | Default theme — colours, shadows, brand tokens | 54 KB |
| tiptap-editor.css | Rich text editor chrome | 96 KB |
| report-deck.css | Report & slide deck views | 83 KB |
| resource-allocation.css | Resource planning board | 53 KB |
| mobile.css | Responsive / mobile overrides | 58 KB |
| forms.css | All form elements & validation | 50 KB |
| kanban.css | Kanban board & cards | 38 KB |
| wiki.css | Wiki / knowledge base views | 25 KB |
| nav.css | Navigation & sidebar | 27 KB |
| reverse-wizard.css | Onboarding wizard UI | 20 KB |
| progressbars.css | Progress bars & gauges | 19 KB |
| tables.css | Data tables & grids | 18 KB |
| dropdowns.css | Dropdown menus | 16 KB |
| tab-group.css | Tab navigation groups | 10 KB |
| calendar.css | Calendar view overrides | 11 KB |
| stat-tiles.css | Dashboard stat tile cards | 9 KB |
| sortableList.css | Draggable sortable lists | 5 KB |
| period-picker.css | Date period picker widget | 6 KB |
| print.css | Print media stylesheet | 3 KB |
| accessibility.css | Focus, ARIA, high-contrast | 2 KB |
Build System
The build system is defined in webpack.mix.js. It reads the version from package.json and stamps every compiled file with a version suffix to bust browser caches on deployment.
const version = pjson.version; // "3.10.1" mix // 1. Framework JS (jQuery + Bootstrap) .combine(['jquery.js', 'bootstrap.min.js'], `compiled-frameworks.${version}.min.js`) // 2. Application JS (all Domain JS auto-discovered via glob) .combine(['app.js', 'snippets.js', '...glob.sync("app/Domain/**/*.js")'], `compiled-app.${version}.min.js`) // 3. LESS -> CSS .less('./less/main.less', `main.${version}.min.css`) // 4. Tailwind utility layer .tailwind() // 5. TipTap (full Webpack bundle with tree-shaking) .js('./tiptap/index.js', `compiled-tiptap-editor.${version}.min.js`) // 6. ESLint (auto-fix on build) .eslint({ fix: true });
Domain JS Discovery: All .js files under app/Domain/**/ are automatically picked up via glob.sync() and merged into compiled-app.min.js. Adding a new JS file in any domain module folder is enough to include it in the bundle.
UI Libraries
| Library | Version | Purpose |
|---|---|---|
| jQuery | 3.7.1 | DOM manipulation, AJAX, event handling — primary JS runtime |
| HTMX | ^1.9.12 | Server-driven partial page updates without full-page reloads |
| TipTap 2 | ^2.11.5 | ProseMirror-based rich text editor with 20+ extensions |
| FullCalendar | ^6.1.20 | Calendar & scheduling view with iCal & Google Calendar feeds |
| Chart.js | ^3.6.0 | Line, bar, doughnut charts on dashboards & reports |
| DataTables | ^1.13.11 | Server-side sortable/filterable tables |
| GridStack | ^12.1.1 | Drag-and-drop dashboard widget grid |
| Frappe Gantt | libs/ | Gantt chart view for project timelines |
| Shepherd.js | ^11.2.0 | User onboarding tour overlays |
| Uppy | ^3.25.3 | File upload UI with AWS S3 direct upload support |
| Mermaid | ^11.12.3 | Diagram-as-code rendering in wiki/comments |
| Lottie Player | ^2.0.4 | JSON-based animations (loading, empty states) |
| Croppie | ^2.6.5 | In-browser image cropper for avatar uploads |
| Tippy.js | ^6.3.7 | Tooltip & popover positioning |
| Luxon + Moment | ^3.4.4 / ^2.29.4 | Date parsing, formatting, timezone support |
| jsTree | ^3.3.16 | Hierarchical tree widget for project structure |
| Isotope + Packery | ^3.0.6 / ^2.1.2 | Masonry & filterable grid layouts (Idea board) |
| Leader Line | ^1.0.7 | SVG connector lines between DOM elements (canvas diagrams) |
| KaTeX | ^0.17.0 | LaTeX math rendering in wiki & comments |
| Font Awesome 6 | ^6.5.2 | Icon set used throughout the UI |
PHP Dependencies
| Package | Purpose |
|---|---|
| laravel/framework ^v11.44 | Application framework — IoC, ORM, routing, queues, mail |
| laravel/sanctum ^4.0 | API token authentication & SPA cookie auth |
| laravel/socialite ^5.16 | OAuth2 social login (13 providers) |
| laravel/mcp ^0.1.1 | Model Context Protocol API for AI agent integration |
| guzzlehttp/guzzle ^7.9 | HTTP client for external API calls |
| phpmailer/phpmailer ^6.6 | Transactional email delivery |
| aws/aws-sdk-php ^3.344 | AWS S3 file storage & other AWS services |
| sabre/dav ^4.7 | CalDAV/WebDAV server for calendar sync |
| prism-php/prism ^0.57 | AI completions via OpenAI, Anthropic, etc. |
| inspector-apm/neuron-ai 1.12.8 | NeuronAI agent framework for AI features |
| sentry/sentry-laravel ^4.13 | Error tracking & performance monitoring |
| stripe/stripe-php ^v17.3 | Payment processing |
| robthree/twofactorauth ^1.8 | TOTP 2FA generation & verification |
| league/flysystem-aws-s3-v3 | S3 filesystem adapter for file uploads |
| symfony/cache ^7.2 | PSR-6/16 cache abstraction |
| ramsey/uuid ^4.3 | UUID generation throughout the domain layer |
| spatie/icalendar-generator ^2.6 | Generate iCal feeds for events & tasks |
| hkulekci/qdrant ^0.5.8 | Qdrant vector database client for AI semantic search |
| phpseclib/phpseclib ~3.0 | Cryptography primitives for SAML2 & OIDC |
Configuration
# Application APP_NAME=Leantime APP_ENV=production # production | local | testing APP_DEBUG=false APP_URL=https://your-domain.com # Database DB_CONNECTION=mysql # mysql | pgsql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=leantime DB_USERNAME=leantime DB_PASSWORD=secret # Cache / Sessions CACHE_DRIVER=redis # redis | file | array SESSION_DRIVER=redis REDIS_HOST=127.0.0.1 # File Storage FILESYSTEM_DISK=local # local | s3 AWS_BUCKET=my-leantime-bucket # Mail MAIL_MAILER=smtp MAIL_HOST=smtp.example.com MAIL_FROM_ADDRESS=noreply@leantime.io # AI / Sentry / Stripe (optional) OPENAI_API_KEY=sk-... SENTRY_LARAVEL_DSN=https://... STRIPE_SECRET=sk_live_...
Node Requirements: Node ≥18 and npm are required to build frontend assets. Run npm install then npx mix (dev) or npx mix --production (prod) to compile all JS & CSS bundles.
PHP Requirements: PHP ≥8.2 with extensions: mysqli, pdo_mysql, ldap, zip, mbstring, pcntl, posix, bcmath, simplexml, openssl, gd, fileinfo, dom. Install with composer install.