# LiveComponents FAQ

**Frequently Asked Questions about LiveComponents**

---

## General Questions

### What are LiveComponents?

LiveComponents is a server-side component system that enables building interactive web applications with minimal JavaScript. Components render on the server, sync state automatically, and update the DOM intelligently via fragment-based rendering.

**Key Benefits**:
- Write interactive UIs in PHP
- Automatic state synchronization
- Fragment-based partial updates
- Built-in security (CSRF, rate limiting, validation)
- Real-time updates via Server-Sent Events

---

### When should I use LiveComponents vs traditional JavaScript?

**Use LiveComponents for**:
- Admin dashboards
- CRUD interfaces
- Forms with complex validation
- Real-time data displays
- Prototyping interactive features

**Use traditional JavaScript for**:
- Complex client-side logic
- Heavy animations
- Offline-first applications
- Games or interactive visualizations
- High-frequency updates (>60fps)

**Use Both**:
- LiveComponents for server-side state management
- JavaScript for client-side enhancements

---

### How do LiveComponents compare to Livewire/Phoenix LiveView?

**Similarities**:
- Server-side rendering
- Automatic state sync
- Minimal JavaScript required

**Differences**:
- **Custom Framework Integration**: Built specifically for this framework's patterns (readonly, composition, value objects)
- **Fragment Rendering**: More granular DOM updates
- **Request Batching**: Automatic batching with configurable debouncing
- **PHP 8.5 Optimized**: Leverages latest PHP performance improvements

---

## Installation & Setup

### How do I install LiveComponents?

LiveComponents is built into the framework - no additional installation needed.

**Verify installation**:
```bash
# Check if LiveComponent JavaScript is compiled
ls public/assets/js/livecomponent.js

# Verify base class exists
grep -r "abstract class LiveComponent" src/Framework/LiveComponents/
```

---

### What are the minimum requirements?

**Server Requirements**:
- PHP 8.4+ (8.5 recommended)
- Composer
- Custom PHP Framework installed

**Browser Requirements**:
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- ES2020 JavaScript support
- Fetch API
- EventSource (SSE)

---

### How do I enable HTTPS for development?

HTTPS is **required** for LiveComponents (CSRF protection, SSE).

Framework includes SSL certificates for local development:
```bash
# Start development server with HTTPS
make up
npm run dev

# Access via HTTPS only
https://localhost
```

---

## Component Development

### Can I use TypeScript with LiveComponents?

Yes! Add type definitions:

```typescript
// livecomponents.d.ts
declare global {
    interface Window {
        LiveComponent: {
            mount(element: HTMLElement): void;
            executeAction(
                componentId: string,
                action: string,
                params?: object
            ): Promise<void>;
            getComponent(componentId: string): Component | null;
        };
    }
}

export {};
```

---

### How do I pass initial data to a component?

```php
// In controller
use App\Framework\LiveComponents\LiveComponent;

public function dashboard(): ViewResult
{
    return new ViewResult('dashboard', [
        'statsWidget' => LiveComponent::mount(StatsWidget::class, [
            'user_id' => $currentUser->id,
            'date_range' => 'last_30_days'
        ])
    ]);
}

// In component
final class StatsWidget extends LiveComponent
{
    #[LiveProp]
    public string $userId;

    #[LiveProp]
    public string $dateRange;

    public function mount(array $initialData = []): void
    {
        $this->userId = $initialData['user_id'] ?? '';
        $this->dateRange = $initialData['date_range'] ?? 'today';

        $this->loadStats();
    }
}
```

---

### How do I access the current user in a component?

```php
use App\Framework\Auth\CurrentUser;

final class UserDashboard extends LiveComponent
{
    public function __construct(
        private readonly CurrentUser $currentUser
    ) {}

    public function mount(): void
    {
        $user = $this->currentUser->get();

        $this->userId = $user->id;
        $this->userName = $user->name;
    }
}
```

---

### Can I nest LiveComponents?

Yes, but with caveats:

```php
// Parent component
final class Dashboard extends LiveComponent
{
    public function render(): string
    {
        return $this->view('dashboard', [
            'statsWidget' => LiveComponent::mount(StatsWidget::class),
            'activityFeed' => LiveComponent::mount(ActivityFeed::class)
        ]);
    }
}
```

**Template**:
```html
<div data-component-id="{component_id}">
    <h1>Dashboard</h1>

    <!-- Nested component 1 -->
    {statsWidget}

    <!-- Nested component 2 -->
    {activityFeed}
</div>
```

