live-component
Symfony UX LiveComponent for reactive server-rendered UI -- components that re-render via AJAX on user interaction, zero JavaScript required. Use when building…
Hotwire Turbo for Symfony UX -- SPA-like speed with zero JavaScript. Covers Drive (navigation), Frames (partial page sections), and Streams (multi-target updates). Use when building ajax navigation, lazy-loaded sections, inline editing, pagination without reload, modals from the
$ npx -y skills add smnandre/symfony-ux-skills --skill turbo --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/turboContext preview
The summary Claude sees to decide when to auto-load this skill.
Hotwire Turbo for Symfony UX -- SPA-like speed with zero JavaScript. Covers Drive (navigation), Frames (partial page sections), and Streams (multi-target updates). Use when building ajax navigation, lazy-loaded sections, inline editing, pagination without reload, modals from the
name: turbo description: 'Hotwire Turbo for Symfony UX -- SPA-like speed with zero JavaScript. Covers Drive (navigation), Frames (partial page sections), and Streams (multi-target updates). Use when building ajax navigation, lazy-loaded sections, inline editing, pagination without reload, modals from the server, flash messages via streams, or real-time updates via Mercure/SSE. Code triggers: turbo-frame, turbo-stream, data-turbo-frame, data-turbo, data-turbo-action, turbo-stream-source, TurboStreamResponse, <twig:Turbo:Frame>, <twig:Turbo:Stream:Append>, <twig:Turbo:Stream:Replace>, turbo:before-fetch-request. Also trigger when the user asks "how to update part of the page without reload", "how to make navigation feel like SPA", "how to lazy-load a section", "how to do inline editing", "how to push real-time updates from server", "how to use Mercure with Turbo". Do NOT trigger for client-side JS behavior (use stimulus), server-rendered reactive components (use live-component), or reusable static UI (use twig-component).' license: MIT metadata: author: Simon Andre email: smn.andre@gmail.com url: https://smnandre.dev version: "1.2.0"
Hotwire Turbo provides SPA-like speed with server-rendered HTML. No JavaScript to write. Three components work together:
Need to update the page? +-- Full page navigation -> Turbo Drive (automatic, already active) +-- Single section from user click -> Turbo Frame +-- Multiple sections from action -> Turbo Stream (HTTP response) +-- Real-time from server/others -> Turbo Stream (Mercure / SSE)
composer require symfony/ux-turbo
That's it. Turbo Drive is active immediately -- all links and forms become AJAX.
Automatic SPA-like navigation. Every `<a>` click and `<form>` submit is intercepted, fetched via AJAX, and the `<body>` is swapped. The browser URL and history update normally.
<!-- Disable on link/form -->
<a href="/external" data-turbo="false">External Link</a>
<!-- Disable for entire section -->
<div data-turbo="false">
<a href="/normal">Normal link (no Turbo)</a>
</div><!-- Replace history instead of push --> <a href="/page" data-turbo-action="replace">Replace History</a> <!-- Force full reload when asset changes --> <link rel="stylesheet" href="/app.css" data-turbo-track="reload"> <script src="/app.js" data-turbo-track="reload"></script>
Scope navigation to a section of the page. Links and forms inside a frame update only that frame's content. The rest of the page stays untouched.
<!-- Page with frame -->
<turbo-frame id="messages">
<h2>Messages</h2>
<a href="/messages/1">View Message 1</a> <!-- Updates only this frame -->
</turbo-frame>
<!-- /messages/1 response must contain a matching frame ID -->
<turbo-frame id="messages">
<h2>Message 1</h2>
<p>Content here...</p>
<a href="/messages">Back to list</a>
</turbo-frame>The server response is a full HTML page, but Turbo extracts only the matching `<turbo-frame>` and swaps it in.
Load frame content asynchronously after the page renders:
<turbo-frame id="notifications" src="/notifications" loading="lazy">
<p>Loading...</p>
</turbo-frame>A link inside one frame can update a different frame:
<turbo-frame id="sidebar">
<a href="/item/1" data-turbo-frame="main-content">View Item</a>
</turbo-frame>
<turbo-frame id="main-content">
<!-- Content replaced here -->
</turbo-frame>Navigate the entire page from within a frame:
<turbo-frame id="modal">
<a href="/dashboard" data-turbo-frame="_top">Go to Dashboard</a>
</turbo-frame>Forms inside frames submit and update within that frame:
<turbo-frame id="search-results">
<form action="/search" method="get">
<input type="search" name="q">
<button>Search</button>
</form>
<ul>
{% for item in results %}
<li>{{ item.name }}</li>
{% endfor %}
</ul>
</turbo-frame>Update the browser URL when a frame navigates (useful for bookmarkable state):
<turbo-frame id="products" data-turbo-action="advance">
<!-- Browser URL updates when this frame navigates -->
</turbo-frame>Update multiple DOM elements from a single server response. Eight actions available (`append`, `prepend`, `replace`, `update`, `remove`, `before`, `after`, `refresh`), each targeting elements by ID or CSS selector.
<turbo-stream action="append" target="messages">
<template><div id="msg_1">New message</div></template>
</turbo-stream>
<turbo-stream action="prepend" target="messages">
<template><div id="msg_0">First!</div></template>
</turbo-stream>
<turbo-stream action="replace" target="notification">
<template><div id="notification">Updated!</div></template>
</turbo-stream>
<turbo-stream action="update" target="counter">
<template>42</template>
</turbo-stream>
<turbo-stream action="remove" target="msg_5"></turbo-stream>
<turbo-stream action="before" target="msg_3">
<template><div id="msg_2">Inserted before</div></template>
</turbo-stream>
<turbo-stream action="after" target="msg_3">
<template><div id="msg_4">Inserted after</div></template>
</turbo-stream>
<turbo-stream action="refresh"></turbo-stream>`replace` and `update` support an optional `method="morph"` attribute for smooth DOM morphing instead of full replacement:
<turbo-stream action="replace" method="morph" target="
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
Symfony UX LiveComponent for reactive server-rendered UI -- components that re-render via AJAX on user interaction, zero JavaScript required. Use when building…
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…
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…