diff --git a/.AI_INSTRUCTIONS_SYNC.md b/.AI_INSTRUCTIONS_SYNC.md
new file mode 100644
index 0000000000..b268064af0
--- /dev/null
+++ b/.AI_INSTRUCTIONS_SYNC.md
@@ -0,0 +1,41 @@
+# AI Instructions Synchronization Guide
+
+**This file has moved!**
+
+All AI documentation and synchronization guidelines are now in the `.ai/` directory.
+
+## New Locations
+
+- **Sync Guide**: [.ai/meta/sync-guide.md](.ai/meta/sync-guide.md)
+- **Maintaining Docs**: [.ai/meta/maintaining-docs.md](.ai/meta/maintaining-docs.md)
+- **Documentation Hub**: [.ai/README.md](.ai/README.md)
+
+## Quick Overview
+
+All AI instructions are now organized in `.ai/` directory:
+
+```
+.ai/
+├── README.md # Navigation hub
+├── core/ # Project information
+├── development/ # Dev workflows
+├── patterns/ # Code patterns
+└── meta/ # Documentation guides
+```
+
+### For AI Assistants
+
+- **Claude Code**: Use `CLAUDE.md` (references `.ai/` files)
+- **Cursor IDE**: Use `.cursor/rules/coolify-ai-docs.mdc` (references `.ai/` files)
+- **All Tools**: Browse `.ai/` directory for detailed documentation
+
+### Key Principles
+
+1. **Single Source of Truth**: Each piece of information exists in ONE file only
+2. **Cross-Reference**: Other files reference the source, don't duplicate
+3. **Organized by Topic**: Core, Development, Patterns, Meta
+4. **Version Consistency**: All versions in `.ai/core/technology-stack.md`
+
+## For More Information
+
+See [.ai/meta/sync-guide.md](.ai/meta/sync-guide.md) for complete synchronization guidelines and [.ai/meta/maintaining-docs.md](.ai/meta/maintaining-docs.md) for documentation maintenance instructions.
diff --git a/.ai/README.md b/.ai/README.md
new file mode 100644
index 0000000000..ea7812496e
--- /dev/null
+++ b/.ai/README.md
@@ -0,0 +1,148 @@
+# Coolify AI Documentation
+
+Welcome to the Coolify AI documentation hub. This directory contains all AI assistant instructions organized by topic for easy navigation and maintenance.
+
+## Quick Start
+
+- **For Claude Code**: Start with [CLAUDE.md in root directory](../CLAUDE.md)
+- **For Cursor IDE**: Check `.cursor/rules/coolify-ai-docs.mdc` which references this directory
+- **For Other AI Tools**: Continue reading below
+
+## Documentation Structure
+
+### 📚 Core Documentation
+Essential project information and architecture:
+
+- **[Technology Stack](core/technology-stack.md)** - All versions, packages, and dependencies (Laravel 12.4.1, PHP 8.4.7, etc.)
+- **[Project Overview](core/project-overview.md)** - What Coolify is and how it works
+- **[Application Architecture](core/application-architecture.md)** - System design and component relationships
+- **[Deployment Architecture](core/deployment-architecture.md)** - How deployments work end-to-end, including Coolify Docker Compose extensions (custom fields)
+
+### 💻 Development
+Day-to-day development practices:
+
+- **[Workflow](development/development-workflow.md)** - Development setup, commands, and daily workflows
+- **[Testing Patterns](development/testing-patterns.md)** - How to write and run tests (Unit vs Feature, Docker requirements)
+- **[Laravel Boost](development/laravel-boost.md)** - Laravel-specific guidelines and best practices
+
+### 🎨 Patterns
+Code patterns and best practices by domain:
+
+- **[Database Patterns](patterns/database-patterns.md)** - Eloquent, migrations, relationships
+- **[Frontend Patterns](patterns/frontend-patterns.md)** - Livewire, Alpine.js, Tailwind CSS
+- **[Security Patterns](patterns/security-patterns.md)** - Authentication, authorization, security best practices
+- **[Form Components](patterns/form-components.md)** - Enhanced form components with authorization
+- **[API & Routing](patterns/api-and-routing.md)** - API design, routing conventions, REST patterns
+
+### 📖 Meta
+Documentation about documentation:
+
+- **[Maintaining Docs](meta/maintaining-docs.md)** - How to update and improve this documentation
+- **[Sync Guide](meta/sync-guide.md)** - Keeping documentation synchronized across tools
+
+## Quick Decision Tree
+
+**What do you need help with?**
+
+### Running Commands
+→ [development/development-workflow.md](development/development-workflow.md)
+- Frontend: `npm run dev`, `npm run build`
+- Backend: `php artisan serve`, `php artisan migrate`
+- Tests: Docker for Feature tests, mocking for Unit tests
+- Code quality: `./vendor/bin/pint`, `./vendor/bin/phpstan`
+
+### Writing Tests
+→ [development/testing-patterns.md](development/testing-patterns.md)
+- **Unit tests**: No database, use mocking, run outside Docker
+- **Feature tests**: Can use database, must run inside Docker
+- Command: `docker exec coolify php artisan test`
+
+### Building UI
+→ [patterns/frontend-patterns.md](patterns/frontend-patterns.md) or [patterns/form-components.md](patterns/form-components.md)
+- Livewire components with server-side state
+- Alpine.js for client-side interactivity
+- Tailwind CSS 4.1.4 for styling
+- Form components with built-in authorization
+
+### Database Work
+→ [patterns/database-patterns.md](patterns/database-patterns.md)
+- Eloquent ORM patterns
+- Migration best practices
+- Relationship definitions
+- Query optimization
+
+### Security & Auth
+→ [patterns/security-patterns.md](patterns/security-patterns.md)
+- Team-based access control
+- Policy and gate patterns
+- Form authorization (canGate, canResource)
+- API security
+
+### Laravel-Specific Questions
+→ [development/laravel-boost.md](development/laravel-boost.md)
+- Laravel 12 patterns
+- Livewire 3 best practices
+- Pest testing patterns
+- Laravel conventions
+
+### Docker Compose Extensions
+→ [core/deployment-architecture.md](core/deployment-architecture.md#coolify-docker-compose-extensions)
+- Custom fields: `exclude_from_hc`, `content`, `isDirectory`
+- How to use inline file content
+- Health check exclusion patterns
+- Volume creation control
+
+### Version Numbers
+→ [core/technology-stack.md](core/technology-stack.md)
+- **Single source of truth** for all version numbers
+- Don't duplicate versions elsewhere, reference this file
+
+## Navigation Tips
+
+1. **Start broad**: Begin with project-overview or ../CLAUDE.md
+2. **Get specific**: Navigate to topic-specific files for details
+3. **Cross-reference**: Files link to related topics
+4. **Single source**: Version numbers and critical data exist in ONE place only
+
+## For AI Assistants
+
+### Important Patterns to Follow
+
+**Testing Commands:**
+- Unit tests: `./vendor/bin/pest tests/Unit` (no database, outside Docker)
+- Feature tests: `docker exec coolify php artisan test` (requires database, inside Docker)
+- NEVER run Feature tests outside Docker - they will fail with database connection errors
+
+**Version Numbers:**
+- Always use exact versions from [technology-stack.md](core/technology-stack.md)
+- Laravel 12.4.1, PHP 8.4.7, Tailwind 4.1.4
+- Don't use "v12" or "8.4" - be precise
+
+**Form Authorization:**
+- ALWAYS include `canGate` and `:canResource` on form components
+- See [form-components.md](patterns/form-components.md) for examples
+
+**Livewire Components:**
+- MUST have exactly ONE root element
+- See [frontend-patterns.md](patterns/frontend-patterns.md) for details
+
+**Code Style:**
+- Run `./vendor/bin/pint` before finalizing changes
+- Follow PSR-12 standards
+- Use PHP 8.4 features (constructor promotion, typed properties, etc.)
+
+## Contributing
+
+When updating documentation:
+1. Read [meta/maintaining-docs.md](meta/maintaining-docs.md)
+2. Follow the single source of truth principle
+3. Update cross-references when moving content
+4. Test all links work
+5. Run Pint on markdown files if applicable
+
+## Questions?
+
+- **Claude Code users**: Check [../CLAUDE.md](../CLAUDE.md) first
+- **Cursor IDE users**: Check `.cursor/rules/coolify-ai-docs.mdc`
+- **Documentation issues**: See [meta/maintaining-docs.md](meta/maintaining-docs.md)
+- **Sync issues**: See [meta/sync-guide.md](meta/sync-guide.md)
diff --git a/.ai/core/application-architecture.md b/.ai/core/application-architecture.md
new file mode 100644
index 0000000000..c1fe7c470e
--- /dev/null
+++ b/.ai/core/application-architecture.md
@@ -0,0 +1,612 @@
+# Coolify Application Architecture
+
+## Laravel Project Structure
+
+### **Core Application Directory** ([app/](mdc:app))
+
+```
+app/
+├── Actions/ # Business logic actions (Action pattern)
+├── Console/ # Artisan commands
+├── Contracts/ # Interface definitions
+├── Data/ # Data Transfer Objects (Spatie Laravel Data)
+├── Enums/ # Enumeration classes
+├── Events/ # Event classes
+├── Exceptions/ # Custom exception classes
+├── Helpers/ # Utility helper classes
+├── Http/ # HTTP layer (Controllers, Middleware, Requests)
+├── Jobs/ # Background job classes
+├── Listeners/ # Event listeners
+├── Livewire/ # Livewire components (Frontend)
+├── Models/ # Eloquent models (Domain entities)
+├── Notifications/ # Notification classes
+├── Policies/ # Authorization policies
+├── Providers/ # Service providers
+├── Repositories/ # Repository pattern implementations
+├── Services/ # Service layer classes
+├── Traits/ # Reusable trait classes
+└── View/ # View composers and creators
+```
+
+## Core Domain Models
+
+### **Infrastructure Management**
+
+#### **[Server.php](mdc:app/Models/Server.php)** (46KB, 1343 lines)
+- **Purpose**: Physical/virtual server management
+- **Key Relationships**:
+ - `hasMany(Application::class)` - Deployed applications
+ - `hasMany(StandalonePostgresql::class)` - Database instances
+ - `belongsTo(Team::class)` - Team ownership
+- **Key Features**:
+ - SSH connection management
+ - Resource monitoring
+ - Proxy configuration (Traefik/Caddy)
+ - Docker daemon interaction
+
+#### **[Application.php](mdc:app/Models/Application.php)** (74KB, 1734 lines)
+- **Purpose**: Application deployment and management
+- **Key Relationships**:
+ - `belongsTo(Server::class)` - Deployment target
+ - `belongsTo(Environment::class)` - Environment context
+ - `hasMany(ApplicationDeploymentQueue::class)` - Deployment history
+- **Key Features**:
+ - Git repository integration
+ - Docker build and deployment
+ - Environment variable management
+ - SSL certificate handling
+
+#### **[Service.php](mdc:app/Models/Service.php)** (58KB, 1325 lines)
+- **Purpose**: Multi-container service orchestration
+- **Key Relationships**:
+ - `hasMany(ServiceApplication::class)` - Service components
+ - `hasMany(ServiceDatabase::class)` - Service databases
+ - `belongsTo(Environment::class)` - Environment context
+- **Key Features**:
+ - Docker Compose generation
+ - Service dependency management
+ - Health check configuration
+
+### **Team & Project Organization**
+
+#### **[Team.php](mdc:app/Models/Team.php)** (8.9KB, 308 lines)
+- **Purpose**: Multi-tenant team management
+- **Key Relationships**:
+ - `hasMany(User::class)` - Team members
+ - `hasMany(Project::class)` - Team projects
+ - `hasMany(Server::class)` - Team servers
+- **Key Features**:
+ - Resource limits and quotas
+ - Team-based access control
+ - Subscription management
+
+#### **[Project.php](mdc:app/Models/Project.php)** (4.3KB, 156 lines)
+- **Purpose**: Project organization and grouping
+- **Key Relationships**:
+ - `hasMany(Environment::class)` - Project environments
+ - `belongsTo(Team::class)` - Team ownership
+- **Key Features**:
+ - Environment isolation
+ - Resource organization
+
+#### **[Environment.php](mdc:app/Models/Environment.php)**
+- **Purpose**: Environment-specific configuration
+- **Key Relationships**:
+ - `hasMany(Application::class)` - Environment applications
+ - `hasMany(Service::class)` - Environment services
+ - `belongsTo(Project::class)` - Project context
+
+### **Database Management Models**
+
+#### **Standalone Database Models**
+- **[StandalonePostgresql.php](mdc:app/Models/StandalonePostgresql.php)** (11KB, 351 lines)
+- **[StandaloneMysql.php](mdc:app/Models/StandaloneMysql.php)** (11KB, 351 lines)
+- **[StandaloneMariadb.php](mdc:app/Models/StandaloneMariadb.php)** (10KB, 337 lines)
+- **[StandaloneMongodb.php](mdc:app/Models/StandaloneMongodb.php)** (12KB, 370 lines)
+- **[StandaloneRedis.php](mdc:app/Models/StandaloneRedis.php)** (12KB, 394 lines)
+- **[StandaloneKeydb.php](mdc:app/Models/StandaloneKeydb.php)** (11KB, 347 lines)
+- **[StandaloneDragonfly.php](mdc:app/Models/StandaloneDragonfly.php)** (11KB, 347 lines)
+- **[StandaloneClickhouse.php](mdc:app/Models/StandaloneClickhouse.php)** (10KB, 336 lines)
+
+**Common Features**:
+- Database configuration management
+- Backup scheduling and execution
+- Connection string generation
+- Health monitoring
+
+### **Configuration & Settings**
+
+#### **[EnvironmentVariable.php](mdc:app/Models/EnvironmentVariable.php)** (7.6KB, 219 lines)
+- **Purpose**: Application environment variable management
+- **Key Features**:
+ - Encrypted value storage
+ - Build-time vs runtime variables
+ - Shared variable inheritance
+
+#### **[InstanceSettings.php](mdc:app/Models/InstanceSettings.php)** (3.2KB, 124 lines)
+- **Purpose**: Global Coolify instance configuration
+- **Key Features**:
+ - FQDN and port configuration
+ - Auto-update settings
+ - Security configurations
+
+## Architectural Patterns
+
+### **Action Pattern** ([app/Actions/](mdc:app/Actions))
+
+Using [lorisleiva/laravel-actions](mdc:composer.json) for business logic encapsulation:
+
+```php
+// Example Action structure
+class DeployApplication extends Action
+{
+ public function handle(Application $application): void
+ {
+ // Business logic for deployment
+ }
+
+ public function asJob(Application $application): void
+ {
+ // Queue job implementation
+ }
+}
+```
+
+**Key Action Categories**:
+- **Application/**: Deployment and management actions
+- **Database/**: Database operations
+- **Server/**: Server management actions
+- **Service/**: Service orchestration actions
+
+### **Repository Pattern** ([app/Repositories/](mdc:app/Repositories))
+
+Data access abstraction layer:
+- Encapsulates database queries
+- Provides testable data layer
+- Abstracts complex query logic
+
+### **Service Layer** ([app/Services/](mdc:app/Services))
+
+Business logic services:
+- External API integrations
+- Complex business operations
+- Cross-cutting concerns
+
+## Data Flow Architecture
+
+### **Request Lifecycle**
+
+1. **HTTP Request** → [routes/web.php](mdc:routes/web.php)
+2. **Middleware** → Authentication, authorization
+3. **Livewire Component** → [app/Livewire/](mdc:app/Livewire)
+4. **Action/Service** → Business logic execution
+5. **Model/Repository** → Data persistence
+6. **Response** → Livewire reactive update
+
+### **Background Processing**
+
+1. **Job Dispatch** → Queue system (Redis)
+2. **Job Processing** → [app/Jobs/](mdc:app/Jobs)
+3. **Action Execution** → Business logic
+4. **Event Broadcasting** → Real-time updates
+5. **Notification** → User feedback
+
+## Security Architecture
+
+### **Multi-Tenant Isolation**
+
+```php
+// Team-based query scoping
+class Application extends Model
+{
+ public function scopeOwnedByCurrentTeam($query)
+ {
+ return $query->whereHas('environment.project.team', function ($q) {
+ $q->where('id', currentTeam()->id);
+ });
+ }
+}
+```
+
+### **Authorization Layers**
+
+1. **Team Membership** → User belongs to team
+2. **Resource Ownership** → Resource belongs to team
+3. **Policy Authorization** → [app/Policies/](mdc:app/Policies)
+4. **Environment Isolation** → Project/environment boundaries
+
+### **Data Protection**
+
+- **Environment Variables**: Encrypted at rest
+- **SSH Keys**: Secure storage and transmission
+- **API Tokens**: Sanctum-based authentication
+- **Audit Logging**: [spatie/laravel-activitylog](mdc:composer.json)
+
+## Configuration Hierarchy
+
+### **Global Configuration**
+- **[InstanceSettings](mdc:app/Models/InstanceSettings.php)**: System-wide settings
+- **[config/](mdc:config)**: Laravel configuration files
+
+### **Team Configuration**
+- **[Team](mdc:app/Models/Team.php)**: Team-specific settings
+- **[ServerSetting](mdc:app/Models/ServerSetting.php)**: Server configurations
+
+### **Project Configuration**
+- **[ProjectSetting](mdc:app/Models/ProjectSetting.php)**: Project settings
+- **[Environment](mdc:app/Models/Environment.php)**: Environment variables
+
+### **Application Configuration**
+- **[ApplicationSetting](mdc:app/Models/ApplicationSetting.php)**: App-specific settings
+- **[EnvironmentVariable](mdc:app/Models/EnvironmentVariable.php)**: Runtime configuration
+
+## Event-Driven Architecture
+
+### **Event Broadcasting** ([app/Events/](mdc:app/Events))
+
+Real-time updates using Laravel Echo and WebSockets:
+
+```php
+// Example event structure
+class ApplicationDeploymentStarted implements ShouldBroadcast
+{
+ public function broadcastOn(): array
+ {
+ return [
+ new PrivateChannel("team.{$this->application->team->id}"),
+ ];
+ }
+}
+```
+
+### **Event Listeners** ([app/Listeners/](mdc:app/Listeners))
+
+- Deployment status updates
+- Resource monitoring alerts
+- Notification dispatching
+- Audit log creation
+
+## Database Design Patterns
+
+### **Polymorphic Relationships**
+
+```php
+// Environment variables can belong to multiple resource types
+class EnvironmentVariable extends Model
+{
+ public function resource(): MorphTo
+ {
+ return $this->morphTo();
+ }
+}
+```
+
+### **Team-Based Soft Scoping**
+
+All major resources include team-based query scoping with request-level caching:
+
+```php
+// ✅ CORRECT - Use cached methods (request-level cache via once())
+$applications = Application::ownedByCurrentTeamCached();
+$servers = Server::ownedByCurrentTeamCached();
+
+// ✅ CORRECT - Filter cached collection in memory
+$activeServers = Server::ownedByCurrentTeamCached()->where('is_active', true);
+
+// Only use query builder when you need eager loading or fresh data
+$projects = Project::ownedByCurrentTeam()->with('environments')->get();
+```
+
+See [Database Patterns](.ai/patterns/database-patterns.md#request-level-caching-with-ownedbycurrentteamcached) for full documentation.
+
+### **Configuration Inheritance**
+
+Environment variables cascade from:
+1. **Shared Variables** → Team-wide defaults
+2. **Project Variables** → Project-specific overrides
+3. **Application Variables** → Application-specific values
+
+## Integration Patterns
+
+### **Git Provider Integration**
+
+Abstracted git operations supporting:
+- **GitHub**: [app/Models/GithubApp.php](mdc:app/Models/GithubApp.php)
+- **GitLab**: [app/Models/GitlabApp.php](mdc:app/Models/GitlabApp.php)
+- **Bitbucket**: Webhook integration
+- **Gitea**: Self-hosted Git support
+
+### **Docker Integration**
+
+- **Container Management**: Direct Docker API communication
+- **Image Building**: Dockerfile and Buildpack support
+- **Network Management**: Custom Docker networks
+- **Volume Management**: Persistent storage handling
+
+### **SSH Communication**
+
+- **[phpseclib/phpseclib](mdc:composer.json)**: Secure SSH connections
+- **Multiplexing**: Connection pooling for efficiency
+- **Key Management**: [PrivateKey](mdc:app/Models/PrivateKey.php) model
+
+## Testing Architecture
+
+### **Test Structure** ([tests/](mdc:tests))
+
+```
+tests/
+├── Feature/ # Integration tests
+├── Unit/ # Unit tests
+├── Browser/ # Dusk browser tests
+├── Traits/ # Test helper traits
+├── Pest.php # Pest configuration
+└── TestCase.php # Base test case
+```
+
+### **Testing Patterns**
+
+- **Feature Tests**: Full request lifecycle testing
+- **Unit Tests**: Individual class/method testing
+- **Browser Tests**: End-to-end user workflows
+- **Database Testing**: Factories and seeders
+
+## Performance Considerations
+
+### **Query Optimization**
+
+- **Eager Loading**: Prevent N+1 queries
+- **Query Scoping**: Team-based filtering
+- **Database Indexing**: Optimized for common queries
+
+### **Caching Strategy**
+
+- **Redis**: Session and cache storage
+- **Model Caching**: Frequently accessed data
+- **Query Caching**: Expensive query results
+
+### **Background Processing**
+
+- **Queue Workers**: Horizon-managed job processing
+- **Job Batching**: Related job grouping
+- **Failed Job Handling**: Automatic retry logic
+
+## Container Status Monitoring System
+
+### **Overview**
+
+Container health status is monitored and updated through **multiple independent paths**. When modifying status logic, **ALL paths must be updated** to ensure consistency.
+
+### **Critical Implementation Locations**
+
+#### **1. SSH-Based Status Updates (Scheduled)**
+**File**: [app/Actions/Docker/GetContainersStatus.php](mdc:app/Actions/Docker/GetContainersStatus.php)
+**Method**: `aggregateApplicationStatus()` (lines 487-540)
+**Trigger**: Scheduled job or manual refresh
+**Frequency**: Every minute (via `ServerCheckJob`)
+
+**Status Aggregation Logic**:
+```php
+// Tracks multiple status flags
+$hasRunning = false;
+$hasRestarting = false;
+$hasUnhealthy = false;
+$hasUnknown = false; // ⚠️ CRITICAL: Must track unknown
+$hasExited = false;
+// ... more states
+
+// Priority: restarting > degraded > running (unhealthy > unknown > healthy)
+if ($hasRunning) {
+ if ($hasUnhealthy) return 'running (unhealthy)';
+ elseif ($hasUnknown) return 'running (unknown)';
+ else return 'running (healthy)';
+}
+```
+
+#### **2. Sentinel-Based Status Updates (Real-time)**
+**File**: [app/Jobs/PushServerUpdateJob.php](mdc:app/Jobs/PushServerUpdateJob.php)
+**Method**: `aggregateMultiContainerStatuses()` (lines 269-298)
+**Trigger**: Sentinel push updates from remote servers
+**Frequency**: Every ~30 seconds (real-time)
+
+**Status Aggregation Logic**:
+```php
+// ⚠️ MUST match GetContainersStatus logic
+$hasRunning = false;
+$hasUnhealthy = false;
+$hasUnknown = false; // ⚠️ CRITICAL: Added to fix bug
+
+foreach ($relevantStatuses as $status) {
+ if (str($status)->contains('running')) {
+ $hasRunning = true;
+ if (str($status)->contains('unhealthy')) $hasUnhealthy = true;
+ if (str($status)->contains('unknown')) $hasUnknown = true; // ⚠️ CRITICAL
+ }
+}
+
+// Priority: unhealthy > unknown > healthy
+if ($hasRunning) {
+ if ($hasUnhealthy) $aggregatedStatus = 'running (unhealthy)';
+ elseif ($hasUnknown) $aggregatedStatus = 'running (unknown)';
+ else $aggregatedStatus = 'running (healthy)';
+}
+```
+
+#### **3. Multi-Server Status Aggregation**
+**File**: [app/Actions/Shared/ComplexStatusCheck.php](mdc:app/Actions/Shared/ComplexStatusCheck.php)
+**Method**: `resource()` (lines 48-210)
+**Purpose**: Aggregates status across multiple servers for applications
+**Used by**: Applications with multiple destinations
+
+**Key Features**:
+- Aggregates statuses from main + additional servers
+- Handles excluded containers (`:excluded` suffix)
+- Calculates overall application health from all containers
+
+**Status Format with Excluded Containers**:
+```php
+// When all containers excluded from health checks:
+return 'running:unhealthy:excluded'; // Container running but unhealthy, monitoring disabled
+return 'running:unknown:excluded'; // Container running, health unknown, monitoring disabled
+return 'running:healthy:excluded'; // Container running and healthy, monitoring disabled
+return 'degraded:excluded'; // Some containers down, monitoring disabled
+return 'exited:excluded'; // All containers stopped, monitoring disabled
+```
+
+#### **4. Service-Level Status Aggregation**
+**File**: [app/Models/Service.php](mdc:app/Models/Service.php)
+**Method**: `complexStatus()` (lines 176-288)
+**Purpose**: Aggregates status for multi-container services
+**Used by**: Docker Compose services
+
+**Status Calculation**:
+```php
+// Aggregates status from all service applications and databases
+// Handles excluded containers separately
+// Returns status with :excluded suffix when all containers excluded
+if (!$hasNonExcluded && $complexStatus === null && $complexHealth === null) {
+ // All services excluded - calculate from excluded containers
+ return "{$excludedStatus}:excluded";
+}
+```
+
+### **Status Flow Diagram**
+
+```
+┌─────────────────────────────────────────────────────────────┐
+│ Container Status Sources │
+└─────────────────────────────────────────────────────────────┘
+ │
+ ┌────────────────────┼────────────────────┐
+ │ │ │
+ ▼ ▼ ▼
+┌───────────────┐ ┌─────────────────┐ ┌──────────────┐
+│ SSH-Based │ │ Sentinel-Based │ │ Multi-Server │
+│ (Scheduled) │ │ (Real-time) │ │ Aggregation │
+├───────────────┤ ├─────────────────┤ ├──────────────┤
+│ ServerCheck │ │ PushServerUp- │ │ ComplexStatus│
+│ Job │ │ dateJob │ │ Check │
+│ │ │ │ │ │
+│ Every ~1min │ │ Every ~30sec │ │ On demand │
+└───────┬───────┘ └────────┬────────┘ └──────┬───────┘
+ │ │ │
+ └────────────────────┼────────────────────┘
+ │
+ ▼
+ ┌───────────────────────┐
+ │ Application/Service │
+ │ Status Property │
+ └───────────────────────┘
+ │
+ ▼
+ ┌───────────────────────┐
+ │ UI Display (Livewire) │
+ └───────────────────────┘
+```
+
+### **Status Priority System**
+
+All status aggregation locations **MUST** follow the same priority:
+
+**For Running Containers**:
+1. **unhealthy** - Container has failing health checks
+2. **unknown** - Container health status cannot be determined
+3. **healthy** - Container is healthy
+
+**For Non-Running States**:
+1. **restarting** → `degraded (unhealthy)`
+2. **running + exited** → `degraded (unhealthy)`
+3. **dead/removing** → `degraded (unhealthy)`
+4. **paused** → `paused`
+5. **created/starting** → `starting`
+6. **exited** → `exited (unhealthy)`
+
+### **Excluded Containers**
+
+When containers have `exclude_from_hc: true` flag or `restart: no`:
+
+**Behavior**:
+- Status is still calculated from container state
+- `:excluded` suffix is appended to indicate monitoring disabled
+- UI shows "(Monitoring Disabled)" badge
+- Action buttons respect the actual container state
+
+**Format**: `{actual-status}:excluded`
+**Examples**: `running:unknown:excluded`, `degraded:excluded`, `exited:excluded`
+
+**All-Excluded Scenario**:
+When ALL containers are excluded from health checks:
+- All three status update paths (PushServerUpdateJob, GetContainersStatus, ComplexStatusCheck) **MUST** calculate status from excluded containers
+- Status is returned with `:excluded` suffix (e.g., `running:healthy:excluded`)
+- **NEVER** skip status updates - always calculate from excluded containers
+- This ensures consistent status regardless of which update mechanism runs
+- Shared logic is in `app/Traits/CalculatesExcludedStatus.php`
+
+### **Important Notes for Developers**
+
+✅ **Container Status Aggregation Service**:
+
+The container status aggregation logic is centralized in `App\Services\ContainerStatusAggregator`.
+
+**Status Format Standard**:
+- **Backend/Storage**: Colon format (`running:healthy`, `degraded:unhealthy`)
+- **UI/Display**: Transform to human format (`Running (Healthy)`, `Degraded (Unhealthy)`)
+
+1. **Using the ContainerStatusAggregator Service**:
+ - Import `App\Services\ContainerStatusAggregator` in any class needing status aggregation
+ - Two methods available:
+ - `aggregateFromStrings(Collection $statusStrings, int $maxRestartCount = 0)` - For pre-formatted status strings
+ - `aggregateFromContainers(Collection $containers, int $maxRestartCount = 0)` - For raw Docker container objects
+ - Returns colon format: `running:healthy`, `degraded:unhealthy`, etc.
+ - Automatically handles crash loop detection via `$maxRestartCount` parameter
+
+2. **State Machine Priority** (handled by service):
+ - Restarting → `degraded:unhealthy` (highest priority)
+ - Crash loop (exited with restarts) → `degraded:unhealthy`
+ - Mixed state (running + exited) → `degraded:unhealthy`
+ - Running → `running:unhealthy` / `running:unknown` / `running:healthy`
+ - Dead/Removing → `degraded:unhealthy`
+ - Paused → `paused:unknown`
+ - Starting/Created → `starting:unknown`
+ - Exited → `exited:unhealthy` (lowest priority)
+
+3. **Test both update paths**:
+ - Run unit tests: `./vendor/bin/pest tests/Unit/ContainerStatusAggregatorTest.php`
+ - Run integration tests: `./vendor/bin/pest tests/Unit/`
+ - Test SSH updates (manual refresh)
+ - Test Sentinel updates (wait 30 seconds)
+
+4. **Handle excluded containers**:
+ - All containers excluded (`exclude_from_hc: true`) - Use `CalculatesExcludedStatus` trait
+ - Mixed excluded/non-excluded containers - Filter then use `ContainerStatusAggregator`
+ - Containers with `restart: no` - Treated same as `exclude_from_hc: true`
+
+5. **Use shared trait for excluded containers**:
+ - Import `App\Traits\CalculatesExcludedStatus` in status calculation classes
+ - Use `getExcludedContainersFromDockerCompose()` to parse exclusions
+ - Use `calculateExcludedStatus()` for full Docker inspect objects (ComplexStatusCheck)
+ - Use `calculateExcludedStatusFromStrings()` for status strings (PushServerUpdateJob, GetContainersStatus)
+
+### **Related Tests**
+
+- **[tests/Unit/ContainerStatusAggregatorTest.php](mdc:tests/Unit/ContainerStatusAggregatorTest.php)**: Core state machine logic (42 comprehensive tests)
+- **[tests/Unit/ContainerHealthStatusTest.php](mdc:tests/Unit/ContainerHealthStatusTest.php)**: Health status aggregation integration
+- **[tests/Unit/PushServerUpdateJobStatusAggregationTest.php](mdc:tests/Unit/PushServerUpdateJobStatusAggregationTest.php)**: Sentinel update logic
+- **[tests/Unit/ExcludeFromHealthCheckTest.php](mdc:tests/Unit/ExcludeFromHealthCheckTest.php)**: Excluded container handling
+
+### **Common Bugs to Avoid**
+
+✅ **Prevented by ContainerStatusAggregator Service**:
+- ❌ **Old Bug**: Forgetting to track `$hasUnknown` flag → ✅ Now centralized in service
+- ❌ **Old Bug**: Inconsistent priority across paths → ✅ Single source of truth
+- ❌ **Old Bug**: Forgetting to update all 4 locations → ✅ Only one location to update
+
+**Still Relevant**:
+
+❌ **Bug**: Forgetting to filter excluded containers before aggregation
+✅ **Fix**: Always use `CalculatesExcludedStatus` trait to filter before calling `ContainerStatusAggregator`
+
+❌ **Bug**: Not passing `$maxRestartCount` for crash loop detection
+✅ **Fix**: Calculate max restart count from containers and pass to `aggregateFromStrings()`/`aggregateFromContainers()`
+
+❌ **Bug**: Not handling excluded containers with `:excluded` suffix
+✅ **Fix**: Check for `:excluded` suffix in UI logic and button visibility
diff --git a/.ai/core/deployment-architecture.md b/.ai/core/deployment-architecture.md
new file mode 100644
index 0000000000..927bdc8de9
--- /dev/null
+++ b/.ai/core/deployment-architecture.md
@@ -0,0 +1,666 @@
+# Coolify Deployment Architecture
+
+## Deployment Philosophy
+
+Coolify orchestrates **Docker-based deployments** across multiple servers with automated configuration generation, zero-downtime deployments, and comprehensive monitoring.
+
+## Core Deployment Components
+
+### Deployment Models
+- **[Application.php](mdc:app/Models/Application.php)** - Main application entity with deployment configurations
+- **[ApplicationDeploymentQueue.php](mdc:app/Models/ApplicationDeploymentQueue.php)** - Deployment job orchestration
+- **[Service.php](mdc:app/Models/Service.php)** - Multi-container service definitions
+- **[Server.php](mdc:app/Models/Server.php)** - Target deployment infrastructure
+
+### Infrastructure Management
+- **[PrivateKey.php](mdc:app/Models/PrivateKey.php)** - SSH key management for secure server access
+- **[StandaloneDocker.php](mdc:app/Models/StandaloneDocker.php)** - Single container deployments
+- **[SwarmDocker.php](mdc:app/Models/SwarmDocker.php)** - Docker Swarm orchestration
+
+## Deployment Workflow
+
+### 1. Source Code Integration
+```
+Git Repository → Webhook → Coolify → Build & Deploy
+```
+
+#### Source Control Models
+- **[GithubApp.php](mdc:app/Models/GithubApp.php)** - GitHub integration and webhooks
+- **[GitlabApp.php](mdc:app/Models/GitlabApp.php)** - GitLab CI/CD integration
+
+#### Deployment Triggers
+- **Git push** to configured branches
+- **Manual deployment** via UI
+- **Scheduled deployments** via cron
+- **API-triggered** deployments
+
+### 2. Build Process
+```
+Source Code → Docker Build → Image Registry → Deployment
+```
+
+#### Build Configurations
+- **Dockerfile detection** and custom Dockerfile support
+- **Buildpack integration** for framework detection
+- **Multi-stage builds** for optimization
+- **Cache layer** management for faster builds
+
+### 3. Deployment Orchestration
+```
+Queue Job → Configuration Generation → Container Deployment → Health Checks
+```
+
+## Deployment Actions
+
+### Location: [app/Actions/](mdc:app/Actions)
+
+#### Application Deployment Actions
+- **Application/** - Core application deployment logic
+- **Docker/** - Docker container management
+- **Service/** - Multi-container service orchestration
+- **Proxy/** - Reverse proxy configuration
+
+#### Database Actions
+- **Database/** - Database deployment and management
+- Automated backup scheduling
+- Connection management and health checks
+
+#### Server Management Actions
+- **Server/** - Server provisioning and configuration
+- SSH connection establishment
+- Docker daemon management
+
+## Configuration Generation
+
+### Dynamic Configuration
+- **[ConfigurationGenerator.php](mdc:app/Services/ConfigurationGenerator.php)** - Generates deployment configurations
+- **[ConfigurationRepository.php](mdc:app/Services/ConfigurationRepository.php)** - Configuration management
+
+### Generated Configurations
+#### Docker Compose Files
+```yaml
+# Generated docker-compose.yml structure
+version: '3.8'
+services:
+ app:
+ image: ${APP_IMAGE}
+ environment:
+ - ${ENV_VARIABLES}
+ labels:
+ - traefik.enable=true
+ - traefik.http.routers.app.rule=Host(`${FQDN}`)
+ volumes:
+ - ${VOLUME_MAPPINGS}
+ networks:
+ - coolify
+```
+
+#### Nginx Configurations
+- **Reverse proxy** setup
+- **SSL termination** with automatic certificates
+- **Load balancing** for multiple instances
+- **Custom headers** and routing rules
+
+## Container Orchestration
+
+### Docker Integration
+- **[DockerImageParser.php](mdc:app/Services/DockerImageParser.php)** - Parse and validate Docker images
+- **Container lifecycle** management
+- **Resource allocation** and limits
+- **Network isolation** and communication
+
+### Volume Management
+- **[LocalFileVolume.php](mdc:app/Models/LocalFileVolume.php)** - Persistent file storage
+- **[LocalPersistentVolume.php](mdc:app/Models/LocalPersistentVolume.php)** - Data persistence
+- **Backup integration** for volume data
+
+### Network Configuration
+- **Custom Docker networks** for isolation
+- **Service discovery** between containers
+- **Port mapping** and exposure
+- **SSL/TLS termination**
+
+## Environment Management
+
+### Environment Isolation
+- **[Environment.php](mdc:app/Models/Environment.php)** - Development, staging, production environments
+- **[EnvironmentVariable.php](mdc:app/Models/EnvironmentVariable.php)** - Application-specific variables
+- **[SharedEnvironmentVariable.php](mdc:app/Models/SharedEnvironmentVariable.php)** - Cross-application variables
+
+### Configuration Hierarchy
+```
+Instance Settings → Server Settings → Project Settings → Application Settings
+```
+
+## Preview Environments
+
+### Git-Based Previews
+- **[ApplicationPreview.php](mdc:app/Models/ApplicationPreview.php)** - Preview environment management
+- **Automatic PR/MR previews** for feature branches
+- **Isolated environments** for testing
+- **Automatic cleanup** after merge/close
+
+### Preview Workflow
+```
+Feature Branch → Auto-Deploy → Preview URL → Review → Cleanup
+```
+
+## SSL & Security
+
+### Certificate Management
+- **[SslCertificate.php](mdc:app/Models/SslCertificate.php)** - SSL certificate automation
+- **Let's Encrypt** integration for free certificates
+- **Custom certificate** upload support
+- **Automatic renewal** and monitoring
+
+### Security Patterns
+- **Private Docker networks** for container isolation
+- **SSH key-based** server authentication
+- **Environment variable** encryption
+- **Access control** via team permissions
+
+## Backup & Recovery
+
+### Database Backups
+- **[ScheduledDatabaseBackup.php](mdc:app/Models/ScheduledDatabaseBackup.php)** - Automated database backups
+- **[ScheduledDatabaseBackupExecution.php](mdc:app/Models/ScheduledDatabaseBackupExecution.php)** - Backup execution tracking
+- **S3-compatible storage** for backup destinations
+
+### Application Backups
+- **Volume snapshots** for persistent data
+- **Configuration export** for disaster recovery
+- **Cross-region replication** for high availability
+
+## Monitoring & Logging
+
+### Real-Time Monitoring
+- **[ActivityMonitor.php](mdc:app/Livewire/ActivityMonitor.php)** - Live deployment monitoring
+- **WebSocket-based** log streaming
+- **Container health checks** and alerts
+- **Resource usage** tracking
+
+### Deployment Logs
+- **Build process** logging
+- **Container startup** logs
+- **Application runtime** logs
+- **Error tracking** and alerting
+
+## Queue System
+
+### Background Jobs
+Location: [app/Jobs/](mdc:app/Jobs)
+- **Deployment jobs** for async processing
+- **Server monitoring** jobs
+- **Backup scheduling** jobs
+- **Notification delivery** jobs
+
+### Queue Processing
+- **Redis-backed** job queues
+- **Laravel Horizon** for queue monitoring
+- **Failed job** retry mechanisms
+- **Queue worker** auto-scaling
+
+## Multi-Server Deployment
+
+### Server Types
+- **Standalone servers** - Single Docker host
+- **Docker Swarm** - Multi-node orchestration
+- **Remote servers** - SSH-based deployment
+- **Local development** - Docker Desktop integration
+
+### Load Balancing
+- **Traefik integration** for automatic load balancing
+- **Health check** based routing
+- **Blue-green deployments** for zero downtime
+- **Rolling updates** with configurable strategies
+
+## Deployment Strategies
+
+### Zero-Downtime Deployment
+```
+Old Container → New Container Build → Health Check → Traffic Switch → Old Container Cleanup
+```
+
+### Blue-Green Deployment
+- **Parallel environments** for safe deployments
+- **Instant rollback** capability
+- **Database migration** handling
+- **Configuration synchronization**
+
+### Rolling Updates
+- **Gradual instance** replacement
+- **Configurable update** strategy
+- **Automatic rollback** on failure
+- **Health check** validation
+
+## API Integration
+
+### Deployment API
+Routes: [routes/api.php](mdc:routes/api.php)
+- **RESTful endpoints** for deployment management
+- **Webhook receivers** for CI/CD integration
+- **Status reporting** endpoints
+- **Deployment triggering** via API
+
+### Authentication
+- **Laravel Sanctum** API tokens
+- **Team-based** access control
+- **Rate limiting** for API calls
+- **Audit logging** for API usage
+
+## Error Handling & Recovery
+
+### Deployment Failure Recovery
+- **Automatic rollback** on deployment failure
+- **Health check** failure handling
+- **Container crash** recovery
+- **Resource exhaustion** protection
+
+### Monitoring & Alerting
+- **Failed deployment** notifications
+- **Resource threshold** alerts
+- **SSL certificate** expiry warnings
+- **Backup failure** notifications
+
+## Performance Optimization
+
+### Build Optimization
+- **Docker layer** caching
+- **Multi-stage builds** for smaller images
+- **Build artifact** reuse
+- **Parallel build** processing
+
+### Docker Build Cache Preservation
+
+Coolify provides settings to preserve Docker build cache across deployments, addressing cache invalidation issues.
+
+#### The Problem
+
+By default, Coolify injects `ARG` statements into user Dockerfiles for build-time variables. This breaks Docker's cache mechanism because:
+1. **ARG declarations invalidate cache** - Any change in ARG values after the `ARG` instruction invalidates all subsequent layers
+2. **SOURCE_COMMIT changes every commit** - Causes full rebuilds even when code changes are minimal
+
+#### Application Settings
+
+Two toggles in **Advanced Settings** control this behavior:
+
+| Setting | Default | Description |
+|---------|---------|-------------|
+| `inject_build_args_to_dockerfile` | `true` | Controls whether Coolify adds `ARG` statements to Dockerfile |
+| `include_source_commit_in_build` | `false` | Controls whether `SOURCE_COMMIT` is included in build context |
+
+**Database columns:** `application_settings.inject_build_args_to_dockerfile`, `application_settings.include_source_commit_in_build`
+
+#### Buildpack Coverage
+
+| Build Pack | ARG Injection | Method |
+|------------|---------------|--------|
+| **Dockerfile** | ✅ Yes | `add_build_env_variables_to_dockerfile()` |
+| **Docker Compose** (with `build:`) | ✅ Yes | `modify_dockerfiles_for_compose()` |
+| **PR Deployments** (Dockerfile only) | ✅ Yes | `add_build_env_variables_to_dockerfile()` |
+| **Nixpacks** | ❌ No | Generates its own Dockerfile internally |
+| **Static** | ❌ No | Uses internal Dockerfile |
+| **Docker Image** | ❌ No | No build phase |
+
+#### How It Works
+
+**When `inject_build_args_to_dockerfile` is enabled (default):**
+```dockerfile
+# Coolify modifies your Dockerfile to add:
+FROM node:20
+ARG MY_VAR=value
+ARG COOLIFY_URL=...
+ARG SOURCE_COMMIT=abc123 # (if include_source_commit_in_build is true)
+# ... rest of your Dockerfile
+```
+
+**When `inject_build_args_to_dockerfile` is disabled:**
+- Coolify does NOT modify the Dockerfile
+- `--build-arg` flags are still passed (harmless without matching `ARG` in Dockerfile)
+- User must manually add `ARG` statements for any build-time variables they need
+
+**When `include_source_commit_in_build` is disabled (default):**
+- `SOURCE_COMMIT` is NOT included in build-time variables
+- `SOURCE_COMMIT` is still available at **runtime** (in container environment)
+- Docker cache preserved across different commits
+
+#### Recommended Configuration
+
+| Use Case | inject_build_args | include_source_commit | Cache Behavior |
+|----------|-------------------|----------------------|----------------|
+| Maximum cache preservation | `false` | `false` | Best cache retention |
+| Need build-time vars, no commit | `true` | `false` | Cache breaks on var changes |
+| Need commit at build-time | `true` | `true` | Cache breaks every commit |
+| Manual ARG management | `false` | `true` | Cache preserved (no ARG in Dockerfile) |
+
+#### Implementation Details
+
+**Files:**
+- `app/Jobs/ApplicationDeploymentJob.php`:
+ - `set_coolify_variables()` - Conditionally adds SOURCE_COMMIT to Docker build context based on `include_source_commit_in_build` setting
+ - `generate_coolify_env_variables(bool $forBuildTime)` - Distinguishes build-time vs. runtime variables; excludes cache-busting variables like SOURCE_COMMIT from build context unless explicitly enabled
+ - `generate_env_variables()` - Populates `$this->env_args` with build-time ARG values, respecting `include_source_commit_in_build` toggle
+ - `add_build_env_variables_to_dockerfile()` - Injects ARG statements into Dockerfiles after FROM instructions; skips injection if `inject_build_args_to_dockerfile` is disabled
+ - `modify_dockerfiles_for_compose()` - Applies ARG injection to Docker Compose service Dockerfiles; respects `inject_build_args_to_dockerfile` toggle
+- `app/Models/ApplicationSetting.php` - Defines `inject_build_args_to_dockerfile` and `include_source_commit_in_build` boolean properties
+- `app/Livewire/Project/Application/Advanced.php` - Livewire component providing UI bindings for cache preservation toggles
+- `resources/views/livewire/project/application/advanced.blade.php` - Checkbox UI elements for user-facing toggles
+
+**Note:** Docker Compose services without a `build:` section (image-only) are automatically skipped.
+
+### Runtime Optimization
+- **Container resource** limits
+- **Auto-scaling** based on metrics
+- **Connection pooling** for databases
+- **CDN integration** for static assets
+
+## Compliance & Governance
+
+### Audit Trail
+- **Deployment history** tracking
+- **Configuration changes** logging
+- **User action** auditing
+- **Resource access** monitoring
+
+### Backup Compliance
+- **Retention policies** for backups
+- **Encryption at rest** for sensitive data
+- **Cross-region** backup replication
+- **Recovery testing** automation
+
+## Integration Patterns
+
+### CI/CD Integration
+- **GitHub Actions** compatibility
+- **GitLab CI** pipeline integration
+- **Custom webhook** endpoints
+- **Build status** reporting
+
+### External Services
+- **S3-compatible** storage integration
+- **External database** connections
+- **Third-party monitoring** tools
+- **Custom notification** channels
+
+---
+
+## Coolify Docker Compose Extensions
+
+Coolify extends standard Docker Compose with custom fields (often called "magic fields") that provide Coolify-specific functionality. These extensions are processed during deployment and stripped before sending the final compose file to Docker, maintaining full compatibility with Docker's compose specification.
+
+### Overview
+
+**Why Custom Fields?**
+- Enable Coolify-specific features without breaking Docker Compose compatibility
+- Simplify configuration by embedding content directly in compose files
+- Allow fine-grained control over health check monitoring
+- Reduce external file dependencies
+
+**Processing Flow:**
+1. User defines compose file with custom fields
+2. Coolify parses and processes custom fields (creates files, stores settings)
+3. Custom fields are stripped from final compose sent to Docker
+4. Docker receives standard, valid compose file
+
+### Service-Level Extensions
+
+#### `exclude_from_hc`
+
+**Type:** Boolean
+**Default:** `false`
+**Purpose:** Exclude specific services from health check monitoring while still showing their status
+
+**Example Usage:**
+```yaml
+services:
+ watchtower:
+ image: containrrr/watchtower
+ exclude_from_hc: true # Don't monitor this service's health
+
+ backup:
+ image: postgres:16
+ exclude_from_hc: true # Backup containers don't need monitoring
+ restart: always
+```
+
+**Behavior:**
+- Container status is still calculated from Docker state (running, exited, etc.)
+- Status displays with `:excluded` suffix (e.g., `running:healthy:excluded`)
+- UI shows "Monitoring Disabled" indicator
+- Functionally equivalent to `restart: no` for health check purposes
+- See [Container Status with All Excluded](application-architecture.md#container-status-when-all-containers-excluded) for detailed status handling
+
+**Use Cases:**
+- Sidecar containers (watchtower, log collectors)
+- Backup/maintenance containers
+- One-time initialization containers
+- Containers that intentionally restart frequently
+
+**Implementation:**
+- Parsed: `bootstrap/helpers/parsers.php`
+- Status logic: `app/Traits/CalculatesExcludedStatus.php`
+- Validation: `tests/Unit/ExcludeFromHealthCheckTest.php`
+
+### Volume-Level Extensions
+
+Volume extensions only work with **long syntax** (array/object format), not short syntax (string format).
+
+#### `content`
+
+**Type:** String (supports multiline with `|` or `>`)
+**Purpose:** Embed file content directly in compose file for automatic creation during deployment
+
+**Example Usage:**
+```yaml
+services:
+ app:
+ image: node:20
+ volumes:
+ # Inline entrypoint script
+ - type: bind
+ source: ./entrypoint.sh
+ target: /app/entrypoint.sh
+ content: |
+ #!/bin/sh
+ set -e
+ echo "Starting application..."
+ npm run migrate
+ exec "$@"
+
+ # Configuration file with environment variables
+ - type: bind
+ source: ./config.xml
+ target: /etc/app/config.xml
+ content: |
+
+
+
+ ${DB_HOST}
+ ${DB_PORT}
+
+
+```
+
+**Behavior:**
+- Content is written to the host at `source` path before container starts
+- File is created with mode `644` (readable by all, writable by owner)
+- Environment variables in content are interpolated at deployment time
+- Content is stored in `LocalFileVolume` model (encrypted at rest)
+- Original `docker_compose_raw` retains content for editing
+
+**Use Cases:**
+- Entrypoint scripts
+- Configuration files
+- Environment-specific settings
+- Small initialization scripts
+- Templates that require dynamic content
+
+**Limitations:**
+- Not suitable for large files (use git repo or external storage instead)
+- Binary files not supported
+- Changes require redeployment
+
+**Real-World Examples:**
+- `templates/compose/traccar.yaml` - XML configuration file
+- `templates/compose/supabase.yaml` - Multiple config files
+- `templates/compose/chaskiq.yaml` - Entrypoint script
+
+**Implementation:**
+- Parsed: `bootstrap/helpers/parsers.php` in `parseCompose()` function (handles `content` field extraction)
+- Storage: `app/Models/LocalFileVolume.php`
+- Validation: `tests/Unit/StripCoolifyCustomFieldsTest.php`
+
+#### `is_directory` / `isDirectory`
+
+**Type:** Boolean
+**Default:** `true` (if neither `content` nor explicit flag provided)
+**Purpose:** Indicate whether bind mount source should be created as directory or file
+
+**Example Usage:**
+```yaml
+services:
+ app:
+ volumes:
+ # Explicit file
+ - type: bind
+ source: ./config.json
+ target: /app/config.json
+ is_directory: false # Create as file
+
+ # Explicit directory
+ - type: bind
+ source: ./logs
+ target: /var/log/app
+ is_directory: true # Create as directory
+
+ # Auto-detected as file (has content)
+ - type: bind
+ source: ./script.sh
+ target: /entrypoint.sh
+ content: |
+ #!/bin/sh
+ echo "Hello"
+ # is_directory: false implied by content presence
+```
+
+**Behavior:**
+- If `is_directory: true` → Creates directory with `mkdir -p`
+- If `is_directory: false` → Creates empty file with `touch`
+- If `content` provided → Implies `is_directory: false`
+- If neither specified → Defaults to `true` (directory)
+
+**Naming Conventions:**
+- `is_directory` (snake_case) - **Preferred**, consistent with PHP/Laravel conventions
+- `isDirectory` (camelCase) - **Legacy support**, both work identically
+
+**Use Cases:**
+- Disambiguating files vs directories when no content provided
+- Ensuring correct bind mount type for Docker
+- Pre-creating mount points before container starts
+
+**Implementation:**
+- Parsed: `bootstrap/helpers/parsers.php` in `parseCompose()` function (handles `is_directory`/`isDirectory` field extraction)
+- Storage: `app/Models/LocalFileVolume.php` (`is_directory` column)
+- Validation: `tests/Unit/StripCoolifyCustomFieldsTest.php`
+
+### Custom Field Stripping
+
+**Function:** `stripCoolifyCustomFields()` in `bootstrap/helpers/docker.php`
+
+All custom fields are removed before the compose file is sent to Docker. This happens in two contexts:
+
+**1. Validation (User-Triggered)**
+```php
+// In validateComposeFile() - Edit Docker Compose modal
+$yaml_compose = Yaml::parse($compose);
+$yaml_compose = stripCoolifyCustomFields($yaml_compose); // Strip custom fields
+// Send to docker compose config for validation
+```
+
+**2. Deployment (Automatic)**
+```php
+// In Service::parse() - During deployment
+$docker_compose = parseCompose($docker_compose_raw);
+// Custom fields are processed and then stripped
+// Final compose sent to Docker has no custom fields
+```
+
+**What Gets Stripped:**
+- Service-level: `exclude_from_hc`
+- Volume-level: `content`, `isDirectory`, `is_directory`
+
+**What's Preserved:**
+- All standard Docker Compose fields
+- Environment variables
+- Standard volume definitions (after custom fields removed)
+
+### Important Notes
+
+#### Long vs Short Volume Syntax
+
+**✅ Long Syntax (Works with Custom Fields):**
+```yaml
+volumes:
+ - type: bind
+ source: ./data
+ target: /app/data
+ content: "Hello" # ✅ Custom fields work here
+```
+
+**❌ Short Syntax (Custom Fields Ignored):**
+```yaml
+volumes:
+ - "./data:/app/data" # ❌ Cannot add custom fields to strings
+```
+
+#### Docker Compose Compatibility
+
+Custom fields are **Coolify-specific** and won't work with standalone `docker compose` CLI:
+
+```bash
+# ❌ Won't work - Docker doesn't recognize custom fields
+docker compose -f compose.yaml up
+
+# ✅ Works - Use Coolify's deployment (strips custom fields first)
+# Deploy through Coolify UI or API
+```
+
+#### Editing Custom Fields
+
+When editing in "Edit Docker Compose" modal:
+- Custom fields are preserved in the editor
+- "Validate" button strips them temporarily for Docker validation
+- "Save" button preserves them in `docker_compose_raw`
+- They're processed again on next deployment
+
+### Template Examples
+
+See these templates for real-world usage:
+
+**Service Exclusions:**
+- `templates/compose/budibase.yaml` - Excludes watchtower from monitoring
+- `templates/compose/pgbackweb.yaml` - Excludes backup service
+- `templates/compose/elasticsearch-with-kibana.yaml` - Excludes elasticsearch
+
+**Inline Content:**
+- `templates/compose/traccar.yaml` - XML configuration (multiline)
+- `templates/compose/supabase.yaml` - Multiple config files
+- `templates/compose/searxng.yaml` - Settings file
+- `templates/compose/invoice-ninja.yaml` - Nginx config
+
+**Directory Flags:**
+- `templates/compose/paperless.yaml` - Explicit directory creation
+
+### Testing
+
+**Unit Tests:**
+- `tests/Unit/StripCoolifyCustomFieldsTest.php` - Custom field stripping logic
+- `tests/Unit/ExcludeFromHealthCheckTest.php` - Health check exclusion behavior
+- `tests/Unit/ContainerStatusAggregatorTest.php` - Status aggregation with exclusions
+
+**Test Coverage:**
+- ✅ All custom fields (exclude_from_hc, content, isDirectory, is_directory)
+- ✅ Multiline content (YAML `|` syntax)
+- ✅ Short vs long volume syntax
+- ✅ Field stripping without data loss
+- ✅ Standard Docker Compose field preservation
diff --git a/.ai/core/project-overview.md b/.ai/core/project-overview.md
new file mode 100644
index 0000000000..59fda48686
--- /dev/null
+++ b/.ai/core/project-overview.md
@@ -0,0 +1,156 @@
+# Coolify Project Overview
+
+## What is Coolify?
+
+Coolify is an **open-source & self-hostable alternative to Heroku / Netlify / Vercel**. It's a comprehensive deployment platform that helps you manage servers, applications, and databases on your own hardware with just an SSH connection.
+
+## Core Mission
+
+**"Imagine having the ease of a cloud but with your own servers. That is Coolify."**
+
+- **No vendor lock-in** - All configurations saved to your servers
+- **Self-hosted** - Complete control over your infrastructure
+- **SSH-only requirement** - Works with VPS, Bare Metal, Raspberry PIs, anything
+- **Docker-first** - Container-based deployment architecture
+
+## Key Features
+
+### 🚀 **Application Deployment**
+- Git-based deployments (GitHub, GitLab, Bitbucket, Gitea)
+- Docker & Docker Compose support
+- Preview deployments for pull requests
+- Zero-downtime deployments
+- Build cache optimization
+
+### 🖥️ **Server Management**
+- Multi-server orchestration
+- Real-time monitoring and logs
+- SSH key management
+- Proxy configuration (Traefik/Caddy)
+- Resource usage tracking
+
+### 🗄️ **Database Management**
+- PostgreSQL, MySQL, MariaDB, MongoDB
+- Redis, KeyDB, Dragonfly, ClickHouse
+- Automated backups with S3 integration
+- Database clustering support
+
+### 🔧 **Infrastructure as Code**
+- Docker Compose generation
+- Environment variable management
+- SSL certificate automation
+- Custom domain configuration
+
+### 👥 **Team Collaboration**
+- Multi-tenant team organization
+- Role-based access control
+- Project and environment isolation
+- Team-wide resource sharing
+
+### 📊 **Monitoring & Observability**
+- Real-time application logs
+- Server resource monitoring
+- Deployment status tracking
+- Webhook integrations
+- Notification systems (Email, Discord, Slack, Telegram)
+
+## Target Users
+
+### **DevOps Engineers**
+- Infrastructure automation
+- Multi-environment management
+- CI/CD pipeline integration
+
+### **Developers**
+- Easy application deployment
+- Development environment provisioning
+- Preview deployments for testing
+
+### **Small to Medium Businesses**
+- Cost-effective Heroku alternative
+- Self-hosted control and privacy
+- Scalable infrastructure management
+
+### **Agencies & Consultants**
+- Client project isolation
+- Multi-tenant management
+- White-label deployment solutions
+
+## Business Model
+
+### **Open Source (Free)**
+- Complete feature set
+- Self-hosted deployment
+- Community support
+- No feature restrictions
+
+### **Cloud Version (Paid)**
+- Managed Coolify instance
+- High availability
+- Premium support
+- Email notifications included
+- Same price as self-hosted server (~$4-5/month)
+
+## Architecture Philosophy
+
+### **Server-Side First**
+- Laravel backend with Livewire frontend
+- Minimal JavaScript footprint
+- Real-time updates via WebSockets
+- Progressive enhancement approach
+
+### **Docker-Native**
+- Container-first deployment strategy
+- Docker Compose orchestration
+- Image building and registry integration
+- Volume and network management
+
+### **Security-Focused**
+- SSH-based server communication
+- Environment variable encryption
+- Team-based access isolation
+- Audit logging and activity tracking
+
+## Project Structure
+
+```
+coolify/
+├── app/ # Laravel application core
+│ ├── Models/ # Domain models (Application, Server, Service)
+│ ├── Livewire/ # Frontend components
+│ ├── Actions/ # Business logic actions
+│ └── Jobs/ # Background job processing
+├── resources/ # Frontend assets and views
+├── database/ # Migrations and seeders
+├── docker/ # Docker configuration
+├── scripts/ # Installation and utility scripts
+└── tests/ # Test suites (Pest, Dusk)
+```
+
+## Key Differentiators
+
+### **vs. Heroku**
+- ✅ Self-hosted (no vendor lock-in)
+- ✅ Multi-server support
+- ✅ No usage-based pricing
+- ✅ Full infrastructure control
+
+### **vs. Vercel/Netlify**
+- ✅ Backend application support
+- ✅ Database management included
+- ✅ Multi-environment workflows
+- ✅ Custom server infrastructure
+
+### **vs. Docker Swarm/Kubernetes**
+- ✅ User-friendly web interface
+- ✅ Git-based deployment workflows
+- ✅ Integrated monitoring and logging
+- ✅ No complex YAML configuration
+
+## Development Principles
+
+- **Simplicity over complexity**
+- **Convention over configuration**
+- **Security by default**
+- **Developer experience focused**
+- **Community-driven development**
diff --git a/.ai/core/technology-stack.md b/.ai/core/technology-stack.md
new file mode 100644
index 0000000000..b12534db70
--- /dev/null
+++ b/.ai/core/technology-stack.md
@@ -0,0 +1,245 @@
+# Coolify Technology Stack
+
+Complete technology stack, dependencies, and infrastructure components.
+
+## Backend Framework
+
+### **Laravel 12.4.1** (PHP Framework)
+- **Purpose**: Core application framework
+- **Key Features**:
+ - Eloquent ORM for database interactions
+ - Artisan CLI for development tasks
+ - Queue system for background jobs
+ - Event-driven architecture
+
+### **PHP 8.4.7**
+- **Requirement**: `^8.4` in composer.json
+- **Features Used**:
+ - Typed properties and return types
+ - Attributes for validation and configuration
+ - Match expressions
+ - Constructor property promotion
+
+## Frontend Stack
+
+### **Livewire 3.5.20** (Primary Frontend Framework)
+- **Purpose**: Server-side rendering with reactive components
+- **Location**: `app/Livewire/`
+- **Key Components**:
+ - Dashboard - Main interface
+ - ActivityMonitor - Real-time monitoring
+ - MonacoEditor - Code editor
+
+### **Alpine.js** (Client-Side Interactivity)
+- **Purpose**: Lightweight JavaScript for DOM manipulation
+- **Integration**: Works seamlessly with Livewire components
+- **Usage**: Declarative directives in Blade templates
+
+### **Tailwind CSS 4.1.4** (Styling Framework)
+- **Configuration**: `postcss.config.cjs`
+- **Extensions**:
+ - `@tailwindcss/forms` - Form styling
+ - `@tailwindcss/typography` - Content typography
+ - `tailwind-scrollbar` - Custom scrollbars
+
+### **Vue.js 3.5.13** (Component Framework)
+- **Purpose**: Enhanced interactive components
+- **Integration**: Used alongside Livewire for complex UI
+- **Build Tool**: Vite with Vue plugin
+
+## Database & Caching
+
+### **PostgreSQL 15** (Primary Database)
+- **Purpose**: Main application data storage
+- **Features**: JSONB support, advanced indexing
+- **Models**: `app/Models/`
+
+### **Redis 7** (Caching & Real-time)
+- **Purpose**:
+ - Session storage
+ - Queue backend
+ - Real-time data caching
+ - WebSocket session management
+
+### **Supported Databases** (For User Applications)
+- **PostgreSQL**: StandalonePostgresql
+- **MySQL**: StandaloneMysql
+- **MariaDB**: StandaloneMariadb
+- **MongoDB**: StandaloneMongodb
+- **Redis**: StandaloneRedis
+- **KeyDB**: StandaloneKeydb
+- **Dragonfly**: StandaloneDragonfly
+- **ClickHouse**: StandaloneClickhouse
+
+## Authentication & Security
+
+### **Laravel Sanctum 4.0.8**
+- **Purpose**: API token authentication
+- **Usage**: Secure API access for external integrations
+
+### **Laravel Fortify 1.25.4**
+- **Purpose**: Authentication scaffolding
+- **Features**: Login, registration, password reset
+
+### **Laravel Socialite 5.18.0**
+- **Purpose**: OAuth provider integration
+- **Providers**:
+ - GitHub, GitLab, Google
+ - Microsoft Azure, Authentik, Discord, Clerk
+ - Custom OAuth implementations
+
+## Background Processing
+
+### **Laravel Horizon 5.30.3**
+- **Purpose**: Queue monitoring and management
+- **Features**: Real-time queue metrics, failed job handling
+
+### **Queue System**
+- **Backend**: Redis-based queues
+- **Jobs**: `app/Jobs/`
+- **Processing**: Background deployment and monitoring tasks
+
+## Development Tools
+
+### **Build Tools**
+- **Vite 6.2.6**: Modern build tool and dev server
+- **Laravel Vite Plugin**: Laravel integration
+- **PostCSS**: CSS processing pipeline
+
+### **Code Quality**
+- **Laravel Pint**: PHP code style fixer
+- **Rector**: PHP automated refactoring
+- **PHPStan**: Static analysis tool
+
+### **Testing Framework**
+- **Pest 3.8.0**: Modern PHP testing framework
+- **Laravel Dusk**: Browser automation testing
+- **PHPUnit**: Unit testing foundation
+
+## External Integrations
+
+### **Git Providers**
+- **GitHub**: Repository integration and webhooks
+- **GitLab**: Self-hosted and cloud GitLab support
+- **Bitbucket**: Atlassian integration
+- **Gitea**: Self-hosted Git service
+
+### **Cloud Storage**
+- **AWS S3**: league/flysystem-aws-s3-v3
+- **SFTP**: league/flysystem-sftp-v3
+- **Local Storage**: File system integration
+
+### **Notification Services**
+- **Email**: resend/resend-laravel
+- **Discord**: Custom webhook integration
+- **Slack**: Webhook notifications
+- **Telegram**: Bot API integration
+- **Pushover**: Push notifications
+
+### **Monitoring & Logging**
+- **Sentry**: sentry/sentry-laravel - Error tracking
+- **Laravel Ray**: spatie/laravel-ray - Debug tool
+- **Activity Log**: spatie/laravel-activitylog
+
+## DevOps & Infrastructure
+
+### **Docker & Containerization**
+- **Docker**: Container runtime
+- **Docker Compose**: Multi-container orchestration
+- **Docker Swarm**: Container clustering (optional)
+
+### **Web Servers & Proxies**
+- **Nginx**: Primary web server
+- **Traefik**: Reverse proxy and load balancer
+- **Caddy**: Alternative reverse proxy
+
+### **Process Management**
+- **S6 Overlay**: Process supervisor
+- **Supervisor**: Alternative process manager
+
+### **SSL/TLS**
+- **Let's Encrypt**: Automatic SSL certificates
+- **Custom Certificates**: Manual SSL management
+
+## Terminal & Code Editing
+
+### **XTerm.js 5.5.0**
+- **Purpose**: Web-based terminal emulator
+- **Features**: SSH session management, real-time command execution
+- **Addons**: Fit addon for responsive terminals
+
+### **Monaco Editor**
+- **Purpose**: Code editor component
+- **Features**: Syntax highlighting, auto-completion
+- **Integration**: Environment variable editing, configuration files
+
+## API & Documentation
+
+### **OpenAPI/Swagger**
+- **Documentation**: openapi.json (373KB)
+- **Generator**: zircote/swagger-php
+- **API Routes**: `routes/api.php`
+
+### **WebSocket Communication**
+- **Laravel Echo**: Real-time event broadcasting
+- **Pusher**: WebSocket service integration
+- **Soketi**: Self-hosted WebSocket server
+
+## Package Management
+
+### **PHP Dependencies** (composer.json)
+```json
+{
+ "require": {
+ "php": "^8.4",
+ "laravel/framework": "12.4.1",
+ "livewire/livewire": "^3.5.20",
+ "spatie/laravel-data": "^4.13.1",
+ "lorisleiva/laravel-actions": "^2.8.6"
+ }
+}
+```
+
+### **JavaScript Dependencies** (package.json)
+```json
+{
+ "devDependencies": {
+ "vite": "^6.2.6",
+ "tailwindcss": "^4.1.4",
+ "@vitejs/plugin-vue": "5.2.3"
+ },
+ "dependencies": {
+ "@xterm/xterm": "^5.5.0",
+ "ioredis": "5.6.0"
+ }
+}
+```
+
+## Configuration Files
+
+### **Build Configuration**
+- **vite.config.js**: Frontend build setup
+- **postcss.config.cjs**: CSS processing
+- **rector.php**: PHP refactoring rules
+- **pint.json**: Code style configuration
+
+### **Testing Configuration**
+- **phpunit.xml**: Unit test configuration
+- **phpunit.dusk.xml**: Browser test configuration
+- **tests/Pest.php**: Pest testing setup
+
+## Version Requirements
+
+### **Minimum Requirements**
+- **PHP**: 8.4+
+- **Node.js**: 18+ (for build tools)
+- **PostgreSQL**: 15+
+- **Redis**: 7+
+- **Docker**: 20.10+
+- **Docker Compose**: 2.0+
+
+### **Recommended Versions**
+- **Ubuntu**: 22.04 LTS or 24.04 LTS
+- **Memory**: 2GB+ RAM
+- **Storage**: 20GB+ available space
+- **Network**: Stable internet connection for deployments
diff --git a/.ai/development/development-workflow.md b/.ai/development/development-workflow.md
new file mode 100644
index 0000000000..4ee3766965
--- /dev/null
+++ b/.ai/development/development-workflow.md
@@ -0,0 +1,648 @@
+# Coolify Development Workflow
+
+## Development Environment Setup
+
+### Prerequisites
+- **PHP 8.4+** - Latest PHP version for modern features
+- **Node.js 18+** - For frontend asset compilation
+- **Docker & Docker Compose** - Container orchestration
+- **PostgreSQL 15** - Primary database
+- **Redis 7** - Caching and queues
+
+### Local Development Setup
+
+#### Using Docker (Recommended)
+```bash
+# Clone the repository
+git clone https://github.com/coollabsio/coolify.git
+cd coolify
+
+# Copy environment configuration
+cp .env.example .env
+
+# Start development environment
+docker-compose -f docker-compose.dev.yml up -d
+
+# Install PHP dependencies
+docker-compose exec app composer install
+
+# Install Node.js dependencies
+docker-compose exec app npm install
+
+# Generate application key
+docker-compose exec app php artisan key:generate
+
+# Run database migrations
+docker-compose exec app php artisan migrate
+
+# Seed development data
+docker-compose exec app php artisan db:seed
+```
+
+#### Native Development
+```bash
+# Install PHP dependencies
+composer install
+
+# Install Node.js dependencies
+npm install
+
+# Setup environment
+cp .env.example .env
+php artisan key:generate
+
+# Setup database
+createdb coolify_dev
+php artisan migrate
+php artisan db:seed
+
+# Start development servers
+php artisan serve &
+npm run dev &
+php artisan queue:work &
+```
+
+## Development Tools & Configuration
+
+### Code Quality Tools
+- **[Laravel Pint](mdc:pint.json)** - PHP code style fixer
+- **[Rector](mdc:rector.php)** - PHP automated refactoring (989B, 35 lines)
+- **PHPStan** - Static analysis for type safety
+- **ESLint** - JavaScript code quality
+
+### Development Configuration Files
+- **[docker-compose.dev.yml](mdc:docker-compose.dev.yml)** - Development Docker setup (3.4KB, 126 lines)
+- **[vite.config.js](mdc:vite.config.js)** - Frontend build configuration (1.0KB, 42 lines)
+- **[.editorconfig](mdc:.editorconfig)** - Code formatting standards (258B, 19 lines)
+
+### Git Configuration
+- **[.gitignore](mdc:.gitignore)** - Version control exclusions (522B, 40 lines)
+- **[.gitattributes](mdc:.gitattributes)** - Git file handling (185B, 11 lines)
+
+## Development Workflow Process
+
+### 1. Feature Development
+```bash
+# Create feature branch
+git checkout -b feature/new-deployment-strategy
+
+# Make changes following coding standards
+# Run code quality checks
+./vendor/bin/pint
+./vendor/bin/rector process --dry-run
+./vendor/bin/phpstan analyse
+
+# Run tests
+./vendor/bin/pest
+./vendor/bin/pest --coverage
+
+# Commit changes
+git add .
+git commit -m "feat: implement blue-green deployment strategy"
+```
+
+### 2. Code Review Process
+```bash
+# Push feature branch
+git push origin feature/new-deployment-strategy
+
+# Create pull request with:
+# - Clear description of changes
+# - Screenshots for UI changes
+# - Test coverage information
+# - Breaking change documentation
+```
+
+### 3. Testing Requirements
+- **Unit tests** for new models and services
+- **Feature tests** for API endpoints
+- **Browser tests** for UI changes
+- **Integration tests** for deployment workflows
+
+## Coding Standards & Conventions
+
+### PHP Coding Standards
+```php
+// Follow PSR-12 coding standards
+class ApplicationDeploymentService
+{
+ public function __construct(
+ private readonly DockerService $dockerService,
+ private readonly ConfigurationGenerator $configGenerator
+ ) {}
+
+ public function deploy(Application $application): ApplicationDeploymentQueue
+ {
+ return DB::transaction(function () use ($application) {
+ $deployment = $application->deployments()->create([
+ 'status' => 'queued',
+ 'commit_sha' => $application->getLatestCommitSha(),
+ ]);
+
+ DeployApplicationJob::dispatch($deployment);
+
+ return $deployment;
+ });
+ }
+}
+```
+
+### Laravel Best Practices
+```php
+// Use Laravel conventions
+class Application extends Model
+{
+ // Mass assignment protection
+ protected $fillable = [
+ 'name', 'git_repository', 'git_branch', 'fqdn'
+ ];
+
+ // Type casting
+ protected $casts = [
+ 'environment_variables' => 'array',
+ 'build_pack' => BuildPack::class,
+ 'created_at' => 'datetime',
+ ];
+
+ // Relationships
+ public function server(): BelongsTo
+ {
+ return $this->belongsTo(Server::class);
+ }
+
+ public function deployments(): HasMany
+ {
+ return $this->hasMany(ApplicationDeploymentQueue::class);
+ }
+}
+```
+
+### Frontend Standards
+```javascript
+// Alpine.js component structure
+document.addEventListener('alpine:init', () => {
+ Alpine.data('deploymentMonitor', () => ({
+ status: 'idle',
+ logs: [],
+
+ init() {
+ this.connectWebSocket();
+ },
+
+ connectWebSocket() {
+ Echo.private(`application.${this.applicationId}`)
+ .listen('DeploymentStarted', (e) => {
+ this.status = 'deploying';
+ })
+ .listen('DeploymentCompleted', (e) => {
+ this.status = 'completed';
+ });
+ }
+ }));
+});
+```
+
+### CSS/Tailwind Standards
+```html
+
+
+
+
+ Application Status
+
+
+
+
+
+
+```
+
+## Database Development
+
+### Migration Best Practices
+```php
+// Create descriptive migration files
+class CreateApplicationDeploymentQueuesTable extends Migration
+{
+ public function up(): void
+ {
+ Schema::create('application_deployment_queues', function (Blueprint $table) {
+ $table->id();
+ $table->foreignId('application_id')->constrained()->cascadeOnDelete();
+ $table->string('status')->default('queued');
+ $table->string('commit_sha')->nullable();
+ $table->text('build_logs')->nullable();
+ $table->text('deployment_logs')->nullable();
+ $table->timestamp('started_at')->nullable();
+ $table->timestamp('finished_at')->nullable();
+ $table->timestamps();
+
+ $table->index(['application_id', 'status']);
+ $table->index('created_at');
+ });
+ }
+
+ public function down(): void
+ {
+ Schema::dropIfExists('application_deployment_queues');
+ }
+}
+```
+
+### Model Factory Development
+```php
+// Create comprehensive factories for testing
+class ApplicationFactory extends Factory
+{
+ protected $model = Application::class;
+
+ public function definition(): array
+ {
+ return [
+ 'name' => $this->faker->words(2, true),
+ 'fqdn' => $this->faker->domainName,
+ 'git_repository' => 'https://github.com/' . $this->faker->userName . '/' . $this->faker->word . '.git',
+ 'git_branch' => 'main',
+ 'build_pack' => BuildPack::NIXPACKS,
+ 'server_id' => Server::factory(),
+ 'environment_id' => Environment::factory(),
+ ];
+ }
+
+ public function withCustomDomain(): static
+ {
+ return $this->state(fn (array $attributes) => [
+ 'fqdn' => $this->faker->domainName,
+ ]);
+ }
+}
+```
+
+## API Development
+
+### Controller Standards
+```php
+class ApplicationController extends Controller
+{
+ public function __construct()
+ {
+ $this->middleware('auth:sanctum');
+ $this->middleware('team.access');
+ }
+
+ public function index(Request $request): AnonymousResourceCollection
+ {
+ $applications = $request->user()
+ ->currentTeam
+ ->applications()
+ ->with(['server', 'environment', 'latestDeployment'])
+ ->paginate();
+
+ return ApplicationResource::collection($applications);
+ }
+
+ public function store(StoreApplicationRequest $request): ApplicationResource
+ {
+ $application = $request->user()
+ ->currentTeam
+ ->applications()
+ ->create($request->validated());
+
+ return new ApplicationResource($application);
+ }
+
+ public function deploy(Application $application): JsonResponse
+ {
+ $this->authorize('deploy', $application);
+
+ $deployment = app(ApplicationDeploymentService::class)
+ ->deploy($application);
+
+ return response()->json([
+ 'message' => 'Deployment started successfully',
+ 'deployment_id' => $deployment->id,
+ ]);
+ }
+}
+```
+
+### API Resource Development
+```php
+class ApplicationResource extends JsonResource
+{
+ public function toArray($request): array
+ {
+ return [
+ 'id' => $this->id,
+ 'name' => $this->name,
+ 'fqdn' => $this->fqdn,
+ 'status' => $this->status,
+ 'git_repository' => $this->git_repository,
+ 'git_branch' => $this->git_branch,
+ 'build_pack' => $this->build_pack,
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at,
+
+ // Conditional relationships
+ 'server' => new ServerResource($this->whenLoaded('server')),
+ 'environment' => new EnvironmentResource($this->whenLoaded('environment')),
+ 'latest_deployment' => new DeploymentResource($this->whenLoaded('latestDeployment')),
+
+ // Computed attributes
+ 'deployment_url' => $this->getDeploymentUrl(),
+ 'can_deploy' => $this->canDeploy(),
+ ];
+ }
+}
+```
+
+## Livewire Component Development
+
+### Component Structure
+```php
+class ApplicationShow extends Component
+{
+ public Application $application;
+ public bool $showLogs = false;
+
+ protected $listeners = [
+ 'deployment.started' => 'refreshDeploymentStatus',
+ 'deployment.completed' => 'refreshDeploymentStatus',
+ ];
+
+ public function mount(Application $application): void
+ {
+ $this->authorize('view', $application);
+ $this->application = $application;
+ }
+
+ public function deploy(): void
+ {
+ $this->authorize('deploy', $this->application);
+
+ try {
+ app(ApplicationDeploymentService::class)->deploy($this->application);
+
+ $this->dispatch('deployment.started', [
+ 'application_id' => $this->application->id
+ ]);
+
+ session()->flash('success', 'Deployment started successfully');
+ } catch (Exception $e) {
+ session()->flash('error', 'Failed to start deployment: ' . $e->getMessage());
+ }
+ }
+
+ public function refreshDeploymentStatus(): void
+ {
+ $this->application->refresh();
+ }
+
+ public function render(): View
+ {
+ return view('livewire.application.show', [
+ 'deployments' => $this->application
+ ->deployments()
+ ->latest()
+ ->limit(10)
+ ->get()
+ ]);
+ }
+}
+```
+
+## Queue Job Development
+
+### Job Structure
+```php
+class DeployApplicationJob implements ShouldQueue
+{
+ use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+ public int $tries = 3;
+ public int $maxExceptions = 1;
+
+ public function __construct(
+ public ApplicationDeploymentQueue $deployment
+ ) {}
+
+ public function handle(
+ DockerService $dockerService,
+ ConfigurationGenerator $configGenerator
+ ): void {
+ $this->deployment->update(['status' => 'running', 'started_at' => now()]);
+
+ try {
+ // Generate configuration
+ $config = $configGenerator->generateDockerCompose($this->deployment->application);
+
+ // Build and deploy
+ $imageTag = $dockerService->buildImage($this->deployment->application);
+ $dockerService->deployContainer($this->deployment->application, $imageTag);
+
+ $this->deployment->update([
+ 'status' => 'success',
+ 'finished_at' => now()
+ ]);
+
+ // Broadcast success
+ broadcast(new DeploymentCompleted($this->deployment));
+
+ } catch (Exception $e) {
+ $this->deployment->update([
+ 'status' => 'failed',
+ 'error_message' => $e->getMessage(),
+ 'finished_at' => now()
+ ]);
+
+ broadcast(new DeploymentFailed($this->deployment));
+
+ throw $e;
+ }
+ }
+
+ public function backoff(): array
+ {
+ return [1, 5, 10];
+ }
+
+ public function failed(Throwable $exception): void
+ {
+ $this->deployment->update([
+ 'status' => 'failed',
+ 'error_message' => $exception->getMessage(),
+ 'finished_at' => now()
+ ]);
+ }
+}
+```
+
+## Testing Development
+
+### Test Structure
+```php
+// Feature test example
+test('user can deploy application via API', function () {
+ $user = User::factory()->create();
+ $application = Application::factory()->create([
+ 'team_id' => $user->currentTeam->id
+ ]);
+
+ // Mock external services
+ $this->mock(DockerService::class, function ($mock) {
+ $mock->shouldReceive('buildImage')->andReturn('app:latest');
+ $mock->shouldReceive('deployContainer')->andReturn(true);
+ });
+
+ $response = $this->actingAs($user)
+ ->postJson("/api/v1/applications/{$application->id}/deploy");
+
+ $response->assertStatus(200)
+ ->assertJson([
+ 'message' => 'Deployment started successfully'
+ ]);
+
+ expect($application->deployments()->count())->toBe(1);
+ expect($application->deployments()->first()->status)->toBe('queued');
+});
+```
+
+## Documentation Standards
+
+### Code Documentation
+```php
+/**
+ * Deploy an application to the specified server.
+ *
+ * This method creates a new deployment queue entry and dispatches
+ * a background job to handle the actual deployment process.
+ *
+ * @param Application $application The application to deploy
+ * @param array $options Additional deployment options
+ * @return ApplicationDeploymentQueue The created deployment queue entry
+ *
+ * @throws DeploymentException When deployment cannot be started
+ * @throws ServerConnectionException When server is unreachable
+ */
+public function deploy(Application $application, array $options = []): ApplicationDeploymentQueue
+{
+ // Implementation
+}
+```
+
+### API Documentation
+```php
+/**
+ * @OA\Post(
+ * path="/api/v1/applications/{application}/deploy",
+ * summary="Deploy an application",
+ * description="Triggers a new deployment for the specified application",
+ * operationId="deployApplication",
+ * tags={"Applications"},
+ * security={{"bearerAuth":{}}},
+ * @OA\Parameter(
+ * name="application",
+ * in="path",
+ * required=true,
+ * @OA\Schema(type="integer"),
+ * description="Application ID"
+ * ),
+ * @OA\Response(
+ * response=200,
+ * description="Deployment started successfully",
+ * @OA\JsonContent(
+ * @OA\Property(property="message", type="string"),
+ * @OA\Property(property="deployment_id", type="integer")
+ * )
+ * )
+ * )
+ */
+```
+
+## Performance Optimization
+
+### Database Optimization
+```php
+// Use eager loading to prevent N+1 queries
+$applications = Application::with([
+ 'server:id,name,ip',
+ 'environment:id,name',
+ 'latestDeployment:id,application_id,status,created_at'
+])->get();
+
+// Use database transactions for consistency
+DB::transaction(function () use ($application) {
+ $deployment = $application->deployments()->create(['status' => 'queued']);
+ $application->update(['last_deployment_at' => now()]);
+ DeployApplicationJob::dispatch($deployment);
+});
+```
+
+### Caching Strategies
+```php
+// Cache expensive operations
+public function getServerMetrics(Server $server): array
+{
+ return Cache::remember(
+ "server.{$server->id}.metrics",
+ now()->addMinutes(5),
+ fn () => $this->fetchServerMetrics($server)
+ );
+}
+```
+
+## Deployment & Release Process
+
+### Version Management
+- **[versions.json](mdc:versions.json)** - Version tracking (355B, 19 lines)
+- **[CHANGELOG.md](mdc:CHANGELOG.md)** - Release notes (187KB, 7411 lines)
+- **[cliff.toml](mdc:cliff.toml)** - Changelog generation (3.2KB, 85 lines)
+
+### Release Workflow
+```bash
+# Create release branch
+git checkout -b release/v4.1.0
+
+# Update version numbers
+# Update CHANGELOG.md
+# Run full test suite
+./vendor/bin/pest
+npm run test
+
+# Create release commit
+git commit -m "chore: release v4.1.0"
+
+# Create and push tag
+git tag v4.1.0
+git push origin v4.1.0
+
+# Merge to main
+git checkout main
+git merge release/v4.1.0
+```
+
+## Contributing Guidelines
+
+### Pull Request Process
+1. **Fork** the repository
+2. **Create** feature branch from `main`
+3. **Implement** changes with tests
+4. **Run** code quality checks
+5. **Submit** pull request with clear description
+6. **Address** review feedback
+7. **Merge** after approval
+
+### Code Review Checklist
+- [ ] Code follows project standards
+- [ ] Tests cover new functionality
+- [ ] Documentation is updated
+- [ ] No breaking changes without migration
+- [ ] Performance impact considered
+- [ ] Security implications reviewed
+
+### Issue Reporting
+- Use issue templates
+- Provide reproduction steps
+- Include environment details
+- Add relevant logs/screenshots
+- Label appropriately
diff --git a/.ai/development/laravel-boost.md b/.ai/development/laravel-boost.md
new file mode 100644
index 0000000000..7f5922d944
--- /dev/null
+++ b/.ai/development/laravel-boost.md
@@ -0,0 +1,402 @@
+
+=== foundation rules ===
+
+# Laravel Boost Guidelines
+
+The Laravel Boost guidelines are specifically curated by Laravel maintainers for this application. These guidelines should be followed closely to enhance the user's satisfaction building Laravel applications.
+
+## Foundational Context
+This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
+
+- php - 8.4.7
+- laravel/fortify (FORTIFY) - v1
+- laravel/framework (LARAVEL) - v12
+- laravel/horizon (HORIZON) - v5
+- laravel/prompts (PROMPTS) - v0
+- laravel/sanctum (SANCTUM) - v4
+- laravel/socialite (SOCIALITE) - v5
+- livewire/livewire (LIVEWIRE) - v3
+- laravel/dusk (DUSK) - v8
+- laravel/pint (PINT) - v1
+- laravel/telescope (TELESCOPE) - v5
+- pestphp/pest (PEST) - v3
+- phpunit/phpunit (PHPUNIT) - v11
+- rector/rector (RECTOR) - v2
+- laravel-echo (ECHO) - v2
+- tailwindcss (TAILWINDCSS) - v4
+- vue (VUE) - v3
+
+
+## Conventions
+- You must follow all existing code conventions used in this application. When creating or editing a file, check sibling files for the correct structure, approach, naming.
+- Use descriptive names for variables and methods. For example, `isRegisteredForDiscounts`, not `discount()`.
+- Check for existing components to reuse before writing a new one.
+
+## Verification Scripts
+- Do not create verification scripts or tinker when tests cover that functionality and prove it works. Unit and feature tests are more important.
+
+## Application Structure & Architecture
+- Stick to existing directory structure - don't create new base folders without approval.
+- Do not change the application's dependencies without approval.
+
+## Frontend Bundling
+- If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `npm run build`, `npm run dev`, or `composer run dev`. Ask them.
+
+## Replies
+- Be concise in your explanations - focus on what's important rather than explaining obvious details.
+
+## Documentation Files
+- You must only create documentation files if explicitly requested by the user.
+
+
+=== boost rules ===
+
+## Laravel Boost
+- Laravel Boost is an MCP server that comes with powerful tools designed specifically for this application. Use them.
+
+## Artisan
+- Use the `list-artisan-commands` tool when you need to call an Artisan command to double check the available parameters.
+
+## URLs
+- Whenever you share a project URL with the user you should use the `get-absolute-url` tool to ensure you're using the correct scheme, domain / IP, and port.
+
+## Tinker / Debugging
+- You should use the `tinker` tool when you need to execute PHP to debug code or query Eloquent models directly.
+- Use the `database-query` tool when you only need to read from the database.
+
+## Reading Browser Logs With the `browser-logs` Tool
+- You can read browser logs, errors, and exceptions using the `browser-logs` tool from Boost.
+- Only recent browser logs will be useful - ignore old logs.
+
+## Searching Documentation (Critically Important)
+- Boost comes with a powerful `search-docs` tool you should use before any other approaches. This tool automatically passes a list of installed packages and their versions to the remote Boost API, so it returns only version-specific documentation specific for the user's circumstance. You should pass an array of packages to filter on if you know you need docs for particular packages.
+- The 'search-docs' tool is perfect for all Laravel related packages, including Laravel, Inertia, Livewire, Filament, Tailwind, Pest, Nova, Nightwatch, etc.
+- You must use this tool to search for Laravel-ecosystem documentation before falling back to other approaches.
+- Search the documentation before making code changes to ensure we are taking the correct approach.
+- Use multiple, broad, simple, topic based queries to start. For example: `['rate limiting', 'routing rate limiting', 'routing']`.
+- Do not add package names to queries - package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`.
+
+### Available Search Syntax
+- You can and should pass multiple queries at once. The most relevant results will be returned first.
+
+1. Simple Word Searches with auto-stemming - query=authentication - finds 'authenticate' and 'auth'
+2. Multiple Words (AND Logic) - query=rate limit - finds knowledge containing both "rate" AND "limit"
+3. Quoted Phrases (Exact Position) - query="infinite scroll" - Words must be adjacent and in that order
+4. Mixed Queries - query=middleware "rate limit" - "middleware" AND exact phrase "rate limit"
+5. Multiple Queries - queries=["authentication", "middleware"] - ANY of these terms
+
+
+=== php rules ===
+
+## PHP
+
+- Always use curly braces for control structures, even if it has one line.
+
+### Constructors
+- Use PHP 8 constructor property promotion in `__construct()`.
+ - public function __construct(public GitHub $github) { }
+- Do not allow empty `__construct()` methods with zero parameters.
+
+### Type Declarations
+- Always use explicit return type declarations for methods and functions.
+- Use appropriate PHP type hints for method parameters.
+
+
+protected function isAccessible(User $user, ?string $path = null): bool
+{
+ ...
+}
+
+
+## Comments
+- Prefer PHPDoc blocks over comments. Never use comments within the code itself unless there is something _very_ complex going on.
+
+## PHPDoc Blocks
+- Add useful array shape type definitions for arrays when appropriate.
+
+## Enums
+- Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`.
+
+
+=== laravel/core rules ===
+
+## Do Things the Laravel Way
+
+- Use `php artisan make:` commands to create new files (i.e. migrations, controllers, models, etc.). You can list available Artisan commands using the `list-artisan-commands` tool.
+- If you're creating a generic PHP class, use `artisan make:class`.
+- Pass `--no-interaction` to all Artisan commands to ensure they work without user input. You should also pass the correct `--options` to ensure correct behavior.
+
+### Database
+- Always use proper Eloquent relationship methods with return type hints. Prefer relationship methods over raw queries or manual joins.
+- Use Eloquent models and relationships before suggesting raw database queries
+- Avoid `DB::`; prefer `Model::query()`. Generate code that leverages Laravel's ORM capabilities rather than bypassing them.
+- Generate code that prevents N+1 query problems by using eager loading.
+- Use Laravel's query builder for very complex database operations.
+
+### Model Creation
+- When creating new models, create useful factories and seeders for them too. Ask the user if they need any other things, using `list-artisan-commands` to check the available options to `php artisan make:model`.
+
+### APIs & Eloquent Resources
+- For APIs, default to using Eloquent API Resources and API versioning unless existing API routes do not, then you should follow existing application convention.
+
+### Controllers & Validation
+- Always create Form Request classes for validation rather than inline validation in controllers. Include both validation rules and custom error messages.
+- Check sibling Form Requests to see if the application uses array or string based validation rules.
+
+### Queues
+- Use queued jobs for time-consuming operations with the `ShouldQueue` interface.
+
+### Authentication & Authorization
+- Use Laravel's built-in authentication and authorization features (gates, policies, Sanctum, etc.).
+
+### URL Generation
+- When generating links to other pages, prefer named routes and the `route()` function.
+
+### Configuration
+- Use environment variables only in configuration files - never use the `env()` function directly outside of config files. Always use `config('app.name')`, not `env('APP_NAME')`.
+
+### Testing
+- When creating models for tests, use the factories for the models. Check if the factory has custom states that can be used before manually setting up the model.
+- Faker: Use methods such as `$this->faker->word()` or `fake()->randomDigit()`. Follow existing conventions whether to use `$this->faker` or `fake()`.
+- When creating tests, make use of `php artisan make:test [options] ` to create a feature test, and pass `--unit` to create a unit test. Most tests should be feature tests.
+
+### Vite Error
+- If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `npm run build` or ask the user to run `npm run dev` or `composer run dev`.
+
+
+=== laravel/v12 rules ===
+
+## Laravel 12
+
+- Use the `search-docs` tool to get version specific documentation.
+- This project upgraded from Laravel 10 without migrating to the new streamlined Laravel file structure.
+- This is **perfectly fine** and recommended by Laravel. Follow the existing structure from Laravel 10. We do not to need migrate to the new Laravel structure unless the user explicitly requests that.
+
+### Laravel 10 Structure
+- Middleware typically lives in `app/Http/Middleware/` and service providers in `app/Providers/`.
+- There is no `bootstrap/app.php` application configuration in a Laravel 10 structure:
+ - Middleware registration happens in `app/Http/Kernel.php`
+ - Exception handling is in `app/Exceptions/Handler.php`
+ - Console commands and schedule register in `app/Console/Kernel.php`
+ - Rate limits likely exist in `RouteServiceProvider` or `app/Http/Kernel.php`
+
+### Database
+- When modifying a column, the migration must include all of the attributes that were previously defined on the column. Otherwise, they will be dropped and lost.
+- Laravel 12 allows limiting eagerly loaded records natively, without external packages: `$query->latest()->limit(10);`.
+
+### Models
+- Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models.
+
+
+=== livewire/core rules ===
+
+## Livewire Core
+- Use the `search-docs` tool to find exact version specific documentation for how to write Livewire & Livewire tests.
+- Use the `php artisan make:livewire [Posts\\CreatePost]` artisan command to create new components
+- State should live on the server, with the UI reflecting it.
+- All Livewire requests hit the Laravel backend, they're like regular HTTP requests. Always validate form data, and run authorization checks in Livewire actions.
+
+## Livewire Best Practices
+- Livewire components require a single root element.
+- Use `wire:loading` and `wire:dirty` for delightful loading states.
+- Add `wire:key` in loops:
+
+ ```blade
+ @foreach ($items as $item)
+
+ {{ $item->name }}
+
+ @endforeach
+ ```
+
+- Prefer lifecycle hooks like `mount()`, `updatedFoo()`) for initialization and reactive side effects:
+
+
+ public function mount(User $user) { $this->user = $user; }
+ public function updatedSearch() { $this->resetPage(); }
+
+
+
+## Testing Livewire
+
+
+ Livewire::test(Counter::class)
+ ->assertSet('count', 0)
+ ->call('increment')
+ ->assertSet('count', 1)
+ ->assertSee(1)
+ ->assertStatus(200);
+
+
+
+
+ $this->get('/posts/create')
+ ->assertSeeLivewire(CreatePost::class);
+
+
+
+=== livewire/v3 rules ===
+
+## Livewire 3
+
+### Key Changes From Livewire 2
+- These things changed in Livewire 2, but may not have been updated in this application. Verify this application's setup to ensure you conform with application conventions.
+ - Use `wire:model.live` for real-time updates, `wire:model` is now deferred by default.
+ - Components now use the `App\Livewire` namespace (not `App\Http\Livewire`).
+ - Use `$this->dispatch()` to dispatch events (not `emit` or `dispatchBrowserEvent`).
+ - Use the `components.layouts.app` view as the typical layout path (not `layouts.app`).
+
+### New Directives
+- `wire:show`, `wire:transition`, `wire:cloak`, `wire:offline`, `wire:target` are available for use. Use the documentation to find usage examples.
+
+### Alpine
+- Alpine is now included with Livewire, don't manually include Alpine.js.
+- Plugins included with Alpine: persist, intersect, collapse, and focus.
+
+### Lifecycle Hooks
+- You can listen for `livewire:init` to hook into Livewire initialization, and `fail.status === 419` for the page expiring:
+
+
+document.addEventListener('livewire:init', function () {
+ Livewire.hook('request', ({ fail }) => {
+ if (fail && fail.status === 419) {
+ alert('Your session expired');
+ }
+ });
+
+ Livewire.hook('message.failed', (message, component) => {
+ console.error(message);
+ });
+});
+
+
+
+=== pint/core rules ===
+
+## Laravel Pint Code Formatter
+
+- You must run `vendor/bin/pint --dirty` before finalizing changes to ensure your code matches the project's expected style.
+- Do not run `vendor/bin/pint --test`, simply run `vendor/bin/pint` to fix any formatting issues.
+
+
+=== pest/core rules ===
+
+## Pest
+
+### Testing
+- If you need to verify a feature is working, write or update a Unit / Feature test.
+
+### Pest Tests
+- All tests must be written using Pest. Use `php artisan make:test --pest `.
+- You must not remove any tests or test files from the tests directory without approval. These are not temporary or helper files - these are core to the application.
+- Tests should test all of the happy paths, failure paths, and weird paths.
+- Tests live in the `tests/Feature` and `tests/Unit` directories.
+- Pest tests look and behave like this:
+
+it('is true', function () {
+ expect(true)->toBeTrue();
+});
+
+
+### Running Tests
+- Run the minimal number of tests using an appropriate filter before finalizing code edits.
+- To run all tests: `php artisan test`.
+- To run all tests in a file: `php artisan test tests/Feature/ExampleTest.php`.
+- To filter on a particular test name: `php artisan test --filter=testName` (recommended after making a change to a related file).
+- When the tests relating to your changes are passing, ask the user if they would like to run the entire test suite to ensure everything is still passing.
+
+### Pest Assertions
+- When asserting status codes on a response, use the specific method like `assertForbidden` and `assertNotFound` instead of using `assertStatus(403)` or similar, e.g.:
+
+it('returns all', function () {
+ $response = $this->postJson('/api/docs', []);
+
+ $response->assertSuccessful();
+});
+
+
+### Mocking
+- Mocking can be very helpful when appropriate.
+- When mocking, you can use the `Pest\Laravel\mock` Pest function, but always import it via `use function Pest\Laravel\mock;` before using it. Alternatively, you can use `$this->mock()` if existing tests do.
+- You can also create partial mocks using the same import or self method.
+
+### Datasets
+- Use datasets in Pest to simplify tests which have a lot of duplicated data. This is often the case when testing validation rules, so consider going with this solution when writing tests for validation rules.
+
+
+it('has emails', function (string $email) {
+ expect($email)->not->toBeEmpty();
+})->with([
+ 'james' => 'james@laravel.com',
+ 'taylor' => 'taylor@laravel.com',
+]);
+
+
+
+=== tailwindcss/core rules ===
+
+## Tailwind Core
+
+- Use Tailwind CSS classes to style HTML, check and use existing tailwind conventions within the project before writing your own.
+- Offer to extract repeated patterns into components that match the project's conventions (i.e. Blade, JSX, Vue, etc..)
+- Think through class placement, order, priority, and defaults - remove redundant classes, add classes to parent or child carefully to limit repetition, group elements logically
+- You can use the `search-docs` tool to get exact examples from the official documentation when needed.
+
+### Spacing
+- When listing items, use gap utilities for spacing, don't use margins.
+
+
+
+
Superior
+
Michigan
+
Erie
+
+
+
+
+### Dark Mode
+- If existing pages and components support dark mode, new pages and components must support dark mode in a similar way, typically using `dark:`.
+
+
+=== tailwindcss/v4 rules ===
+
+## Tailwind 4
+
+- Always use Tailwind CSS v4 - do not use the deprecated utilities.
+- `corePlugins` is not supported in Tailwind v4.
+- In Tailwind v4, you import Tailwind using a regular CSS `@import` statement, not using the `@tailwind` directives used in v3:
+
+
+
+
+### Replaced Utilities
+- Tailwind v4 removed deprecated utilities. Do not use the deprecated option - use the replacement.
+- Opacity values are still numeric.
+
+| Deprecated | Replacement |
+|------------+--------------|
+| bg-opacity-* | bg-black/* |
+| text-opacity-* | text-black/* |
+| border-opacity-* | border-black/* |
+| divide-opacity-* | divide-black/* |
+| ring-opacity-* | ring-black/* |
+| placeholder-opacity-* | placeholder-black/* |
+| flex-shrink-* | shrink-* |
+| flex-grow-* | grow-* |
+| overflow-ellipsis | text-ellipsis |
+| decoration-slice | box-decoration-slice |
+| decoration-clone | box-decoration-clone |
+
+
+=== tests rules ===
+
+## Test Enforcement
+
+- Every change must be programmatically tested. Write a new test or update an existing test, then run the affected tests to make sure they pass.
+- Run the minimum number of tests needed to ensure code quality and speed. Use `php artisan test` with a specific filename or filter.
+
\ No newline at end of file
diff --git a/.ai/development/testing-patterns.md b/.ai/development/testing-patterns.md
new file mode 100644
index 0000000000..875de8b3be
--- /dev/null
+++ b/.ai/development/testing-patterns.md
@@ -0,0 +1,648 @@
+# Coolify Testing Architecture & Patterns
+
+> **Cross-Reference**: These detailed testing patterns align with the testing guidelines in **[CLAUDE.md](mdc:CLAUDE.md)**. Both documents share the same core principles about Docker execution and mocking preferences.
+
+## Testing Philosophy
+
+Coolify employs **comprehensive testing strategies** using modern PHP testing frameworks to ensure reliability of deployment operations, infrastructure management, and user interactions.
+
+### Test Execution Rules
+
+**CRITICAL**: Tests are categorized by database dependency:
+
+#### Unit Tests (`tests/Unit/`)
+- **MUST NOT** use database connections
+- **MUST** use mocking for models and external dependencies
+- **CAN** run outside Docker: `./vendor/bin/pest tests/Unit`
+- Purpose: Test isolated logic, helper functions, and business rules
+
+#### Feature Tests (`tests/Feature/`)
+- **MAY** use database connections (factories, migrations, models)
+- **MUST** run inside Docker container: `docker exec coolify php artisan test`
+- **MUST** use `RefreshDatabase` trait if touching database
+- Purpose: Test API endpoints, workflows, and integration scenarios
+
+**Rule of thumb**: If your test needs `Server::factory()->create()` or any database operation, it's a Feature test and MUST run in Docker.
+
+### Prefer Mocking Over Database
+
+When writing tests, always prefer mocking over real database operations:
+
+```php
+// ❌ BAD: Unit test using database
+it('extracts custom commands', function () {
+ $server = Server::factory()->create(['ip' => '1.2.3.4']);
+ $commands = extract_custom_proxy_commands($server, $yaml);
+ expect($commands)->toBeArray();
+});
+
+// ✅ GOOD: Unit test using mocking
+it('extracts custom commands', function () {
+ $server = Mockery::mock('App\Models\Server');
+ $server->shouldReceive('proxyType')->andReturn('traefik');
+ $commands = extract_custom_proxy_commands($server, $yaml);
+ expect($commands)->toBeArray();
+});
+```
+
+**Design principles for testable code:**
+- Use dependency injection instead of global state
+- Create interfaces for external dependencies (SSH, Docker, etc.)
+- Separate business logic from data persistence
+- Make functions accept interfaces instead of concrete models when possible
+
+## Testing Framework Stack
+
+### Core Testing Tools
+- **Pest PHP 3.8+** - Primary testing framework with expressive syntax
+- **Laravel Dusk** - Browser automation and end-to-end testing
+- **PHPUnit** - Underlying unit testing framework
+- **Mockery** - Mocking and stubbing for isolated tests
+
+### Testing Configuration
+- **[tests/Pest.php](mdc:tests/Pest.php)** - Pest configuration and global setup (1.5KB, 45 lines)
+- **[tests/TestCase.php](mdc:tests/TestCase.php)** - Base test case class (163B, 11 lines)
+- **[tests/CreatesApplication.php](mdc:tests/CreatesApplication.php)** - Application factory trait (375B, 22 lines)
+- **[tests/DuskTestCase.php](mdc:tests/DuskTestCase.php)** - Browser testing setup (1.4KB, 58 lines)
+
+## Test Directory Structure
+
+### Test Organization
+- **[tests/Feature/](mdc:tests/Feature)** - Feature and integration tests
+- **[tests/Unit/](mdc:tests/Unit)** - Unit tests for isolated components
+- **[tests/Browser/](mdc:tests/Browser)** - Laravel Dusk browser tests
+- **[tests/Traits/](mdc:tests/Traits)** - Shared testing utilities
+
+## Unit Testing Patterns
+
+### Model Testing
+```php
+// Testing Eloquent models
+test('application model has correct relationships', function () {
+ $application = Application::factory()->create();
+
+ expect($application->server)->toBeInstanceOf(Server::class);
+ expect($application->environment)->toBeInstanceOf(Environment::class);
+ expect($application->deployments)->toBeInstanceOf(Collection::class);
+});
+
+test('application can generate deployment configuration', function () {
+ $application = Application::factory()->create([
+ 'name' => 'test-app',
+ 'git_repository' => 'https://github.com/user/repo.git'
+ ]);
+
+ $config = $application->generateDockerCompose();
+
+ expect($config)->toContain('test-app');
+ expect($config)->toContain('image:');
+ expect($config)->toContain('networks:');
+});
+```
+
+### Service Layer Testing
+```php
+// Testing service classes
+test('configuration generator creates valid docker compose', function () {
+ $generator = new ConfigurationGenerator();
+ $application = Application::factory()->create();
+
+ $compose = $generator->generateDockerCompose($application);
+
+ expect($compose)->toBeString();
+ expect(yaml_parse($compose))->toBeArray();
+ expect($compose)->toContain('version: "3.8"');
+});
+
+test('docker image parser validates image names', function () {
+ $parser = new DockerImageParser();
+
+ expect($parser->isValid('nginx:latest'))->toBeTrue();
+ expect($parser->isValid('invalid-image-name'))->toBeFalse();
+ expect($parser->parse('nginx:1.21'))->toEqual([
+ 'registry' => 'docker.io',
+ 'namespace' => 'library',
+ 'repository' => 'nginx',
+ 'tag' => '1.21'
+ ]);
+});
+```
+
+### Action Testing
+```php
+// Testing Laravel Actions
+test('deploy application action creates deployment queue', function () {
+ $application = Application::factory()->create();
+ $action = new DeployApplicationAction();
+
+ $deployment = $action->handle($application);
+
+ expect($deployment)->toBeInstanceOf(ApplicationDeploymentQueue::class);
+ expect($deployment->status)->toBe('queued');
+ expect($deployment->application_id)->toBe($application->id);
+});
+
+test('server validation action checks ssh connectivity', function () {
+ $server = Server::factory()->create([
+ 'ip' => '192.168.1.100',
+ 'port' => 22
+ ]);
+
+ $action = new ValidateServerAction();
+
+ // Mock SSH connection
+ $this->mock(SshConnection::class, function ($mock) {
+ $mock->shouldReceive('connect')->andReturn(true);
+ $mock->shouldReceive('execute')->with('docker --version')->andReturn('Docker version 20.10.0');
+ });
+
+ $result = $action->handle($server);
+
+ expect($result['ssh_connection'])->toBeTrue();
+ expect($result['docker_installed'])->toBeTrue();
+});
+```
+
+## Feature Testing Patterns
+
+### API Testing
+```php
+// Testing API endpoints
+test('authenticated user can list applications', function () {
+ $user = User::factory()->create();
+ $team = Team::factory()->create();
+ $user->teams()->attach($team);
+
+ $applications = Application::factory(3)->create([
+ 'team_id' => $team->id
+ ]);
+
+ $response = $this->actingAs($user)
+ ->getJson('/api/v1/applications');
+
+ $response->assertStatus(200)
+ ->assertJsonCount(3, 'data')
+ ->assertJsonStructure([
+ 'data' => [
+ '*' => ['id', 'name', 'fqdn', 'status', 'created_at']
+ ]
+ ]);
+});
+
+test('user cannot access applications from other teams', function () {
+ $user = User::factory()->create();
+ $otherTeam = Team::factory()->create();
+
+ $application = Application::factory()->create([
+ 'team_id' => $otherTeam->id
+ ]);
+
+ $response = $this->actingAs($user)
+ ->getJson("/api/v1/applications/{$application->id}");
+
+ $response->assertStatus(403);
+});
+```
+
+### Deployment Testing
+```php
+// Testing deployment workflows
+test('application deployment creates docker containers', function () {
+ $application = Application::factory()->create([
+ 'git_repository' => 'https://github.com/laravel/laravel.git',
+ 'git_branch' => 'main'
+ ]);
+
+ // Mock Docker operations
+ $this->mock(DockerService::class, function ($mock) {
+ $mock->shouldReceive('buildImage')->andReturn('app:latest');
+ $mock->shouldReceive('createContainer')->andReturn('container_id');
+ $mock->shouldReceive('startContainer')->andReturn(true);
+ });
+
+ $deployment = $application->deploy();
+
+ expect($deployment->status)->toBe('queued');
+
+ // Process the deployment job
+ $this->artisan('queue:work --once');
+
+ $deployment->refresh();
+ expect($deployment->status)->toBe('success');
+});
+
+test('failed deployment triggers rollback', function () {
+ $application = Application::factory()->create();
+
+ // Mock failed deployment
+ $this->mock(DockerService::class, function ($mock) {
+ $mock->shouldReceive('buildImage')->andThrow(new DeploymentException('Build failed'));
+ });
+
+ $deployment = $application->deploy();
+
+ $this->artisan('queue:work --once');
+
+ $deployment->refresh();
+ expect($deployment->status)->toBe('failed');
+ expect($deployment->error_message)->toContain('Build failed');
+});
+```
+
+### Webhook Testing
+```php
+// Testing webhook endpoints
+test('github webhook triggers deployment', function () {
+ $application = Application::factory()->create([
+ 'git_repository' => 'https://github.com/user/repo.git',
+ 'git_branch' => 'main'
+ ]);
+
+ $payload = [
+ 'ref' => 'refs/heads/main',
+ 'repository' => [
+ 'clone_url' => 'https://github.com/user/repo.git'
+ ],
+ 'head_commit' => [
+ 'id' => 'abc123',
+ 'message' => 'Update application'
+ ]
+ ];
+
+ $response = $this->postJson("/webhooks/github/{$application->id}", $payload);
+
+ $response->assertStatus(200);
+
+ expect($application->deployments()->count())->toBe(1);
+ expect($application->deployments()->first()->commit_sha)->toBe('abc123');
+});
+
+test('webhook validates payload signature', function () {
+ $application = Application::factory()->create();
+
+ $payload = ['invalid' => 'payload'];
+
+ $response = $this->postJson("/webhooks/github/{$application->id}", $payload);
+
+ $response->assertStatus(400);
+});
+```
+
+## Browser Testing (Laravel Dusk)
+
+### End-to-End Testing
+```php
+// Testing complete user workflows
+test('user can create and deploy application', function () {
+ $user = User::factory()->create();
+ $server = Server::factory()->create(['team_id' => $user->currentTeam->id]);
+
+ $this->browse(function (Browser $browser) use ($user, $server) {
+ $browser->loginAs($user)
+ ->visit('/applications/create')
+ ->type('name', 'Test Application')
+ ->type('git_repository', 'https://github.com/laravel/laravel.git')
+ ->type('git_branch', 'main')
+ ->select('server_id', $server->id)
+ ->press('Create Application')
+ ->assertPathIs('/applications/*')
+ ->assertSee('Test Application')
+ ->press('Deploy')
+ ->waitForText('Deployment started', 10)
+ ->assertSee('Deployment started');
+ });
+});
+
+test('user can monitor deployment logs in real-time', function () {
+ $user = User::factory()->create();
+ $application = Application::factory()->create(['team_id' => $user->currentTeam->id]);
+
+ $this->browse(function (Browser $browser) use ($user, $application) {
+ $browser->loginAs($user)
+ ->visit("/applications/{$application->id}")
+ ->press('Deploy')
+ ->waitForText('Deployment started')
+ ->click('@logs-tab')
+ ->waitFor('@deployment-logs')
+ ->assertSee('Building Docker image')
+ ->waitForText('Deployment completed', 30);
+ });
+});
+```
+
+### UI Component Testing
+```php
+// Testing Livewire components
+test('server status component updates in real-time', function () {
+ $user = User::factory()->create();
+ $server = Server::factory()->create(['team_id' => $user->currentTeam->id]);
+
+ $this->browse(function (Browser $browser) use ($user, $server) {
+ $browser->loginAs($user)
+ ->visit("/servers/{$server->id}")
+ ->assertSee('Status: Online')
+ ->waitFor('@server-metrics')
+ ->assertSee('CPU Usage')
+ ->assertSee('Memory Usage')
+ ->assertSee('Disk Usage');
+
+ // Simulate server going offline
+ $server->update(['status' => 'offline']);
+
+ $browser->waitForText('Status: Offline', 5)
+ ->assertSee('Status: Offline');
+ });
+});
+```
+
+## Database Testing Patterns
+
+### Migration Testing
+```php
+// Testing database migrations
+test('applications table has correct structure', function () {
+ expect(Schema::hasTable('applications'))->toBeTrue();
+ expect(Schema::hasColumns('applications', [
+ 'id', 'name', 'fqdn', 'git_repository', 'git_branch',
+ 'server_id', 'environment_id', 'created_at', 'updated_at'
+ ]))->toBeTrue();
+});
+
+test('foreign key constraints are properly set', function () {
+ $application = Application::factory()->create();
+
+ expect($application->server)->toBeInstanceOf(Server::class);
+ expect($application->environment)->toBeInstanceOf(Environment::class);
+
+ // Test cascade deletion
+ $application->server->delete();
+ expect(Application::find($application->id))->toBeNull();
+});
+```
+
+### Factory Testing
+```php
+// Testing model factories
+test('application factory creates valid models', function () {
+ $application = Application::factory()->create();
+
+ expect($application->name)->toBeString();
+ expect($application->git_repository)->toStartWith('https://');
+ expect($application->server_id)->toBeInt();
+ expect($application->environment_id)->toBeInt();
+});
+
+test('application factory can create with custom attributes', function () {
+ $application = Application::factory()->create([
+ 'name' => 'Custom App',
+ 'git_branch' => 'develop'
+ ]);
+
+ expect($application->name)->toBe('Custom App');
+ expect($application->git_branch)->toBe('develop');
+});
+```
+
+## Queue Testing
+
+### Job Testing
+```php
+// Testing background jobs
+test('deploy application job processes successfully', function () {
+ $application = Application::factory()->create();
+ $deployment = ApplicationDeploymentQueue::factory()->create([
+ 'application_id' => $application->id,
+ 'status' => 'queued'
+ ]);
+
+ $job = new DeployApplicationJob($deployment);
+
+ // Mock external dependencies
+ $this->mock(DockerService::class, function ($mock) {
+ $mock->shouldReceive('buildImage')->andReturn('app:latest');
+ $mock->shouldReceive('deployContainer')->andReturn(true);
+ });
+
+ $job->handle();
+
+ $deployment->refresh();
+ expect($deployment->status)->toBe('success');
+});
+
+test('failed job is retried with exponential backoff', function () {
+ $application = Application::factory()->create();
+ $deployment = ApplicationDeploymentQueue::factory()->create([
+ 'application_id' => $application->id
+ ]);
+
+ $job = new DeployApplicationJob($deployment);
+
+ // Mock failure
+ $this->mock(DockerService::class, function ($mock) {
+ $mock->shouldReceive('buildImage')->andThrow(new Exception('Network error'));
+ });
+
+ expect(fn() => $job->handle())->toThrow(Exception::class);
+
+ // Job should be retried
+ expect($job->tries)->toBe(3);
+ expect($job->backoff())->toBe([1, 5, 10]);
+});
+```
+
+## Security Testing
+
+### Authentication Testing
+```php
+// Testing authentication and authorization
+test('unauthenticated users cannot access protected routes', function () {
+ $response = $this->get('/dashboard');
+ $response->assertRedirect('/login');
+});
+
+test('users can only access their team resources', function () {
+ $user1 = User::factory()->create();
+ $user2 = User::factory()->create();
+
+ $team1 = Team::factory()->create();
+ $team2 = Team::factory()->create();
+
+ $user1->teams()->attach($team1);
+ $user2->teams()->attach($team2);
+
+ $application = Application::factory()->create(['team_id' => $team1->id]);
+
+ $response = $this->actingAs($user2)
+ ->get("/applications/{$application->id}");
+
+ $response->assertStatus(403);
+});
+```
+
+### Input Validation Testing
+```php
+// Testing input validation and sanitization
+test('application creation validates required fields', function () {
+ $user = User::factory()->create();
+
+ $response = $this->actingAs($user)
+ ->postJson('/api/v1/applications', []);
+
+ $response->assertStatus(422)
+ ->assertJsonValidationErrors(['name', 'git_repository', 'server_id']);
+});
+
+test('malicious input is properly sanitized', function () {
+ $user = User::factory()->create();
+
+ $response = $this->actingAs($user)
+ ->postJson('/api/v1/applications', [
+ 'name' => '',
+ 'git_repository' => 'javascript:alert("xss")',
+ 'server_id' => 'invalid'
+ ]);
+
+ $response->assertStatus(422);
+});
+```
+
+## Performance Testing
+
+### Load Testing
+```php
+// Testing application performance under load
+test('application list endpoint handles concurrent requests', function () {
+ $user = User::factory()->create();
+ $applications = Application::factory(100)->create(['team_id' => $user->currentTeam->id]);
+
+ $startTime = microtime(true);
+
+ $response = $this->actingAs($user)
+ ->getJson('/api/v1/applications');
+
+ $endTime = microtime(true);
+ $responseTime = ($endTime - $startTime) * 1000; // Convert to milliseconds
+
+ $response->assertStatus(200);
+ expect($responseTime)->toBeLessThan(500); // Should respond within 500ms
+});
+```
+
+### Memory Usage Testing
+```php
+// Testing memory efficiency
+test('deployment process does not exceed memory limits', function () {
+ $initialMemory = memory_get_usage();
+
+ $application = Application::factory()->create();
+ $deployment = $application->deploy();
+
+ // Process deployment
+ $this->artisan('queue:work --once');
+
+ $finalMemory = memory_get_usage();
+ $memoryIncrease = $finalMemory - $initialMemory;
+
+ expect($memoryIncrease)->toBeLessThan(50 * 1024 * 1024); // Less than 50MB
+});
+```
+
+## Test Utilities and Helpers
+
+### Custom Assertions
+```php
+// Custom test assertions
+expect()->extend('toBeValidDockerCompose', function () {
+ $yaml = yaml_parse($this->value);
+
+ return $yaml !== false &&
+ isset($yaml['version']) &&
+ isset($yaml['services']) &&
+ is_array($yaml['services']);
+});
+
+expect()->extend('toHaveValidSshConnection', function () {
+ $server = $this->value;
+
+ try {
+ $connection = new SshConnection($server);
+ return $connection->test();
+ } catch (Exception $e) {
+ return false;
+ }
+});
+```
+
+### Test Traits
+```php
+// Shared testing functionality
+trait CreatesTestServers
+{
+ protected function createTestServer(array $attributes = []): Server
+ {
+ return Server::factory()->create(array_merge([
+ 'name' => 'Test Server',
+ 'ip' => '127.0.0.1',
+ 'port' => 22,
+ 'team_id' => $this->user->currentTeam->id
+ ], $attributes));
+ }
+}
+
+trait MocksDockerOperations
+{
+ protected function mockDockerService(): void
+ {
+ $this->mock(DockerService::class, function ($mock) {
+ $mock->shouldReceive('buildImage')->andReturn('test:latest');
+ $mock->shouldReceive('createContainer')->andReturn('container_123');
+ $mock->shouldReceive('startContainer')->andReturn(true);
+ $mock->shouldReceive('stopContainer')->andReturn(true);
+ });
+ }
+}
+```
+
+## Continuous Integration Testing
+
+### GitHub Actions Integration
+```yaml
+# .github/workflows/tests.yml
+name: Tests
+on: [push, pull_request]
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ services:
+ postgres:
+ image: postgres:15
+ env:
+ POSTGRES_PASSWORD: password
+ options: >-
+ --health-cmd pg_isready
+ --health-interval 10s
+ --health-timeout 5s
+ --health-retries 5
+ steps:
+ - uses: actions/checkout@v3
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: 8.4
+ - name: Install dependencies
+ run: composer install
+ - name: Run tests
+ run: ./vendor/bin/pest
+```
+
+### Test Coverage
+```php
+// Generate test coverage reports
+test('application has adequate test coverage', function () {
+ $coverage = $this->getCoverageData();
+
+ expect($coverage['application'])->toBeGreaterThan(80);
+ expect($coverage['models'])->toBeGreaterThan(90);
+ expect($coverage['actions'])->toBeGreaterThan(85);
+});
+```
diff --git a/.ai/meta/maintaining-docs.md b/.ai/meta/maintaining-docs.md
new file mode 100644
index 0000000000..1a15523995
--- /dev/null
+++ b/.ai/meta/maintaining-docs.md
@@ -0,0 +1,172 @@
+# Maintaining AI Documentation
+
+Guidelines for creating and maintaining AI documentation to ensure consistency and effectiveness across all AI tools (Claude Code, Cursor IDE, etc.).
+
+## Documentation Structure
+
+All AI documentation lives in the `.ai/` directory with the following structure:
+
+```
+.ai/
+├── README.md # Navigation hub
+├── core/ # Core project information
+├── development/ # Development practices
+├── patterns/ # Code patterns and best practices
+└── meta/ # Documentation maintenance guides
+```
+
+> **Note**: `CLAUDE.md` is in the repository root, not in the `.ai/` directory.
+
+## Required File Structure
+
+When creating new documentation files:
+
+```markdown
+# Title
+
+Brief description of what this document covers.
+
+## Section 1
+
+- **Main Points in Bold**
+ - Sub-points with details
+ - Examples and explanations
+
+## Section 2
+
+### Subsection
+
+Content with code examples:
+
+```language
+// ✅ DO: Show good examples
+const goodExample = true;
+
+// ❌ DON'T: Show anti-patterns
+const badExample = false;
+```
+```
+
+## File References
+
+- Use relative paths: `See [technology-stack.md](../core/technology-stack.md)`
+- For code references: `` `app/Models/Application.php` ``
+- Keep links working across different tools
+
+## Content Guidelines
+
+### DO:
+- Start with high-level overview
+- Include specific, actionable requirements
+- Show examples of correct implementation
+- Reference existing code when possible
+- Keep documentation DRY by cross-referencing
+- Use bullet points for clarity
+- Include both DO and DON'T examples
+
+### DON'T:
+- Create theoretical examples when real code exists
+- Duplicate content across multiple files
+- Use tool-specific formatting that won't work elsewhere
+- Make assumptions about versions - specify exact versions
+
+## Rule Improvement Triggers
+
+Update documentation when you notice:
+- New code patterns not covered by existing docs
+- Repeated similar implementations across files
+- Common error patterns that could be prevented
+- New libraries or tools being used consistently
+- Emerging best practices in the codebase
+
+## Analysis Process
+
+When updating documentation:
+1. Compare new code with existing rules
+2. Identify patterns that should be standardized
+3. Look for references to external documentation
+4. Check for consistent error handling patterns
+5. Monitor test patterns and coverage
+
+## Rule Updates
+
+### Add New Documentation When:
+- A new technology/pattern is used in 3+ files
+- Common bugs could be prevented by documentation
+- Code reviews repeatedly mention the same feedback
+- New security or performance patterns emerge
+
+### Modify Existing Documentation When:
+- Better examples exist in the codebase
+- Additional edge cases are discovered
+- Related documentation has been updated
+- Implementation details have changed
+
+## Quality Checks
+
+Before committing documentation changes:
+- [ ] Documentation is actionable and specific
+- [ ] Examples come from actual code
+- [ ] References are up to date
+- [ ] Patterns are consistently enforced
+- [ ] Cross-references work correctly
+- [ ] Version numbers are exact and current
+
+## Continuous Improvement
+
+- Monitor code review comments
+- Track common development questions
+- Update docs after major refactors
+- Add links to relevant documentation
+- Cross-reference related docs
+
+## Deprecation
+
+When patterns become outdated:
+1. Mark outdated patterns as deprecated
+2. Remove docs that no longer apply
+3. Update references to deprecated patterns
+4. Document migration paths for old patterns
+
+## Synchronization
+
+### Single Source of Truth
+- Each piece of information should exist in exactly ONE location
+- Other files should reference the source, not duplicate it
+- Example: Version numbers live in `core/technology-stack.md`, other files reference it
+
+### Cross-Tool Compatibility
+- **CLAUDE.md**: Main instructions for Claude Code users (references `.ai/` files)
+- **.cursor/rules/**: Single master file pointing to `.ai/` documentation
+- **Both tools**: Should get same information from `.ai/` directory
+
+### When to Update What
+
+**Version Changes** (Laravel, PHP, packages):
+1. Update `core/technology-stack.md` (single source)
+2. Verify CLAUDE.md references it correctly
+3. No other files should duplicate version numbers
+
+**Workflow Changes** (commands, setup):
+1. Update `development/workflow.md`
+2. Ensure CLAUDE.md quick reference is updated
+3. Verify all cross-references work
+
+**Pattern Changes** (how to write code):
+1. Update appropriate file in `patterns/`
+2. Add/update examples from real codebase
+3. Cross-reference from related docs
+
+## Documentation Files
+
+Keep documentation files only when explicitly needed. Don't create docs that merely describe obvious functionality - the code itself should be clear.
+
+## Breaking Changes
+
+When making breaking changes to documentation structure:
+1. Update this maintaining-docs.md file
+2. Update `.ai/README.md` navigation
+3. Update CLAUDE.md references
+4. Update `.cursor/rules/coolify-ai-docs.mdc`
+5. Test all cross-references still work
+6. Document the changes in sync-guide.md
diff --git a/.ai/meta/sync-guide.md b/.ai/meta/sync-guide.md
new file mode 100644
index 0000000000..ab9a45d1ac
--- /dev/null
+++ b/.ai/meta/sync-guide.md
@@ -0,0 +1,214 @@
+# AI Instructions Synchronization Guide
+
+This document explains how AI instructions are organized and synchronized across different AI tools used with Coolify.
+
+## Overview
+
+Coolify maintains AI instructions with a **single source of truth** approach:
+
+1. **CLAUDE.md** - Main entry point for Claude Code (references `.ai/` directory)
+2. **.cursor/rules/coolify-ai-docs.mdc** - Master reference file for Cursor IDE (references `.ai/` directory)
+3. **.ai/** - Single source of truth containing all detailed documentation
+
+All AI tools (Claude Code, Cursor IDE, etc.) reference the same `.ai/` directory to ensure consistency.
+
+## Structure
+
+### CLAUDE.md (Root Directory)
+- **Purpose**: Entry point for Claude Code with quick-reference guide
+- **Format**: Single markdown file
+- **Includes**:
+ - Quick-reference development commands
+ - High-level architecture overview
+ - Essential patterns and guidelines
+ - References to detailed `.ai/` documentation
+
+### .cursor/rules/coolify-ai-docs.mdc
+- **Purpose**: Master reference file for Cursor IDE
+- **Format**: Single .mdc file with frontmatter
+- **Content**: Quick decision tree and references to `.ai/` directory
+- **Note**: Replaces all previous topic-specific .mdc files
+
+### .ai/ Directory (Single Source of Truth)
+- **Purpose**: All detailed, topic-specific documentation
+- **Format**: Organized markdown files by category
+- **Structure**:
+ ```
+ .ai/
+ ├── README.md # Navigation hub
+ ├── core/ # Project information
+ │ ├── technology-stack.md # Version numbers (SINGLE SOURCE OF TRUTH)
+ │ ├── project-overview.md
+ │ ├── application-architecture.md
+ │ └── deployment-architecture.md
+ ├── development/ # Development practices
+ │ ├── development-workflow.md
+ │ ├── testing-patterns.md
+ │ └── laravel-boost.md
+ ├── patterns/ # Code patterns
+ │ ├── database-patterns.md
+ │ ├── frontend-patterns.md
+ │ ├── security-patterns.md
+ │ ├── form-components.md
+ │ └── api-and-routing.md
+ └── meta/ # Documentation guides
+ ├── maintaining-docs.md
+ └── sync-guide.md (this file)
+ ```
+- **Used by**: All AI tools through CLAUDE.md or coolify-ai-docs.mdc
+
+## Cross-References
+
+All systems reference the `.ai/` directory as the source of truth:
+
+- **CLAUDE.md** → references `.ai/` files for detailed documentation
+- **.cursor/rules/coolify-ai-docs.mdc** → references `.ai/` files for detailed documentation
+- **.ai/README.md** → provides navigation to all documentation
+
+## Maintaining Consistency
+
+### 1. Core Principles (MUST be consistent)
+
+These are defined ONCE in `.ai/core/technology-stack.md`:
+- Laravel version (currently Laravel 12.4.1)
+- PHP version (8.4.7)
+- All package versions (Livewire 3.5.20, Tailwind 4.1.4, etc.)
+
+**Exception**: CLAUDE.md is permitted to show essential version numbers as a quick reference for convenience. These must stay synchronized with `technology-stack.md`. When updating versions, update both locations.
+
+Other critical patterns defined in `.ai/`:
+- Testing execution rules (Docker for Feature tests, mocking for Unit tests)
+- Security patterns and authorization requirements
+- Code style requirements (Pint, PSR-12)
+
+### 2. Where to Make Changes
+
+**For version numbers** (Laravel, PHP, packages):
+1. Update `.ai/core/technology-stack.md` (single source of truth)
+2. Update CLAUDE.md quick reference section (essential versions only)
+3. Verify both files stay synchronized
+4. Never duplicate version numbers in other locations
+
+**For workflow changes** (how to run commands, development setup):
+1. Update `.ai/development/development-workflow.md`
+2. Update quick reference in CLAUDE.md if needed
+3. Verify `.cursor/rules/coolify-ai-docs.mdc` references are correct
+
+**For architectural patterns** (how code should be structured):
+1. Update appropriate file in `.ai/core/`
+2. Add cross-references from related docs
+3. Update CLAUDE.md if it needs to highlight this pattern
+
+**For code patterns** (how to write code):
+1. Update appropriate file in `.ai/patterns/`
+2. Add examples from real codebase
+3. Cross-reference from related docs
+
+**For testing patterns**:
+1. Update `.ai/development/testing-patterns.md`
+2. Ensure CLAUDE.md testing section references it
+
+### 3. Update Checklist
+
+When making significant changes:
+
+- [ ] Identify if change affects core principles (version numbers, critical patterns)
+- [ ] Update primary location in `.ai/` directory
+- [ ] Check if CLAUDE.md needs quick-reference update
+- [ ] Verify `.cursor/rules/coolify-ai-docs.mdc` references are still accurate
+- [ ] Update cross-references in related `.ai/` files
+- [ ] Verify all relative paths work correctly
+- [ ] Test links in markdown files
+- [ ] Run: `./vendor/bin/pint` on modified files (if applicable)
+
+### 4. Common Inconsistencies to Watch
+
+- **Version numbers**: Should ONLY exist in `.ai/core/technology-stack.md`
+- **Testing instructions**: Docker execution requirements must be consistent
+- **File paths**: Ensure relative paths work from their location
+- **Command syntax**: Docker commands, artisan commands must be accurate
+- **Cross-references**: Links must point to current file locations
+
+## File Organization
+
+```
+/
+├── CLAUDE.md # Claude Code entry point
+├── .AI_INSTRUCTIONS_SYNC.md # Redirect to this file
+├── .cursor/
+│ └── rules/
+│ └── coolify-ai-docs.mdc # Cursor IDE master reference
+└── .ai/ # SINGLE SOURCE OF TRUTH
+ ├── README.md # Navigation hub
+ ├── core/ # Project information
+ ├── development/ # Development practices
+ ├── patterns/ # Code patterns
+ └── meta/ # Documentation guides
+```
+
+## Recent Updates
+
+### 2025-11-18 - Documentation Consolidation
+- ✅ Consolidated all documentation into `.ai/` directory
+- ✅ Created single source of truth for version numbers
+- ✅ Reduced CLAUDE.md from 719 to 319 lines
+- ✅ Replaced 11 .cursor/rules/*.mdc files with single coolify-ai-docs.mdc
+- ✅ Organized by topic: core/, development/, patterns/, meta/
+- ✅ Standardized version numbers (Laravel 12.4.1, PHP 8.4.7, Tailwind 4.1.4)
+- ✅ Created comprehensive navigation with .ai/README.md
+
+### 2025-10-07
+- ✅ Added cross-references between CLAUDE.md and .cursor/rules/
+- ✅ Synchronized Laravel version (12) across all files
+- ✅ Added comprehensive testing execution rules (Docker for Feature tests)
+- ✅ Added test design philosophy (prefer mocking over database)
+- ✅ Fixed inconsistencies in testing documentation
+
+## Maintenance Commands
+
+```bash
+# Check for version inconsistencies (should only be in technology-stack.md)
+# Note: CLAUDE.md is allowed to show quick reference versions
+grep -r "Laravel 12" .ai/ CLAUDE.md .cursor/rules/coolify-ai-docs.mdc
+grep -r "PHP 8.4" .ai/ CLAUDE.md .cursor/rules/coolify-ai-docs.mdc
+
+# Check for broken cross-references to old .mdc files
+grep -r "\.cursor/rules/.*\.mdc" .ai/ CLAUDE.md
+
+# Format all documentation
+./vendor/bin/pint CLAUDE.md .ai/**/*.md
+
+# Search for specific patterns across all docs
+grep -r "pattern_to_check" CLAUDE.md .ai/ .cursor/rules/
+
+# Verify all markdown links work (from repository root)
+find .ai -name "*.md" -exec grep -H "\[.*\](.*)" {} \;
+```
+
+## Contributing
+
+When contributing documentation:
+
+1. **Check `.ai/` directory** for existing documentation
+2. **Update `.ai/` files** - this is the single source of truth
+3. **Use cross-references** - never duplicate content
+4. **Update CLAUDE.md** if adding critical quick-reference information
+5. **Verify `.cursor/rules/coolify-ai-docs.mdc`** still references correctly
+6. **Test all links** work from their respective locations
+7. **Update this sync-guide.md** if changing organizational structure
+8. **Verify consistency** before submitting PR
+
+## Questions?
+
+If unsure about where to document something:
+
+- **Version numbers** → `.ai/core/technology-stack.md` (ONLY location)
+- **Quick reference / commands** → CLAUDE.md + `.ai/development/development-workflow.md`
+- **Detailed patterns / examples** → `.ai/patterns/[topic].md`
+- **Architecture / concepts** → `.ai/core/[topic].md`
+- **Development practices** → `.ai/development/[topic].md`
+- **Documentation guides** → `.ai/meta/[topic].md`
+
+**Golden Rule**: Each piece of information exists in ONE location in `.ai/`, other files reference it.
+
+When in doubt, prefer detailed documentation in `.ai/` and lightweight references in CLAUDE.md and coolify-ai-docs.mdc.
diff --git a/.ai/patterns/api-and-routing.md b/.ai/patterns/api-and-routing.md
new file mode 100644
index 0000000000..ceaadaad55
--- /dev/null
+++ b/.ai/patterns/api-and-routing.md
@@ -0,0 +1,469 @@
+# Coolify API & Routing Architecture
+
+## Routing Structure
+
+Coolify implements **multi-layered routing** with web interfaces, RESTful APIs, webhook endpoints, and real-time communication channels.
+
+## Route Files
+
+### Core Route Definitions
+- **[routes/web.php](mdc:routes/web.php)** - Web application routes (21KB, 362 lines)
+- **[routes/api.php](mdc:routes/api.php)** - RESTful API endpoints (13KB, 185 lines)
+- **[routes/webhooks.php](mdc:routes/webhooks.php)** - Webhook receivers (815B, 22 lines)
+- **[routes/channels.php](mdc:routes/channels.php)** - WebSocket channel definitions (829B, 33 lines)
+- **[routes/console.php](mdc:routes/console.php)** - Artisan command routes (592B, 20 lines)
+
+## Web Application Routing
+
+### Authentication Routes
+```php
+// Laravel Fortify authentication
+Route::middleware('guest')->group(function () {
+ Route::get('/login', [AuthController::class, 'login']);
+ Route::get('/register', [AuthController::class, 'register']);
+ Route::get('/forgot-password', [AuthController::class, 'forgotPassword']);
+});
+```
+
+### Dashboard & Core Features
+```php
+// Main application routes
+Route::middleware(['auth', 'verified'])->group(function () {
+ Route::get('/dashboard', Dashboard::class)->name('dashboard');
+ Route::get('/projects', ProjectIndex::class)->name('projects');
+ Route::get('/servers', ServerIndex::class)->name('servers');
+ Route::get('/teams', TeamIndex::class)->name('teams');
+});
+```
+
+### Resource Management Routes
+```php
+// Server management
+Route::prefix('servers')->group(function () {
+ Route::get('/{server}', ServerShow::class)->name('server.show');
+ Route::get('/{server}/edit', ServerEdit::class)->name('server.edit');
+ Route::get('/{server}/logs', ServerLogs::class)->name('server.logs');
+});
+
+// Application management
+Route::prefix('applications')->group(function () {
+ Route::get('/{application}', ApplicationShow::class)->name('application.show');
+ Route::get('/{application}/deployments', ApplicationDeployments::class);
+ Route::get('/{application}/environment-variables', ApplicationEnvironmentVariables::class);
+ Route::get('/{application}/logs', ApplicationLogs::class);
+});
+```
+
+## RESTful API Architecture
+
+### API Versioning
+```php
+// API route structure
+Route::prefix('v1')->group(function () {
+ // Application endpoints
+ Route::apiResource('applications', ApplicationController::class);
+ Route::apiResource('servers', ServerController::class);
+ Route::apiResource('teams', TeamController::class);
+});
+```
+
+### Authentication & Authorization
+```php
+// Sanctum API authentication
+Route::middleware('auth:sanctum')->group(function () {
+ Route::get('/user', function (Request $request) {
+ return $request->user();
+ });
+
+ // Team-scoped resources
+ Route::middleware('team.access')->group(function () {
+ Route::apiResource('applications', ApplicationController::class);
+ });
+});
+```
+
+### Application Management API
+```php
+// Application CRUD operations
+Route::prefix('applications')->group(function () {
+ Route::get('/', [ApplicationController::class, 'index']);
+ Route::post('/', [ApplicationController::class, 'store']);
+ Route::get('/{application}', [ApplicationController::class, 'show']);
+ Route::patch('/{application}', [ApplicationController::class, 'update']);
+ Route::delete('/{application}', [ApplicationController::class, 'destroy']);
+
+ // Deployment operations
+ Route::post('/{application}/deploy', [ApplicationController::class, 'deploy']);
+ Route::post('/{application}/restart', [ApplicationController::class, 'restart']);
+ Route::post('/{application}/stop', [ApplicationController::class, 'stop']);
+ Route::get('/{application}/logs', [ApplicationController::class, 'logs']);
+});
+```
+
+### Server Management API
+```php
+// Server operations
+Route::prefix('servers')->group(function () {
+ Route::get('/', [ServerController::class, 'index']);
+ Route::post('/', [ServerController::class, 'store']);
+ Route::get('/{server}', [ServerController::class, 'show']);
+ Route::patch('/{server}', [ServerController::class, 'update']);
+ Route::delete('/{server}', [ServerController::class, 'destroy']);
+
+ // Server actions
+ Route::post('/{server}/validate', [ServerController::class, 'validate']);
+ Route::get('/{server}/usage', [ServerController::class, 'usage']);
+ Route::post('/{server}/cleanup', [ServerController::class, 'cleanup']);
+});
+```
+
+### Database Management API
+```php
+// Database operations
+Route::prefix('databases')->group(function () {
+ Route::get('/', [DatabaseController::class, 'index']);
+ Route::post('/', [DatabaseController::class, 'store']);
+ Route::get('/{database}', [DatabaseController::class, 'show']);
+ Route::patch('/{database}', [DatabaseController::class, 'update']);
+ Route::delete('/{database}', [DatabaseController::class, 'destroy']);
+
+ // Database actions
+ Route::post('/{database}/backup', [DatabaseController::class, 'backup']);
+ Route::post('/{database}/restore', [DatabaseController::class, 'restore']);
+ Route::get('/{database}/logs', [DatabaseController::class, 'logs']);
+});
+```
+
+## Webhook Architecture
+
+### Git Integration Webhooks
+```php
+// GitHub webhook endpoints
+Route::post('/webhooks/github/{application}', [GitHubWebhookController::class, 'handle'])
+ ->name('webhooks.github');
+
+// GitLab webhook endpoints
+Route::post('/webhooks/gitlab/{application}', [GitLabWebhookController::class, 'handle'])
+ ->name('webhooks.gitlab');
+
+// Generic Git webhooks
+Route::post('/webhooks/git/{application}', [GitWebhookController::class, 'handle'])
+ ->name('webhooks.git');
+```
+
+### Deployment Webhooks
+```php
+// Deployment status webhooks
+Route::post('/webhooks/deployment/{deployment}/success', [DeploymentWebhookController::class, 'success']);
+Route::post('/webhooks/deployment/{deployment}/failure', [DeploymentWebhookController::class, 'failure']);
+Route::post('/webhooks/deployment/{deployment}/progress', [DeploymentWebhookController::class, 'progress']);
+```
+
+### Third-Party Integration Webhooks
+```php
+// Monitoring webhooks
+Route::post('/webhooks/monitoring/{server}', [MonitoringWebhookController::class, 'handle']);
+
+// Backup status webhooks
+Route::post('/webhooks/backup/{backup}', [BackupWebhookController::class, 'handle']);
+
+// SSL certificate webhooks
+Route::post('/webhooks/ssl/{certificate}', [SslWebhookController::class, 'handle']);
+```
+
+## WebSocket Channel Definitions
+
+### Real-Time Channels
+```php
+// Private channels for team members
+Broadcast::channel('team.{teamId}', function ($user, $teamId) {
+ return $user->teams->contains('id', $teamId);
+});
+
+// Application deployment channels
+Broadcast::channel('application.{applicationId}', function ($user, $applicationId) {
+ return $user->hasAccessToApplication($applicationId);
+});
+
+// Server monitoring channels
+Broadcast::channel('server.{serverId}', function ($user, $serverId) {
+ return $user->hasAccessToServer($serverId);
+});
+```
+
+### Presence Channels
+```php
+// Team collaboration presence
+Broadcast::channel('team.{teamId}.presence', function ($user, $teamId) {
+ if ($user->teams->contains('id', $teamId)) {
+ return ['id' => $user->id, 'name' => $user->name];
+ }
+});
+```
+
+## API Controllers
+
+### Location: [app/Http/Controllers/Api/](mdc:app/Http/Controllers)
+
+#### Resource Controllers
+```php
+class ApplicationController extends Controller
+{
+ public function index(Request $request)
+ {
+ return ApplicationResource::collection(
+ $request->user()->currentTeam->applications()
+ ->with(['server', 'environment'])
+ ->paginate()
+ );
+ }
+
+ public function store(StoreApplicationRequest $request)
+ {
+ $application = $request->user()->currentTeam
+ ->applications()
+ ->create($request->validated());
+
+ return new ApplicationResource($application);
+ }
+
+ public function deploy(Application $application)
+ {
+ $deployment = $application->deploy();
+
+ return response()->json([
+ 'message' => 'Deployment started',
+ 'deployment_id' => $deployment->id
+ ]);
+ }
+}
+```
+
+### API Responses & Resources
+```php
+// API Resource classes
+class ApplicationResource extends JsonResource
+{
+ public function toArray($request)
+ {
+ return [
+ 'id' => $this->id,
+ 'name' => $this->name,
+ 'fqdn' => $this->fqdn,
+ 'status' => $this->status,
+ 'git_repository' => $this->git_repository,
+ 'git_branch' => $this->git_branch,
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at,
+ 'server' => new ServerResource($this->whenLoaded('server')),
+ 'environment' => new EnvironmentResource($this->whenLoaded('environment')),
+ ];
+ }
+}
+```
+
+## API Authentication
+
+### Sanctum Token Authentication
+```php
+// API token generation
+Route::post('/auth/tokens', function (Request $request) {
+ $request->validate([
+ 'name' => 'required|string',
+ 'abilities' => 'array'
+ ]);
+
+ $token = $request->user()->createToken(
+ $request->name,
+ $request->abilities ?? []
+ );
+
+ return response()->json([
+ 'token' => $token->plainTextToken,
+ 'abilities' => $token->accessToken->abilities
+ ]);
+});
+```
+
+### Team-Based Authorization
+```php
+// Team access middleware
+class EnsureTeamAccess
+{
+ public function handle($request, Closure $next)
+ {
+ $teamId = $request->route('team');
+
+ if (!$request->user()->teams->contains('id', $teamId)) {
+ abort(403, 'Access denied to team resources');
+ }
+
+ return $next($request);
+ }
+}
+```
+
+## Rate Limiting
+
+### API Rate Limits
+```php
+// API throttling configuration
+RateLimiter::for('api', function (Request $request) {
+ return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
+});
+
+// Deployment rate limiting
+RateLimiter::for('deployments', function (Request $request) {
+ return Limit::perMinute(10)->by($request->user()->id);
+});
+```
+
+### Webhook Rate Limiting
+```php
+// Webhook throttling
+RateLimiter::for('webhooks', function (Request $request) {
+ return Limit::perMinute(100)->by($request->ip());
+});
+```
+
+## Route Model Binding
+
+### Custom Route Bindings
+```php
+// Custom model binding for applications
+Route::bind('application', function ($value) {
+ return Application::where('uuid', $value)
+ ->orWhere('id', $value)
+ ->firstOrFail();
+});
+
+// Team-scoped model binding
+Route::bind('team_application', function ($value, $route) {
+ $teamId = $route->parameter('team');
+ return Application::whereHas('environment.project', function ($query) use ($teamId) {
+ $query->where('team_id', $teamId);
+ })->findOrFail($value);
+});
+```
+
+## API Documentation
+
+### OpenAPI Specification
+- **[openapi.json](mdc:openapi.json)** - API documentation (373KB, 8316 lines)
+- **[openapi.yaml](mdc:openapi.yaml)** - YAML format documentation (184KB, 5579 lines)
+
+### Documentation Generation
+```php
+// Swagger/OpenAPI annotations
+/**
+ * @OA\Get(
+ * path="/api/v1/applications",
+ * summary="List applications",
+ * tags={"Applications"},
+ * security={{"bearerAuth":{}}},
+ * @OA\Response(
+ * response=200,
+ * description="List of applications",
+ * @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Application"))
+ * )
+ * )
+ */
+```
+
+## Error Handling
+
+### API Error Responses
+```php
+// Standardized error response format
+class ApiExceptionHandler
+{
+ public function render($request, Throwable $exception)
+ {
+ if ($request->expectsJson()) {
+ return response()->json([
+ 'message' => $exception->getMessage(),
+ 'error_code' => $this->getErrorCode($exception),
+ 'timestamp' => now()->toISOString()
+ ], $this->getStatusCode($exception));
+ }
+
+ return parent::render($request, $exception);
+ }
+}
+```
+
+### Validation Error Handling
+```php
+// Form request validation
+class StoreApplicationRequest extends FormRequest
+{
+ public function rules()
+ {
+ return [
+ 'name' => 'required|string|max:255',
+ 'git_repository' => 'required|url',
+ 'git_branch' => 'required|string',
+ 'server_id' => 'required|exists:servers,id',
+ 'environment_id' => 'required|exists:environments,id'
+ ];
+ }
+
+ public function failedValidation(Validator $validator)
+ {
+ throw new HttpResponseException(
+ response()->json([
+ 'message' => 'Validation failed',
+ 'errors' => $validator->errors()
+ ], 422)
+ );
+ }
+}
+```
+
+## Real-Time API Integration
+
+### WebSocket Events
+```php
+// Broadcasting deployment events
+class DeploymentStarted implements ShouldBroadcast
+{
+ public $application;
+ public $deployment;
+
+ public function broadcastOn()
+ {
+ return [
+ new PrivateChannel("application.{$this->application->id}"),
+ new PrivateChannel("team.{$this->application->team->id}")
+ ];
+ }
+
+ public function broadcastWith()
+ {
+ return [
+ 'deployment_id' => $this->deployment->id,
+ 'status' => 'started',
+ 'timestamp' => now()
+ ];
+ }
+}
+```
+
+### API Event Streaming
+```php
+// Server-Sent Events for real-time updates
+Route::get('/api/v1/applications/{application}/events', function (Application $application) {
+ return response()->stream(function () use ($application) {
+ while (true) {
+ $events = $application->getRecentEvents();
+ foreach ($events as $event) {
+ echo "data: " . json_encode($event) . "\n\n";
+ }
+ usleep(1000000); // 1 second
+ }
+ }, 200, [
+ 'Content-Type' => 'text/event-stream',
+ 'Cache-Control' => 'no-cache',
+ ]);
+});
+```
diff --git a/.ai/patterns/database-patterns.md b/.ai/patterns/database-patterns.md
new file mode 100644
index 0000000000..5a9d16f711
--- /dev/null
+++ b/.ai/patterns/database-patterns.md
@@ -0,0 +1,377 @@
+# Coolify Database Architecture & Patterns
+
+## Database Strategy
+
+Coolify uses **PostgreSQL 15** as the primary database with **Redis 7** for caching and real-time features. The architecture supports managing multiple external databases across different servers.
+
+## Primary Database (PostgreSQL)
+
+### Core Tables & Models
+
+#### User & Team Management
+- **[User.php](mdc:app/Models/User.php)** - User authentication and profiles
+- **[Team.php](mdc:app/Models/Team.php)** - Multi-tenant organization structure
+- **[TeamInvitation.php](mdc:app/Models/TeamInvitation.php)** - Team collaboration invitations
+- **[PersonalAccessToken.php](mdc:app/Models/PersonalAccessToken.php)** - API token management
+
+#### Infrastructure Management
+- **[Server.php](mdc:app/Models/Server.php)** - Physical/virtual server definitions (46KB, complex)
+- **[PrivateKey.php](mdc:app/Models/PrivateKey.php)** - SSH key management
+- **[ServerSetting.php](mdc:app/Models/ServerSetting.php)** - Server-specific configurations
+
+#### Project Organization
+- **[Project.php](mdc:app/Models/Project.php)** - Project containers for applications
+- **[Environment.php](mdc:app/Models/Environment.php)** - Environment isolation (staging, production, etc.)
+- **[ProjectSetting.php](mdc:app/Models/ProjectSetting.php)** - Project-specific settings
+
+#### Application Deployment
+- **[Application.php](mdc:app/Models/Application.php)** - Main application entity (74KB, highly complex)
+- **[ApplicationSetting.php](mdc:app/Models/ApplicationSetting.php)** - Application configurations
+- **[ApplicationDeploymentQueue.php](mdc:app/Models/ApplicationDeploymentQueue.php)** - Deployment orchestration
+- **[ApplicationPreview.php](mdc:app/Models/ApplicationPreview.php)** - Preview environment management
+
+#### Service Management
+- **[Service.php](mdc:app/Models/Service.php)** - Service definitions (58KB, complex)
+- **[ServiceApplication.php](mdc:app/Models/ServiceApplication.php)** - Service components
+- **[ServiceDatabase.php](mdc:app/Models/ServiceDatabase.php)** - Service-attached databases
+
+## Database Type Support
+
+### Standalone Database Models
+Each database type has its own dedicated model with specific configurations:
+
+#### SQL Databases
+- **[StandalonePostgresql.php](mdc:app/Models/StandalonePostgresql.php)** - PostgreSQL instances
+- **[StandaloneMysql.php](mdc:app/Models/StandaloneMysql.php)** - MySQL instances
+- **[StandaloneMariadb.php](mdc:app/Models/StandaloneMariadb.php)** - MariaDB instances
+
+#### NoSQL & Analytics
+- **[StandaloneMongodb.php](mdc:app/Models/StandaloneMongodb.php)** - MongoDB instances
+- **[StandaloneClickhouse.php](mdc:app/Models/StandaloneClickhouse.php)** - ClickHouse analytics
+
+#### Caching & In-Memory
+- **[StandaloneRedis.php](mdc:app/Models/StandaloneRedis.php)** - Redis instances
+- **[StandaloneKeydb.php](mdc:app/Models/StandaloneKeydb.php)** - KeyDB instances
+- **[StandaloneDragonfly.php](mdc:app/Models/StandaloneDragonfly.php)** - Dragonfly instances
+
+## Configuration Management
+
+### Environment Variables
+- **[EnvironmentVariable.php](mdc:app/Models/EnvironmentVariable.php)** - Application-specific environment variables
+- **[SharedEnvironmentVariable.php](mdc:app/Models/SharedEnvironmentVariable.php)** - Shared across applications
+
+### Settings Hierarchy
+- **[InstanceSettings.php](mdc:app/Models/InstanceSettings.php)** - Global Coolify instance settings
+- **[ServerSetting.php](mdc:app/Models/ServerSetting.php)** - Server-specific settings
+- **[ProjectSetting.php](mdc:app/Models/ProjectSetting.php)** - Project-level settings
+- **[ApplicationSetting.php](mdc:app/Models/ApplicationSetting.php)** - Application settings
+
+## Storage & Backup Systems
+
+### Storage Management
+- **[S3Storage.php](mdc:app/Models/S3Storage.php)** - S3-compatible storage configurations
+- **[LocalFileVolume.php](mdc:app/Models/LocalFileVolume.php)** - Local filesystem volumes
+- **[LocalPersistentVolume.php](mdc:app/Models/LocalPersistentVolume.php)** - Persistent volume management
+
+### Backup Infrastructure
+- **[ScheduledDatabaseBackup.php](mdc:app/Models/ScheduledDatabaseBackup.php)** - Automated backup scheduling
+- **[ScheduledDatabaseBackupExecution.php](mdc:app/Models/ScheduledDatabaseBackupExecution.php)** - Backup execution tracking
+
+### Task Scheduling
+- **[ScheduledTask.php](mdc:app/Models/ScheduledTask.php)** - Cron job management
+- **[ScheduledTaskExecution.php](mdc:app/Models/ScheduledTaskExecution.php)** - Task execution history
+
+## Notification & Integration Models
+
+### Notification Channels
+- **[EmailNotificationSettings.php](mdc:app/Models/EmailNotificationSettings.php)** - Email notifications
+- **[DiscordNotificationSettings.php](mdc:app/Models/DiscordNotificationSettings.php)** - Discord integration
+- **[SlackNotificationSettings.php](mdc:app/Models/SlackNotificationSettings.php)** - Slack integration
+- **[TelegramNotificationSettings.php](mdc:app/Models/TelegramNotificationSettings.php)** - Telegram bot
+- **[PushoverNotificationSettings.php](mdc:app/Models/PushoverNotificationSettings.php)** - Pushover notifications
+
+### Source Control Integration
+- **[GithubApp.php](mdc:app/Models/GithubApp.php)** - GitHub App integration
+- **[GitlabApp.php](mdc:app/Models/GitlabApp.php)** - GitLab integration
+
+### OAuth & Authentication
+- **[OauthSetting.php](mdc:app/Models/OauthSetting.php)** - OAuth provider configurations
+
+## Docker & Container Management
+
+### Container Orchestration
+- **[StandaloneDocker.php](mdc:app/Models/StandaloneDocker.php)** - Standalone Docker containers
+- **[SwarmDocker.php](mdc:app/Models/SwarmDocker.php)** - Docker Swarm management
+
+### SSL & Security
+- **[SslCertificate.php](mdc:app/Models/SslCertificate.php)** - SSL certificate management
+
+## Database Migration Strategy
+
+### Migration Location: [database/migrations/](mdc:database/migrations)
+
+#### Migration Patterns
+```php
+// Typical Coolify migration structure
+Schema::create('applications', function (Blueprint $table) {
+ $table->id();
+ $table->string('name');
+ $table->string('fqdn')->nullable();
+ $table->json('environment_variables')->nullable();
+ $table->foreignId('destination_id');
+ $table->foreignId('source_id');
+ $table->timestamps();
+});
+```
+
+### Schema Versioning
+- **Incremental migrations** for database evolution
+- **Data migrations** for complex transformations
+- **Rollback support** for deployment safety
+
+## Eloquent Model Patterns
+
+### Base Model Structure
+- **[BaseModel.php](mdc:app/Models/BaseModel.php)** - Common model functionality
+- **UUID primary keys** for distributed systems
+- **Soft deletes** for audit trails
+- **Activity logging** with Spatie package
+
+### **CRITICAL: Mass Assignment Protection**
+**When adding new database columns, you MUST update the model's `$fillable` array.** Without this, Laravel will silently ignore mass assignment operations like `Model::create()` or `$model->update()`.
+
+**Checklist for new columns:**
+1. ✅ Create migration file
+2. ✅ Run migration
+3. ✅ **Add column to model's `$fillable` array**
+4. ✅ Update any Livewire components that sync this property
+5. ✅ Test that the column can be read and written
+
+**Example:**
+```php
+class Server extends BaseModel
+{
+ protected $fillable = [
+ 'name',
+ 'ip',
+ 'port',
+ 'is_validating', // ← MUST add new columns here
+ ];
+}
+```
+
+### Relationship Patterns
+```php
+// Typical relationship structure in Application model
+class Application extends Model
+{
+ public function server()
+ {
+ return $this->belongsTo(Server::class);
+ }
+
+ public function environment()
+ {
+ return $this->belongsTo(Environment::class);
+ }
+
+ public function deployments()
+ {
+ return $this->hasMany(ApplicationDeploymentQueue::class);
+ }
+
+ public function environmentVariables()
+ {
+ return $this->hasMany(EnvironmentVariable::class);
+ }
+}
+```
+
+### Model Traits
+```php
+// Common traits used across models
+use SoftDeletes;
+use LogsActivity;
+use HasFactory;
+use HasUuids;
+```
+
+## Caching Strategy (Redis)
+
+### Cache Usage Patterns
+- **Session storage** - User authentication sessions
+- **Queue backend** - Background job processing
+- **Model caching** - Expensive query results
+- **Real-time data** - WebSocket state management
+
+### Cache Keys Structure
+```
+coolify:session:{session_id}
+coolify:server:{server_id}:status
+coolify:deployment:{deployment_id}:logs
+coolify:user:{user_id}:teams
+```
+
+## Query Optimization Patterns
+
+### Eager Loading
+```php
+// Optimized queries with relationships
+$applications = Application::with([
+ 'server',
+ 'environment.project',
+ 'environmentVariables',
+ 'deployments' => function ($query) {
+ $query->latest()->limit(5);
+ }
+])->get();
+```
+
+### Chunking for Large Datasets
+```php
+// Processing large datasets efficiently
+Server::chunk(100, function ($servers) {
+ foreach ($servers as $server) {
+ // Process server monitoring
+ }
+});
+```
+
+### Database Indexes
+- **Primary keys** on all tables
+- **Foreign key indexes** for relationships
+- **Composite indexes** for common queries
+- **Unique constraints** for business rules
+
+### Request-Level Caching with ownedByCurrentTeamCached()
+
+Many models have both `ownedByCurrentTeam()` (returns query builder) and `ownedByCurrentTeamCached()` (returns cached collection). **Always prefer the cached version** to avoid duplicate database queries within the same request.
+
+**Models with cached methods available:**
+- `Server`, `PrivateKey`, `Project`
+- `Application`
+- `StandalonePostgresql`, `StandaloneMysql`, `StandaloneRedis`, `StandaloneMariadb`, `StandaloneMongodb`, `StandaloneKeydb`, `StandaloneDragonfly`, `StandaloneClickhouse`
+- `Service`, `ServiceApplication`, `ServiceDatabase`
+
+**Usage patterns:**
+```php
+// ✅ CORRECT - Uses request-level cache (via Laravel's once() helper)
+$servers = Server::ownedByCurrentTeamCached();
+
+// ❌ AVOID - Makes a new database query each time
+$servers = Server::ownedByCurrentTeam()->get();
+
+// ✅ CORRECT - Filter cached collection in memory
+$activeServers = Server::ownedByCurrentTeamCached()->where('is_active', true);
+$server = Server::ownedByCurrentTeamCached()->firstWhere('id', $serverId);
+$serverIds = Server::ownedByCurrentTeamCached()->pluck('id');
+
+// ❌ AVOID - Making filtered database queries when data is already cached
+$activeServers = Server::ownedByCurrentTeam()->where('is_active', true)->get();
+```
+
+**When to use which:**
+- `ownedByCurrentTeamCached()` - **Default choice** for reading team data
+- `ownedByCurrentTeam()` - Only when you need to chain query builder methods that can't be done on collections (like `with()` for eager loading), or when you explicitly need a fresh database query
+
+**Implementation pattern for new models:**
+```php
+/**
+ * Get query builder for resources owned by current team.
+ * If you need all resources without further query chaining, use ownedByCurrentTeamCached() instead.
+ */
+public static function ownedByCurrentTeam()
+{
+ return self::whereTeamId(currentTeam()->id);
+}
+
+/**
+ * Get all resources owned by current team (cached for request duration).
+ */
+public static function ownedByCurrentTeamCached()
+{
+ return once(function () {
+ return self::ownedByCurrentTeam()->get();
+ });
+}
+```
+
+## Data Consistency Patterns
+
+### Database Transactions
+```php
+// Atomic operations for deployment
+DB::transaction(function () {
+ $application = Application::create($data);
+ $application->environmentVariables()->createMany($envVars);
+ $application->deployments()->create(['status' => 'queued']);
+});
+```
+
+### Model Events
+```php
+// Automatic cleanup on model deletion
+class Application extends Model
+{
+ protected static function booted()
+ {
+ static::deleting(function ($application) {
+ $application->environmentVariables()->delete();
+ $application->deployments()->delete();
+ });
+ }
+}
+```
+
+## Backup & Recovery
+
+### Database Backup Strategy
+- **Automated PostgreSQL backups** via scheduled tasks
+- **Point-in-time recovery** capability
+- **Cross-region backup** replication
+- **Backup verification** and testing
+
+### Data Export/Import
+- **Application configurations** export/import
+- **Environment variable** bulk operations
+- **Server configurations** backup and restore
+
+## Performance Monitoring
+
+### Query Performance
+- **Laravel Telescope** for development debugging
+- **Slow query logging** in production
+- **Database connection** pooling
+- **Read replica** support for scaling
+
+### Metrics Collection
+- **Database size** monitoring
+- **Connection count** tracking
+- **Query execution time** analysis
+- **Cache hit rates** monitoring
+
+## Multi-Tenancy Pattern
+
+### Team-Based Isolation
+```php
+// Global scope for team-based filtering
+class Application extends Model
+{
+ protected static function booted()
+ {
+ static::addGlobalScope('team', function (Builder $builder) {
+ if (auth()->user()) {
+ $builder->whereHas('environment.project', function ($query) {
+ $query->where('team_id', auth()->user()->currentTeam->id);
+ });
+ }
+ });
+ }
+}
+```
+
+### Data Separation
+- **Team-scoped queries** by default
+- **Cross-team access** controls
+- **Admin access** patterns
+- **Data isolation** guarantees
diff --git a/.ai/patterns/form-components.md b/.ai/patterns/form-components.md
new file mode 100644
index 0000000000..3ff1d0f817
--- /dev/null
+++ b/.ai/patterns/form-components.md
@@ -0,0 +1,447 @@
+
+# Enhanced Form Components with Authorization
+
+## Overview
+
+Coolify's form components now feature **built-in authorization** that automatically handles permission-based UI control, dramatically reducing code duplication and improving security consistency.
+
+## Enhanced Components
+
+All form components now support the `canGate` authorization system:
+
+- **[Input.php](mdc:app/View/Components/Forms/Input.php)** - Text, password, and other input fields
+- **[Select.php](mdc:app/View/Components/Forms/Select.php)** - Dropdown selection components
+- **[Textarea.php](mdc:app/View/Components/Forms/Textarea.php)** - Multi-line text areas
+- **[Checkbox.php](mdc:app/View/Components/Forms/Checkbox.php)** - Boolean toggle components
+- **[Button.php](mdc:app/View/Components/Forms/Button.php)** - Action buttons
+
+## Authorization Parameters
+
+### Core Parameters
+```php
+public ?string $canGate = null; // Gate name: 'update', 'view', 'deploy', 'delete'
+public mixed $canResource = null; // Resource model instance to check against
+public bool $autoDisable = true; // Automatically disable if no permission
+```
+
+### How It Works
+```php
+// Automatic authorization logic in each component
+if ($this->canGate && $this->canResource && $this->autoDisable) {
+ $hasPermission = Gate::allows($this->canGate, $this->canResource);
+
+ if (! $hasPermission) {
+ $this->disabled = true;
+ // For Checkbox: also sets $this->instantSave = false;
+ }
+}
+```
+
+## Usage Patterns
+
+### ✅ Recommended: Single Line Pattern
+
+**Before (Verbose, 6+ lines per element):**
+```html
+@can('update', $application)
+
+
+ Save
+@else
+
+
+@endcan
+```
+
+**After (Clean, 1 line per element):**
+```html
+
+
+Save
+```
+
+**Result: 90% code reduction!**
+
+### Component-Specific Examples
+
+#### Input Fields
+```html
+
+
+
+
+
+
+
+
+```
+
+#### Select Dropdowns
+```html
+
+
+
+
+
+
+
+
+
+ @foreach($servers as $server)
+
+ @endforeach
+
+```
+
+#### Checkboxes with InstantSave
+```html
+
+
+
+
+
+
+
+
+```
+
+#### Textareas
+```html
+
+
+
+
+
+```
+
+#### Buttons
+```html
+
+
+ Save Configuration
+
+
+
+
+ Deploy Application
+
+
+
+
+ Delete Application
+
+```
+
+## Advanced Usage
+
+### Custom Authorization Logic
+```html
+
+
+```
+
+### Multiple Permission Checks
+```html
+
+
+```
+
+### Conditional Resources
+```html
+
+
+ {{ $isEditing ? 'Save Changes' : 'View Details' }}
+
+```
+
+## Supported Gates
+
+### Resource-Level Gates
+- `view` - Read access to resource details
+- `update` - Modify resource configuration and settings
+- `deploy` - Deploy, restart, or manage resource state
+- `delete` - Remove or destroy resource
+- `clone` - Duplicate resource to another location
+
+### Global Gates
+- `createAnyResource` - Create new resources of any type
+- `manageTeam` - Team administration permissions
+- `accessServer` - Server-level access permissions
+
+## Supported Resources
+
+### Primary Resources
+- `$application` - Application instances and configurations
+- `$service` - Docker Compose services and components
+- `$database` - Database instances (PostgreSQL, MySQL, etc.)
+- `$server` - Physical or virtual server instances
+
+### Container Resources
+- `$project` - Project containers and environments
+- `$environment` - Environment-specific configurations
+- `$team` - Team and organization contexts
+
+### Infrastructure Resources
+- `$privateKey` - SSH private keys and certificates
+- `$source` - Git sources and repositories
+- `$destination` - Deployment destinations and targets
+
+## Component Behavior
+
+### Input Components (Input, Select, Textarea)
+When authorization fails:
+- **disabled = true** - Field becomes non-editable
+- **Visual styling** - Opacity reduction and disabled cursor
+- **Form submission** - Values are ignored in forms
+- **User feedback** - Clear visual indication of restricted access
+
+### Checkbox Components
+When authorization fails:
+- **disabled = true** - Checkbox becomes non-clickable
+- **instantSave = false** - Automatic saving is disabled
+- **State preservation** - Current value is maintained but read-only
+- **Visual styling** - Disabled appearance with reduced opacity
+
+### Button Components
+When authorization fails:
+- **disabled = true** - Button becomes non-clickable
+- **Event blocking** - Click handlers are ignored
+- **Visual styling** - Disabled appearance and cursor
+- **Loading states** - Loading indicators are disabled
+
+## Migration Guide
+
+### Converting Existing Forms
+
+**Old Pattern:**
+```html
+
+```
+
+**New Pattern:**
+```html
+
+```
+
+### Gradual Migration Strategy
+
+1. **Start with new forms** - Use the new pattern for all new components
+2. **Convert high-traffic areas** - Migrate frequently used forms first
+3. **Batch convert similar forms** - Group similar authorization patterns
+4. **Test thoroughly** - Verify authorization behavior matches expectations
+5. **Remove old patterns** - Clean up legacy @can/@else blocks
+
+## Testing Patterns
+
+### Component Authorization Tests
+```php
+// Test authorization integration in components
+test('input component respects authorization', function () {
+ $user = User::factory()->member()->create();
+ $application = Application::factory()->create();
+
+ // Member should see disabled input
+ $component = Livewire::actingAs($user)
+ ->test(TestComponent::class, [
+ 'canGate' => 'update',
+ 'canResource' => $application
+ ]);
+
+ expect($component->get('disabled'))->toBeTrue();
+});
+
+test('checkbox disables instantSave for unauthorized users', function () {
+ $user = User::factory()->member()->create();
+ $application = Application::factory()->create();
+
+ $component = Livewire::actingAs($user)
+ ->test(CheckboxComponent::class, [
+ 'instantSave' => true,
+ 'canGate' => 'update',
+ 'canResource' => $application
+ ]);
+
+ expect($component->get('disabled'))->toBeTrue();
+ expect($component->get('instantSave'))->toBeFalse();
+});
+```
+
+### Integration Tests
+```php
+// Test full form authorization behavior
+test('application form respects member permissions', function () {
+ $member = User::factory()->member()->create();
+ $application = Application::factory()->create();
+
+ $this->actingAs($member)
+ ->get(route('application.edit', $application))
+ ->assertSee('disabled')
+ ->assertDontSee('Save Configuration');
+});
+```
+
+## Best Practices
+
+### Consistent Gate Usage
+- Use `update` for configuration changes
+- Use `deploy` for operational actions
+- Use `view` for read-only access
+- Use `delete` for destructive actions
+
+### Resource Context
+- Always pass the specific resource being acted upon
+- Use team context for creation permissions
+- Consider nested resource relationships
+
+### Error Handling
+- Provide clear feedback for disabled components
+- Use helper text to explain permission requirements
+- Consider tooltips for disabled buttons
+
+### Performance
+- Authorization checks are cached per request
+- Use eager loading for resource relationships
+- Consider query optimization for complex permissions
+
+## Common Patterns
+
+### Application Configuration Forms
+```html
+
+
+...
+
+Save
+```
+
+### Service Configuration Forms
+```html
+
+
+
+
+Save
+
+
+
+
+
+@can('update', $service)
+
+@endcan
+```
+
+### Server Management Forms
+```html
+
+
+...
+Delete Server
+```
+
+### Resource Creation Forms
+```html
+
+
+...
+Create Application
+```
\ No newline at end of file
diff --git a/.ai/patterns/frontend-patterns.md b/.ai/patterns/frontend-patterns.md
new file mode 100644
index 0000000000..675881608c
--- /dev/null
+++ b/.ai/patterns/frontend-patterns.md
@@ -0,0 +1,696 @@
+# Coolify Frontend Architecture & Patterns
+
+## Frontend Philosophy
+
+Coolify uses a **server-side first** approach with minimal JavaScript, leveraging Livewire for reactivity and Alpine.js for lightweight client-side interactions.
+
+## Core Frontend Stack
+
+### Livewire 3.5+ (Primary Framework)
+- **Server-side rendering** with reactive components
+- **Real-time updates** without page refreshes
+- **State management** handled on the server
+- **WebSocket integration** for live updates
+
+### Alpine.js (Client-Side Interactivity)
+- **Lightweight JavaScript** for DOM manipulation
+- **Declarative directives** in HTML
+- **Component-like behavior** without build steps
+- **Perfect companion** to Livewire
+
+### Tailwind CSS 4.1+ (Styling)
+- **Utility-first** CSS framework
+- **Custom design system** for deployment platform
+- **Responsive design** built-in
+- **Dark mode support**
+
+## Livewire Component Structure
+
+### Location: [app/Livewire/](mdc:app/Livewire)
+
+#### Core Application Components
+- **[Dashboard.php](mdc:app/Livewire/Dashboard.php)** - Main dashboard interface
+- **[ActivityMonitor.php](mdc:app/Livewire/ActivityMonitor.php)** - Real-time activity tracking
+- **[MonacoEditor.php](mdc:app/Livewire/MonacoEditor.php)** - Code editor component
+
+#### Server Management
+- **Server/** directory - Server configuration and monitoring
+- Real-time server status updates
+- SSH connection management
+- Resource monitoring
+
+#### Project & Application Management
+- **Project/** directory - Project organization
+- Application deployment interfaces
+- Environment variable management
+- Service configuration
+
+#### Settings & Configuration
+- **Settings/** directory - System configuration
+- **[SettingsEmail.php](mdc:app/Livewire/SettingsEmail.php)** - Email notification setup
+- **[SettingsOauth.php](mdc:app/Livewire/SettingsOauth.php)** - OAuth provider configuration
+- **[SettingsBackup.php](mdc:app/Livewire/SettingsBackup.php)** - Backup configuration
+
+#### User & Team Management
+- **Team/** directory - Team collaboration features
+- **Profile/** directory - User profile management
+- **Security/** directory - Security settings
+
+## Blade Template Organization
+
+### Location: [resources/views/](mdc:resources/views)
+
+#### Layout Structure
+- **layouts/** - Base layout templates
+- **components/** - Reusable UI components
+- **livewire/** - Livewire component views
+
+#### Feature-Specific Views
+- **server/** - Server management interfaces
+- **auth/** - Authentication pages
+- **emails/** - Email templates
+- **errors/** - Error pages
+
+## Interactive Components
+
+### Monaco Editor Integration
+- **Code editing** for configuration files
+- **Syntax highlighting** for multiple languages
+- **Live validation** and error detection
+- **Integration** with deployment process
+
+### Terminal Emulation (XTerm.js)
+- **Real-time terminal** access to servers
+- **WebSocket-based** communication
+- **Multi-session** support
+- **Secure connection** through SSH
+
+### Real-Time Updates
+- **WebSocket connections** via Laravel Echo
+- **Live deployment logs** streaming
+- **Server monitoring** with live metrics
+- **Activity notifications** in real-time
+
+## Alpine.js Patterns
+
+### Common Directives Used
+```html
+
+