# 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) →