**Limitations**:
- Each component has its own lifecycle
- Parent changes don't automatically update children
- Use component communication for coordination

---

## State Management

### What types can I use for LiveProp?

```php
// ✅ Supported types
#[LiveProp] public string $name;
#[LiveProp] public int $count;
#[LiveProp] public float $price;
#[LiveProp] public bool $active;
#[LiveProp] public array $items;

// ✅ Value Objects (with proper serialization)
#[LiveProp] public Email $email;
#[LiveProp] public Money $total;

// ❌ Not supported
#[LiveProp] public \DateTime $date;  // Use DateTimeImmutable or Timestamp VO
#[LiveProp] public UserRepository $repo;  // Use DI, not LiveProp
#[LiveProp] public callable $callback;  // Closures can't be serialized
```

---

### How do I handle large datasets?

**Use pagination**:
```php
final class ProductList extends LiveComponent
{
    #[LiveProp]
    public int $page = 1;

    #[LiveProp]
    public int $perPage = 50;

    private array $products = [];

    public function mount(): void
    {
        $this->loadPage();
    }

    #[LiveAction]
    #[Fragment('product-list')]
    public function loadPage(int $page = null): void
    {
        $this->page = $page ?? $this->page;

        // Only load current page
        $this->products = $this->productRepository->paginate(
            page: $this->page,
            perPage: $this->perPage
        );
    }
}
```

**Don't serialize large datasets**:
```php
// ❌ Bad - serializes entire dataset
#[LiveProp]
public array $allProducts = [];  // 10,000 products

// ✅ Good - only serialize IDs
#[LiveProp]
public array $productIds = [];

private array $products = [];  // Not serialized

public function hydrate(array $state): void
{
    parent::hydrate($state);

    // Reload products from IDs
    $this->products = $this->productRepository->findByIds($this->productIds);
}
```

---

### Can I use sessions/cookies in components?

Yes:

```php
use App\Framework\Http\Session;

final class PreferencesComponent extends LiveComponent
{
    public function __construct(
        private readonly Session $session
    ) {}

    #[LiveAction]
    public function savePreference(string $key, string $value): void
    {
        $this->session->set("preferences.{$key}", $value);
    }
}
```

---

## Performance

### How can I optimize component performance?

**1. Use Fragment Rendering**:
```php
#[LiveAction]
#[Fragment('search-results')]
public function search(): void
{
    // Only re-render search results fragment
}
```

**2. Enable Request Batching**:
```javascript
LiveComponent.configure({
    batchSize: 10,
    batchDebounce: 50
});
```

**3. Cache Expensive Operations**:
```php
use App\Framework\Cache\Attributes\Cached;

#[Cached(ttl: Duration::fromMinutes(5))]
public function getStats(): array
{
    // Cached for 5 minutes
    return $this->analyticsService->getStats();
}
```

**4. Use Optimistic UI**:
```php
#[LiveAction]
#[Optimistic(property: 'count', operation: 'increment')]
public function increment(): void
{
    $this->count++;
}
```

See [Performance Guide](performance-guide.md) for more strategies.

---

### What's the maximum number of components per page?

**Recommended**: <50 components per page for optimal performance

**Performance characteristics**:
- Each component: ~2MB memory (browser)
- 50 components: ~100MB total
- Network: Fragment updates minimize bandwidth

**For high component counts**:
- Use lazy loading
- Implement virtual scrolling
- Consider pagination

---

### How do I debug performance issues?

**Enable DevTools**:
```env
LIVECOMPONENT_DEVTOOLS_ENABLED=true
```

**Or via localStorage**:
```javascript
localStorage.setItem('livecomponent_devtools', 'true');
location.reload();
```

**Monitor metrics**:
- Performance tab: Flamegraphs, timeline, memory profiling
- Network tab: Request batching efficiency
- Action log: Execution times

---

## Security

### Is CSRF protection enabled by default?

Yes, CSRF protection is **automatic** for all LiveComponent requests.

**How it works**:
1. CSRF token in meta tag: `<meta name="csrf-token" content="...">`
2. Automatically included in all requests
3. Server validates token via `CsrfMiddleware`

**Disable for specific routes** (not recommended):
```php
#[Route(path: '/public-api', method: Method::POST)]
#[SkipCsrf]
public function publicEndpoint(): JsonResult
{
    // Public endpoint without CSRF
}
```

