feat(Production): Complete production deployment infrastructure

- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
This commit is contained in:
2025-10-25 19:18:37 +02:00
parent caa85db796
commit fc3d7e6357
83016 changed files with 378904 additions and 20919 deletions

View File

@@ -0,0 +1,520 @@
# Getting Started with LiveComponents
This guide will help you set up and create your first LiveComponent.
## Prerequisites
- PHP 8.4+ (8.5 recommended)
- Custom PHP Framework installed
- Node.js 18+ for frontend assets
- Docker (optional, for development environment)
## Installation
LiveComponents is built into the Custom PHP Framework. No additional installation is required.
### Verify Installation
```bash
# Check if LiveComponents are available
docker exec php php console.php list | grep livecomponent
# Should show LiveComponent-related commands
```
## Project Structure
```
src/
├── Application/
│ └── LiveComponents/ # Your LiveComponent classes
├── Framework/
│ └── LiveComponents/ # Framework LiveComponents code
│ ├── LiveComponent.php # Base class
│ ├── Attributes/ # Attributes (#[LiveProp], etc.)
│ └── Services/ # Internal services
resources/
├── js/
│ └── modules/
│ └── LiveComponent.js # Client-side JavaScript
└── views/
└── components/ # Component templates
public/
└── assets/
└── js/
└── livecomponent.js # Compiled JavaScript
```
## Configuration
### Environment Variables
Add to your `.env` file:
```env
# LiveComponents Configuration
LIVECOMPONENT_ENABLED=true
LIVECOMPONENT_CSRF_PROTECTION=true
LIVECOMPONENT_RATE_LIMIT=60 # Requests per minute
LIVECOMPONENT_BATCH_SIZE=10 # Max actions per batch
LIVECOMPONENT_BATCH_DEBOUNCE=50 # Debounce delay in ms
LIVECOMPONENT_SSE_ENABLED=true
LIVECOMPONENT_SSE_HEARTBEAT=15 # Heartbeat interval in seconds
LIVECOMPONENT_DEVTOOLS_ENABLED=false # Enable in development only
```
### Frontend Assets
Ensure LiveComponent JavaScript is included in your base layout:
```html
<!-- resources/views/layouts/app.view.php -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="{csrf_token}">
<title>{title}</title>
</head>
<body>
<slot>Main content</slot>
<!-- LiveComponent JavaScript (built by Vite) -->
<script type="module" src="/assets/js/main.js"></script>
</body>
</html>
```
The LiveComponent module is automatically loaded via the main JavaScript entry point.
## Creating Your First Component
### Step 1: Create Component Class
Create a new file: `src/Application/LiveComponents/HelloWorld.php`
```php
<?php
declare(strict_types=1);
namespace App\Application\LiveComponents;
use App\Framework\LiveComponents\LiveComponent;
use App\Framework\LiveComponents\Attributes\LiveAction;
use App\Framework\LiveComponents\Attributes\LiveProp;
final class HelloWorld extends LiveComponent
{
#[LiveProp]
public string $name = 'World';
#[LiveProp]
public int $clickCount = 0;
#[LiveAction]
public function updateName(string $newName): void
{
$this->name = $newName;
}
#[LiveAction]
public function incrementClicks(): void
{
$this->clickCount++;
}
public function render(): string
{
return $this->view('components/hello-world', [
'name' => $this->name,
'clickCount' => $this->clickCount,
'greeting' => $this->getGreeting()
]);
}
private function getGreeting(): string
{
return "Hello, {$this->name}!";
}
}
```
### Step 2: Create Component Template
Create template: `resources/views/components/hello-world.view.php`
```html
<div
data-component-id="{component_id}"
data-component-name="HelloWorld"
class="hello-world-component"
>
<h2>{greeting}</h2>
<div class="input-group">
<label for="name-input">Your Name:</label>
<input
type="text"
id="name-input"
data-lc-model="name"
value="{name}"
placeholder="Enter your name"
/>
</div>
<div class="click-counter">
<p>Button clicked: <strong>{clickCount}</strong> times</p>
<button data-lc-action="incrementClicks" class="btn btn-primary">
Click Me!
</button>
</div>
<style>
.hello-world-component {
padding: 20px;
border: 1px solid #ccc;
border-radius: 8px;
max-width: 400px;
}
.input-group {
margin: 15px 0;
}
.input-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.input-group input {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
.click-counter {
margin-top: 20px;
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.btn-primary {
background: #007bff;
color: white;
}
.btn-primary:hover {
background: #0056b3;
}
</style>
</div>
```
### Step 3: Use Component in Controller
```php
<?php
namespace App\Application;
use App\Framework\Attributes\Route;
use App\Framework\Http\Method;
use App\Framework\Http\ViewResult;
use App\Framework\LiveComponents\LiveComponent;
use App\Application\LiveComponents\HelloWorld;
final readonly class HomeController
{
#[Route(path: '/demo', method: Method::GET)]
public function demo(): ViewResult
{
return new ViewResult('demo', [
'title' => 'LiveComponent Demo',
'helloComponent' => LiveComponent::mount(HelloWorld::class)
]);
}
}
```
### Step 4: Create View Template
Create: `resources/views/demo.view.php`
```html
<include template="layouts/app" data="{title: title}">
<div class="container">
<h1>LiveComponent Demo</h1>
<p>This component is fully interactive without writing any JavaScript!</p>
{helloComponent}
</div>
</include>
```
### Step 5: Test Your Component
1. **Start the development server**:
```bash
make up
npm run dev
```
2. **Visit the demo page**:
```
https://localhost/demo
```
3. **Try the interactions**:
- Type in the name input → Greeting updates automatically
- Click the button → Counter increments
- Open DevTools (F12) → Check Network tab for LiveComponent requests
## How It Works
### 1. Component Mounting
When the page loads:
```php
LiveComponent::mount(HelloWorld::class)
```
This creates a component instance and renders the initial HTML with a unique `component_id`.
### 2. Client-Side Initialization
The JavaScript module detects components by `data-component-id`:
```javascript
// Automatic initialization
document.querySelectorAll('[data-component-id]').forEach(element => {
LiveComponent.initializeComponent(element);
});
```
### 3. Two-Way Data Binding
Input with `data-lc-model="name"`:
- User types → `input` event → Send to server → Update `$name` property → Re-render → Update DOM
### 4. Action Execution
Button with `data-lc-action="incrementClicks"`:
- User clicks → Send action to server → Execute `incrementClicks()` → Re-render → Update DOM
### 5. Request Flow
```
Client Server
│ │
├─ Click Button ──────────────>│
│ ├─ Find Component
│ ├─ Execute Action
│ ├─ Render Template
│<─ JSON Response ─────────────┤
├─ Update DOM │
│ │
```
**Response Format**:
```json
{
"success": true,
"html": "<div data-component-id=\"abc123\">...</div>",
"fragments": {
"results": "<div>Updated fragment HTML</div>"
},
"redirect": null
}
```
## Common Data Binding Patterns
### Input Fields
```html
<!-- Text input -->
<input type="text" data-lc-model="title" value="{title}" />
<!-- Textarea -->
<textarea data-lc-model="description">{description}</textarea>
<!-- Checkbox -->
<input type="checkbox" data-lc-model="agreed" {agreed ? 'checked' : ''} />
<!-- Select -->
<select data-lc-model="category">
<option value="tech" {category === 'tech' ? 'selected' : ''}>Tech</option>
<option value="news" {category === 'news' ? 'selected' : ''}>News</option>
</select>
```
### Actions with Parameters
```html
<!-- Simple action -->
<button data-lc-action="save">Save</button>
<!-- Action with inline parameters -->
<button
data-lc-action="updateStatus"
data-lc-params='{"status": "published"}'
>
Publish
</button>
<!-- Action from event handler -->
<form data-lc-submit="handleSubmit">
<input type="text" name="email" />
<button type="submit">Submit</button>
</form>
```
### Optimistic Updates
```html
<!-- Instant UI feedback -->
<button
data-lc-action="toggleLike"
data-optimistic="true"
>
{isLiked ? '❤️' : '🤍'} Like ({likeCount})
</button>
```
## Debugging
### Enable DevTools Overlay
Set in `.env`:
```env
LIVECOMPONENT_DEVTOOLS_ENABLED=true
```
Or activate via localStorage:
```javascript
localStorage.setItem('livecomponent_devtools', 'true');
location.reload();
```
### DevTools Features
- **Component Tree**: Inspect all components on the page
- **Action Log**: See all executed actions with timing
- **Event Log**: Track client and server events
- **Performance**: Flamegraphs, timeline, memory profiling
- **Network**: Monitor LiveComponent HTTP requests
- **DOM Badges**: Visual component boundaries with activity
### Console Debugging
```javascript
// Get component instance
const component = LiveComponent.getComponent('component-id-here');
// Inspect component state
console.log(component.state);
// Manually trigger action
LiveComponent.executeAction('component-id', 'actionName', { param: 'value' });
// Monitor events
window.addEventListener('livecomponent:action-executed', (e) => {
console.log('Action executed:', e.detail);
});
```
## Next Steps
- [Your First Component](02-first-component.md) - Detailed walkthrough
- [Core Concepts](03-core-concepts.md) - Deep dive into architecture
- [Security Guide](security-guide.md) - CSRF, validation, rate limiting
- [Performance Guide](performance-guide.md) - Optimization techniques
## Troubleshooting
### Component Not Responding
**Check**:
1. Is `data-component-id` present in the rendered HTML?
2. Is the JavaScript bundle loaded? (Check browser console)
3. Are there any JavaScript errors? (F12 → Console)
4. Is HTTPS enabled? (Required for some features)
**Solution**:
```bash
# Rebuild JavaScript assets
npm run build
# Check server logs
docker logs php
# Verify component registration
docker exec php php console.php livecomponent:list
```
### CSRF Token Errors
**Error**: "CSRF token mismatch"
**Solution**:
```html
<!-- Ensure CSRF meta tag is present -->
<meta name="csrf-token" content="{csrf_token}">
```
### Rate Limiting
**Error**: "Too many requests"
**Solution**: Increase rate limit in `.env`:
```env
LIVECOMPONENT_RATE_LIMIT=120 # Increase to 120 per minute
```
## Common Pitfalls
❌ **Forgetting `data-component-id`**
```html
<!-- Wrong -->
<div class="component">...</div>
<!-- Correct -->
<div data-component-id="{component_id}">...</div>
```
❌ **Not using `#[LiveProp]` attribute**
```php
// Wrong - won't sync with client
public string $name = '';
// Correct
#[LiveProp]
public string $name = '';
```
❌ **Mutating props directly in template**
```html
<!-- Wrong - props are readonly on client -->
<button onclick="name = 'new value'">Change</button>
<!-- Correct - use actions -->
<button data-lc-action="updateName" data-lc-params='{"name": "new value"}'>
Change
</button>
```
---
**Next**: [Your First Component Tutorial](02-first-component.md) →