stimulus
Stimulus JS framework for Symfony UX -- client-side behavior via HTML data attributes, zero server round-trips. Use when creating controllers for DOM…
Symfony UX LiveComponent for reactive server-rendered UI -- components that re-render via AJAX on user interaction, zero JavaScript required. Use when building live search, real-time filtering, dynamic forms, inline validation, dependent selects, auto-save, polling,
$ npx -y skills add smnandre/symfony-ux-skills --skill live-component --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/live-componentContext preview
The summary Claude sees to decide when to auto-load this skill.
Symfony UX LiveComponent for reactive server-rendered UI -- components that re-render via AJAX on user interaction, zero JavaScript required. Use when building live search, real-time filtering, dynamic forms, inline validation, dependent selects, auto-save, polling,
name: live-component description: 'Symfony UX LiveComponent for reactive server-rendered UI -- components that re-render via AJAX on user interaction, zero JavaScript required. Use when building live search, real-time filtering, dynamic forms, inline validation, dependent selects, auto-save, polling, deferred/lazy rendering, or any UI that updates itself based on user input. Code triggers: AsLiveComponent, LiveProp, LiveAction, data-model, data-loading, data-live-action-url, ComponentWithFormTrait, LiveListener, emit, defer, lazy, polling. Also trigger when the user asks "how to build a search that filters as I type", "how to validate a form in real-time", "how to make a reactive component in PHP", "how to build dependent selects", "how to defer component rendering", "how to communicate between components via emit", "how to bind a form to a LiveComponent". Do NOT trigger for static reusable UI without reactivity (use twig-component), pure client-side JS behavior (use stimulus), or page-level navigation (use turbo).' license: MIT metadata: author: Simon Andre email: smn.andre@gmail.com url: https://smnandre.dev version: "1.2.0"
TwigComponents that re-render dynamically via AJAX. Build reactive UIs in PHP + Twig with zero JavaScript. Every user interaction triggers a server round-trip that re-renders the component and morphs the DOM.
Use LiveComponent when a component's output depends on user interaction -- search results that update as you type, forms with real-time validation, filters that refine a list, anything where the UI needs to change based on user input and that change requires server-side data or logic.
If the component never re-renders after initial load, use TwigComponent instead (less overhead, no AJAX). If the interaction is purely client-side (toggle, animation), use Stimulus instead.
composer require symfony/ux-live-component
#[AsLiveComponent] Make component live (re-renderable via AJAX)
#[LiveProp] State that persists across re-renders
#[LiveProp(writable: true)] State that the frontend can modify
#[LiveAction] Server method callable from frontend
data-model="prop" Two-way bind input to LiveProp
data-action="live#action" Call LiveAction on event
data-loading="..." Show/hide/style elements during AJAX
{{ attributes }} REQUIRED on root element (wires the Stimulus controller)// src/Twig/Components/Counter.php
namespace App\Twig\Components;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\Attribute\LiveAction;
use Symfony\UX\LiveComponent\DefaultActionTrait;
#[AsLiveComponent]
final class Counter
{
use DefaultActionTrait;
#[LiveProp]
public int $count = 0;
#[LiveAction]
public function increment(): void
{
$this->count++;
}
#[LiveAction]
public function decrement(): void
{
$this->count--;
}
}{# templates/components/Counter.html.twig #}
<div {{ attributes }}>
<button data-action="live#action" data-live-action-param="decrement">-</button>
<span>{{ count }}</span>
<button data-action="live#action" data-live-action-param="increment">+</button>
</div>**Critical:** The root element must render `{{ attributes }}`. This injects the Stimulus `data-controller="live"` attribute that makes the whole system work. Without it, nothing re-renders.
State that persists between AJAX re-renders. Props are serialized to the frontend and sent back on every request.
#[LiveProp] public string $query = ''; #[LiveProp] public int $page = 1; #[LiveProp] public ?User $user = null; // Entities auto-hydrate by ID
Only writable props can be modified from the frontend via `data-model`:
#[LiveProp(writable: true)] public string $search = ''; // Writable with specific fields for objects #[LiveProp(writable: ['email', 'name'])] public User $user;
Sync a prop to a URL query parameter -- enables bookmarkable/shareable state:
#[LiveProp(writable: true, url: true)] public string $query = ''; // URL becomes: ?query=search+term // Custom parameter name use Symfony\UX\LiveComponent\Metadata\UrlMapping; #[LiveProp(writable: true, url: new UrlMapping(as: 'q'))] public string $query = ''; // URL becomes: ?q=search+term
Doctrine entities auto-hydrate by ID. For custom types:
#[LiveProp(hydrateWith: 'hydrateStatus', dehydrateWith: 'dehydrateStatus')]
public Status $status;
public function hydrateStatus(string $value): Status
{
return Status::from($value);
}
public function dehydrateStatus(Status $status): string
{
return $status->value;
}Bind inputs to writable LiveProps. When the input changes, the component re-renders with the new value.
{# Re-render on change (default) #}
<input type="text" data-model="search">
{# Debounced -- wait 300ms after last keystroke #}
<input type="text" data-model="debounce(300)|search">
{# Only update on blur #}
<input type="text" data-model="on(blur)|search">
{# Update model but don't re-render yet #}
<input type="text" data-model="norender|search">
{# Checkbox, radio, select #}
<input type="checkbox" data-model="enabled">
<select data-model="category">
<option value="1">Category 1</option>
</select>{# Only re-render when input meets criteria #}
<input data-model="minlength(3)|search">
<input data-model="maxlength(100)|bio">
<input data-model="min(0)|quantity">
<input data-model="max(999)|price">Server methods callable from the frontend:
#[LiveAction]
public function save(): void
{
// Called via data-AI agent skills for the Symfony UX frontend stack -- Stimulus, Turbo, TwigComponent, LiveComponent, UX Icons and UX Map. By Simon Andre
Repo: smnandre/symfony-ux-skills
Stimulus JS framework for Symfony UX -- client-side behavior via HTML data attributes, zero server round-trips. Use when creating controllers for DOM…
Symfony UX frontend stack -- decision tree and orchestrator for choosing between Stimulus, Turbo, TwigComponent, LiveComponent, UX Icons, and UX Map. Use when…
Hotwire Turbo for Symfony UX -- SPA-like speed with zero JavaScript. Covers Drive (navigation), Frames (partial page sections), and Streams (multi-target…
Symfony UX TwigComponent for reusable UI building blocks -- server-rendered components with PHP classes and Twig templates. Use when creating buttons, cards,…
Symfony UX Icons for rendering SVG icons in Twig templates. Supports 200,000+ Iconify icons (Lucide, Heroicons, Tabler, Material Design, etc.), local SVG…