---

### How do I implement authorization?

```php
use App\Framework\LiveComponents\Attributes\Authorize;

#[LiveAction]
#[Authorize(roles: ['admin'])]
public function deleteUser(string $userId): void
{
    $this->userService->delete($userId);
}

#[LiveAction]
#[Authorize(permissions: ['posts.edit'])]
public function updatePost(): void
{
    // Only users with posts.edit permission
}
```

**Custom authorization**:
```php
#[LiveAction]
public function criticalAction(): void
{
    if (!$this->canPerformAction()) {
        throw new UnauthorizedException('Insufficient permissions');
    }

    // Perform action
}

private function canPerformAction(): bool
{
    return $this->currentUser->hasRole('admin')
        || $this->resource->ownedBy($this->currentUser->id);
}
```

---

### How do I prevent SQL injection?

Framework uses **parameterized queries** automatically:

```php
// ✅ Safe - framework handles parameterization
$users = $this->repository->findByEmail($this->email);

// ✅ Safe - query builder with bindings
$results = $this->db->query(
    'SELECT * FROM users WHERE email = ?',
    [$this->email]
);

// ❌ NEVER do this
$results = $this->db->query(
    "SELECT * FROM users WHERE email = '{$this->email}'"
);
```

**Additional protection**: WAF SQL injection layer blocks suspicious patterns.

---

## Deployment

### What do I need for production deployment?

**Required**:
- [x] PHP 8.4+ production environment
- [x] HTTPS enabled (required for CSRF/SSE)
- [x] CSRF protection enabled (`LIVECOMPONENT_CSRF_PROTECTION=true`)
- [x] Rate limiting configured
- [x] Compiled JavaScript assets (`npm run build`)

**Recommended**:
- [x] Redis for SSE connection pool
- [x] OPcache enabled (PHP 8.5 JIT)
- [x] CDN for static assets
- [x] Monitoring (performance metrics, error tracking)

