
Building a Modern Project Management System: How We Architected Complexus for Scale and Speed
Are you building a complex web application and struggling with structure and maintainability? This article dives deep into the architecture of Complexus, a modern project management system, revealing how we leveraged cutting-edge technologies and proven design principles to build a scalable and efficient frontend. Learn how we combined Turborepo, a custom UI library, and Domain-Driven Design to create a robust system.
The Power of a Monorepo: Speed and Consistency with Turborepo
Managing multiple applications and shared libraries can quickly become a nightmare. That's why we chose a monorepo structure for Complexus, using Turborepo to manage our codebase.
- Simplified Dependency Management: Easily manage dependencies across projects.
- Streamlined Code Sharing: Share code seamlessly between applications.
- Atomic Commits: Make changes across multiple projects in a single commit.
- Consistent Code Style: Enforce uniform standards across the entire codebase.
Turborepo's intelligent caching and efficient task orchestration dramatically speed up build times and improve the developer experience. Using Turbopack with Next.js provides near-instantaneous updates during development.
Inside the Complexus Monorepo: A Clear and Modular Structure
Our monorepo is organized for clarity and maintainability:
complexus-monorepo/
├── apps/
│ ├── projects/ # Core project management system (Next.js)
│ ├── landing/ # Marketing landing page (Next.js)
│ └── docs/ # Documentation site (Nextra)
├── packages/
│ ├── ui/ # Custom UI component library
│ ├── icons/ # Shared SVG icons
│ ├── lib/ # Shared utilities
│ ├── tailwind-config/ # Tailwind CSS configuration
│ ├── eslint-config/ # ESLint configuration
│ └── tsconfig/ # TypeScript configuration
├── package.json # Root dependencies and scripts
├── pnpm-workspace.yaml # Workspace definition
└── turbo.json # Turborepo configuration
This structure separates deployable applications from reusable code, making it easier to navigate and maintain the codebase.
Shared Packages: The Key to Consistency and Efficiency
The packages/
directory is where we define shared UI resources and configurations.
ui
: Our custom UI component library.icons
: A centralized repository for SVG icons.lib
: Shared utility functions, including Tailwind CSS class merging.tailwind-config
: Base Tailwind CSS theme for visual consistency.eslint-config
: Shared ESLint rules for code quality.tsconfig
: Base TypeScript configurations.
Sharing these packages ensures a consistent look and feel and reduces code duplication.
Domain-Driven Design: Structuring Application Logic for Scalability
To manage the complexity of the main project management application, we adopted Domain-Driven Design (DDD) principles, organizing code by feature or domain within a modules/
directory. For example:
apps/projects/src/
├── app/ # Next.js App Router
├── components/ # Global components
├── lib/ # App-specific utilities
├── modules/ # Domain/Feature modules
│ ├── sprints/ # Sprints feature
│ │ ├── components/
│ │ ├── hooks/
│ │ ├── queries/
│ │ ├── mutations/
│ │ ├── lib/
│ │ └── types/
│ ├── tasks/ # Tasks feature
│ │ └── ...
│ ├── settings/ # Project Settings feature
│ │ └── ...
│ └── ... # Other features
├── styles/ # Global styles
└── ...
Each module is self-contained, making it easier to add new features and for teams to collaborate effectively. Organizing a large system for managing projects using this pattern can increase development velocity and keep the features clearly segmented.
Benefits of Feature-Based Structure
- Cohesion: Related code is grouped together.
- Modularity: Features are self-contained and promote code reuse.
- Scalability: New modules can be added easily.
- Team Collaboration: Different teams can own separate modules.
Seamless Authentication Across Subdomains with NextAuth.js v5
Complexus uses subdomains. We used NextAuth.js v5 to achieve seamless authentication across all subdomains. The magic lies in correctly configuring the session cookie:
Setting the domain
attribute to .complexus.app
ensures the session cookie is accessible across all subdomains.
Documentation with Nextra: Clear and Concise
We use Nextra for our documentation site. Nextra integrates seamlessly with Next.js and allows us to write documentation in Markdown (MDX), embedding React components directly into the pages.
Key Takeaways: Building Scalable Frontend Architectures with TypeScript
Building with TypeScript and architecting a project management system like Complexus requires careful planning and the right tools. By combining Turborepo, shared packages, Domain-Driven Design, NextAuth.js, and Nextra, we've created a scalable and maintainable frontend architecture. These best practices and architectural pillars can be applied to other complex web applications to realize positive impacts on development velocity and long-term maintainability.