See [Security Guide - Production Checklist](security-guide.md#production-deployment-checklist).

---

### Can I use LiveComponents with a CDN?

Yes:

```html
<!-- Compiled assets served from CDN -->
<script type="module" src="https://cdn.example.com/assets/js/livecomponent.min.js"></script>
```

**Configure in build**:
```javascript
// vite.config.js
export default defineConfig({
    base: 'https://cdn.example.com/assets/'
});
```

---

### How do I handle server errors in production?

**Server-side**:
```php
use App\Framework\ErrorHandling\ErrorHandler;

try {
    $result = $this->executeAction();
} catch (\Exception $e) {
    $this->errorHandler->log($e);

    // Return user-friendly error
    return new ActionResult(
        success: false,
        message: 'An error occurred. Please try again.',
        errors: $this->environment->isProduction()
            ? []
            : [$e->getMessage()]
    );
}
```

**Client-side**:
```javascript
window.addEventListener('livecomponent:error', (e) => {
    const { message, code } = e.detail;

    if (code === 'CSRF_TOKEN_EXPIRED') {
        LiveComponent.refreshCsrfToken();
    } else {
        showNotification(message, 'error');
    }
});
```

---

## Testing

### How do I test LiveComponents?

**Unit Tests (Pest)**:
```php
it('increments counter', function () {
    $component = new Counter();
    $component->mount();

    expect($component->count)->toBe(0);

    $component->increment();

    expect($component->count)->toBe(1);
});
```

**Integration Tests**:
```php
it('renders component with correct data', function () {
    $component = new UserProfile();
    $component->mount(['user_id' => '123']);

    $html = $component->render();

    expect($html)->toContain('data-component-id');
    expect($html)->toContain('User Profile');
});
```

**E2E Tests (Playwright)**:
```javascript
test('user can submit form', async ({ page }) => {
    await page.goto('https://localhost/form');

    await page.fill('[data-lc-model="name"]', 'John Doe');
    await page.click('[data-lc-action="submit"]');

    await expect(page.locator('.success-message')).toBeVisible();
});
```

---

## Troubleshooting

### Component not updating after action

**Check**:
1. Is `#[LiveProp]` attribute present?
2. Is property being modified in action?
3. Check browser console for JavaScript errors
4. Verify CSRF token is valid

**Debug**:
```javascript
// Get component state
const component = LiveComponent.getComponent('component-id');
console.log('Current state:', component.state);

// Monitor action execution
window.addEventListener('livecomponent:action-executed', (e) => {
    console.log('Action result:', e.detail);
});
```

---

### "CSRF token mismatch" error

**Causes**:
- Token expired (default: 2 hours)
- Session cleared
- Token not in meta tag

**Solutions**:
```html
<!-- Ensure CSRF meta tag exists -->
<meta name="csrf-token" content="{csrf_token}">
```

```javascript
// Refresh token
LiveComponent.refreshCsrfToken().then(() => {
    LiveComponent.retryLastAction();
});
```

---

### SSE connection not working

**Check**:
1. HTTPS enabled? (Required for SSE)
2. Port 443 accessible?
3. Firewall blocking SSE endpoint?

**Debug**:
```javascript
// Monitor SSE events
window.addEventListener('livecomponent:sse-connected', () => {
    console.log('SSE connected');
});

window.addEventListener('livecomponent:sse-error', (e) => {
    console.error('SSE error:', e.detail);
});
```

---

### High memory usage

**Causes**:
- Too many components (>100)
- Large serialized state
- Memory leaks in actions

**Solutions**:
1. **Reduce component count**: Use pagination/lazy loading
2. **Minimize state**: Don't serialize large datasets
3. **Clean up in unmount**:
```php
public function unmount(): void
{
    $this->largeDataset = [];
    gc_collect_cycles();
}
```

---

## Integration

### Can I use LiveComponents with Alpine.js?

Yes:

```html
<div
    data-component-id="{component_id}"
    x-data="{ expanded: false }"
>
    <!-- LiveComponent state -->
    <p>Count: {count}</p>
    <button data-lc-action="increment">Increment</button>

    <!-- Alpine.js state -->
    <button @click="expanded = !expanded">Toggle</button>
    <div x-show="expanded">
        Expandable content
    </div>
</div>
```

**Best practices**:
- Use LiveComponents for server state
- Use Alpine.js for client-only UI state

---

### Can I use LiveComponents with htmx?

They can coexist, but **don't mix** on the same element:

```html
<!-- ✅ Separate usage -->
<div data-component-id="lc-component">
    LiveComponent content
</div>

<div hx-get="/endpoint">
    htmx content
</div>

<!-- ❌ Don't mix on same element -->
<div data-component-id="..." hx-post="...">
    Conflict!
</div>
```

---

## Advanced

### Can I create custom directives?

Yes, extend the template processor:

```php
use App\Framework\Template\TemplateProcessor;

final readonly class CustomDirectiveProcessor implements TemplateProcessor
{
    public function process(string $template, array $data): string
    {
        // Process custom directive: <custom-tag>
        return preg_replace_callback(
            '/<custom-tag>(.+?)<\/custom-tag>/',
            fn($matches) => $this->processCustomTag($matches[1]),
            $template
        );
    }
}
```

Register via attribute discovery:
```php
#[TemplateProcessor(priority: 100)]
final readonly class CustomDirectiveProcessor { ... }
```

---

### How do I implement server-side rendering (SSR)?

LiveComponents **is** server-side rendering - components render on the server and stream HTML to the client.

For **initial page load SEO**:
```php
// Controller returns fully rendered HTML
public function page(): ViewResult
{
    return new ViewResult('page', [
        'component' => LiveComponent::mount(InteractiveComponent::class)
    ]);
}
```

HTML is immediately crawlable by search engines.

---

### Can I use WebSockets instead of SSE?

Framework uses SSE by design because:
- Simpler than WebSockets for server-to-client
- Automatic reconnection
- HTTP/2 multiplexing
- Lower overhead for one-way updates

For **two-way real-time**: Consider GraphQL subscriptions or framework's WebSocket support (separate from LiveComponents).

---

## Getting Help

### Where can I find more examples?

- **GitHub**: Example components in `src/Application/LiveComponents/`
- **Tests**: E2E tests in `tests/e2e/livecomponents-*.spec.js`
- **Documentation**: [Getting Started](01-getting-started.md), [Advanced Features](advanced-features.md)

---

### How do I report bugs?

**Security issues**: security@example.com

**Bug reports**: GitHub Issues with:
- Component code
- Expected vs actual behavior
- Browser console errors
- Steps to reproduce

---

### How do I request features?

Open GitHub Discussion with:
- Use case description
- Proposed API/syntax
- Alternative solutions considered

---

**Next**: [Troubleshooting Guide](troubleshooting.md) →
