PHPackages                             tito10047/ux-sdc - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. tito10047/ux-sdc

ActiveSymfony-bundle[Templating &amp; Views](/categories/templating)

tito10047/ux-sdc
================

A performance-optimized SDC implementation for Symfony UX components with automatic discovery and static metadata registry.

0.3.1(3mo ago)122061[2 issues](https://github.com/tito10047/ux-sdc/issues)MITPHPPHP &gt;=8.1CI passing

Since Jan 19Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/tito10047/ux-sdc)[ Packagist](https://packagist.org/packages/tito10047/ux-sdc)[ RSS](/packages/tito10047-ux-sdc/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (3)Dependencies (30)Versions (12)Used By (0)

UX SDC Bundle
=============

[](#ux-sdc-bundle)

[![Build Status](https://camo.githubusercontent.com/e28684f0b4774fbd3976ef80cdef4130a66e9fa2ba055a5c1e936083d5cbe594/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7469746f31303034372f75782d7364632f63692e796d6c3f6272616e63683d6d61696e)](https://github.com/tito10047/ux-sdc/actions)[![PHP-CS-Fixer](https://camo.githubusercontent.com/7b461d1d3392a45dd2f1a65abfb6d63c29ec8b97e9bd85c9e833a2e85f81ad36/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7469746f31303034372f75782d7364632f63692e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65)](https://github.com/tito10047/ux-sdc/actions/workflows/ci.yml)[![PHPStan](https://camo.githubusercontent.com/0aa217559bfa29336c7223ab33243e6aba2c72eab6926ef31e1bafd0ddb5ac41/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7469746f31303034372f75782d7364632f63692e796d6c3f6272616e63683d6d61696e266c6162656c3d7068707374616e)](https://github.com/tito10047/ux-sdc/actions/workflows/ci.yml)[![Latest Stable Version](https://camo.githubusercontent.com/2b6f4671f9119d545773d3ffaf92a9fc7d644b13b856fc303c8fd11a6c8c2168/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7469746f31303034372f75782d7364632e737667)](https://packagist.org/packages/tito10047/ux-sdc)[![License](https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667)](LICENSE)[![PHP Version](https://camo.githubusercontent.com/3d4de2d3fd1110e24714a0182fb51b620fbf3310302503a7ea95f639828a4bce/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344253230382e312d3838393262662e737667)](https://php.net)[![Symfony Version](https://camo.githubusercontent.com/d667415dd34ff31d986621444fb17659993b42fd9bd49c64bbb45f09de2c0eaa/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53796d666f6e792d253345253344253230362e342d626c61636b3f6c6f676f3d73796d666f6e79)](https://symfony.com/)[![Symfony Style](https://camo.githubusercontent.com/40e2296e85dbcd539c9773dad57ecb272159ac077b129f0a651fc2291c8b5d18/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f64652532307374796c652d73796d666f6e792d626c61636b3f6c6f676f3d73796d666f6e79)](https://symfony.com/)

A Symfony bundle that implements the **Single Directory Component (SDC)** methodology for Symfony UX. It bridges the gap between **AssetMapper** and **Twig Components** by providing a fully automated, convention-over-configuration workflow.

Real-world Usage &amp; Developer Experience
-------------------------------------------

[](#real-world-usage--developer-experience)

This bundle is actively used in production. Here are some real-world examples:

- [formalitka.mostka.sk](https://formalitka.mostka.sk/)
- [mostka.sk](https://mostka.sk/)
- [ycon.cc](https://ycon.cc)

### Developer Evaluation

[](#developer-evaluation)

Working with UX SDC provides an excellent developer experience. A recommended project structure organizes the code into distinct functional areas:

- **UI**: Generic interface elements (e.g., `Button`, `Spinner`, `Tabs`).
- **Layout**: Structural page elements (e.g., `TopBar`, `Footer`, `FlashMessage`).
- **Component**: Reusable feature blocks.
- **Page**: Complete page components (e.g., `Homepage`, `AboutUs`).

A significant advantage of this architecture is the ability to place Symfony controllers directly within the page-level SDC component directory (e.g., `HomepageAction.php`). The controller merely handles routing and renders the base layout, while all business and presentation logic remains encapsulated in isolated SDC components.

Because the code is highly granular and strictly structured, AI tools work exceptionally well within this architecture, easily generating robust and creative design implementations.

The Concept
-----------

[](#the-concept)

This bundle is inspired by the architectural challenges discussed in **["A Better Architecture for Your Symfony UX Twig Components"](https://hugo.alliau.me/blog/posts/a-better-architecture-for-your-symfony-ux-twig-components)** by **Hugo Alliaume**.

Instead of scattering your component files across `src/`, `templates/`, and `assets/`, this bundle allows you to keep everything in one place.

Quick Example
-------------

[](#quick-example)

Just create a directory for your component. Everything else is handled automatically.

```
ux_sdc:
    ux_components_dir: '%kernel.project_dir%/src_component/Component'
    component_namespace: 'App\Component'
```

```
{
   "autoload": {
      "psr-4": {
         "App\\": "src/",
         "App\\Component\\": "src_component/"
      }
   }
}
```

```
src_component/
└── Component/
    └── Alert/
        ├── Alert.php           # Auto-registered logic
        ├── Alert.html.twig     # Auto-mapped template
        ├── Alert.css           # Auto-injected styles
        └── alert_controller.js # Auto-mapped Stimulus controller

```

```
namespace App\Component\Alert;

use Tito10047\UX\Sdc\Attribute\AsSdcComponent;
use Tito10047\UX\Sdc\Twig\ComponentNamespaceInterface;
use Tito10047\UX\Sdc\Twig\Stimulus;

#[AsSdcComponent] // No need to define names, templates, or assets. It's all inferred!
class Alert
{
    use Stimulus;

    public string $type = 'info';
    public string $message;
}
```

In the `Alert.html.twig` template, you can then use the automatically generated stimulus controller name:

```

    {{ message }}

```

Tip

**Zero Configuration Magic:** The bundle automatically registers the component, maps the template based on its location, and injects the required CSS/JS into your HTML header only when the component is rendered.

---

Key Features
------------

[](#key-features)

- **Automatic Registration:** Every class marked with `#[AsSdcComponent]` is automatically discovered and registered.
- **Smart Template Mapping:** Forget `template: 'components/Alert.html.twig'`. If the template is in the same folder as your class, it's found automatically.
- **Asset Orchestration:** CSS and JS files in your component folder are collected during rendering and injected into the ``.
- **Automatic Stimulus Controllers:** By using the `Stimulus` trait and `ComponentNamespaceInterface`, your component automatically gets a `controller` variable representing its Stimulus controller name based on its namespace.
- **Support for Live Components:** Works seamlessly with `#[AsLiveComponent]` and `#[Asset]` attributes for modern, reactive interfaces.
- **No "Phantom" Controllers:** Load component-specific CSS via **AssetMapper** without the need for empty Stimulus controllers just for imports.
- **Performance First:** \* **Compiler Pass:** All file discovery happens at build time. Zero reflection in production.
- **Response Post-processing:** Assets are injected at the end of the request.
- **HTTP Preload:** Automatic generation of `Link` headers to trigger early browser downloads.
- **Maker Command:** Quickly generate new SDC components with all necessary files using `php bin/console make:sdc-component`.

---

Installation &amp; Setup
------------------------

[](#installation--setup)

1. **Install via Composer:**

```
composer require tito10047/ux-sdc
```

2. **Register the bundle** (if not done automatically by Symfony Flex):

```
// config/bundles.php
return [
    // ...
    Tito10047\UX\Sdc\SdcBundle::class => ['all' => true],
];
```

3. **Configure the bundle:**Create a configuration files:

```
/*composer.json*/
{
    "autoload": {
        "psr-4": {
            "App\\": "src/",
            "App\\Component\\": "src_component/"
        }
    }
}
```

```
#config/packages/stimulus.yaml
stimulus:
    controller_paths:
        - '%kernel.project_dir%/assets/controllers'
```

```
#config/packages/ux_sdc.yaml
ux_sdc:
    ux_components_dir: '%kernel.project_dir%/src_component'
    component_namespace: 'App\Component'
    stimulus:
        enabled: true
```

4. **Add the placeholder to your base template:**Place this in your `` to define where the collected assets should be injected:

```

    {# ... #}
    {{ render_component_assets() }}

```

Usage
-----

[](#usage)

### Live Components

[](#live-components)

The bundle also supports **Live Components**. It handles both initial rendering and AJAX updates automatically.

#### How it works with Live Components:

[](#how-it-works-with-live-components)

1. **Initial Render:** Assets are collected and injected into the `` just like with regular Twig components.
2. **AJAX Updates:** When a Live Component is updated via AJAX, the bundle identifies the request and sends asset paths via HTTP headers (`X-SDC-Assets-CSS` and `X-SDC-Assets-JS`) to the browser.
3. **Dynamic Loading:** The bundle includes a Stimulus controller that listens for Live Component events and dynamically injects any missing assets into the `` of the document.

#### Enabling Dynamic Asset Loading

[](#enabling-dynamic-asset-loading)

To enable dynamic loading of assets during Live Component updates, you must add the bundle's Stimulus controller to your base template (ideally on the `` element):

```

    {# ... #}

```

#### Usage with Live Components:

[](#usage-with-live-components)

To get full support (including the `controller` variable in Twig), your Live Component should implement `ComponentNamespaceInterface` and use the `Stimulus` trait:

```
namespace App\Component\Search;

use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\DefaultActionTrait;
use Tito10047\UX\Sdc\Attribute\Asset;
use Tito10047\UX\Sdc\Twig\ComponentNamespaceInterface;
use Tito10047\UX\Sdc\Twig\Stimulus;

#[AsLiveComponent]
#[Asset] // Automatically discovers Search.css and Search_controller.js
class Search implements ComponentNamespaceInterface
{
    use DefaultActionTrait;
    use Stimulus;

    // ... logic
}
```

In your `Search.html.twig`:

```

```

### Generating Components

[](#generating-components)

You can use the built-in maker command to create a new component:

`php bin/console make:sdc-component UI:Alert`

This will create:

- `src/Component/UI/Alert/Alert.php` (PHP logic)
- `src/Component/UI/Alert/Alert.html.twig` (Twig template)
- `src/Component/UI/Alert/Alert.css` (CSS styles)
- (Optional) `src/Component/UI/Alert/Alert_controller.js` (Stimulus controller)

The maker supports options and interactive mode:

- `--stimulus` to force generating a Stimulus controller (non-interactive mode will not create it unless explicitly set)
- `--action` to generate a minimal controller action and a wrapper Twig template for the component

Example with an action:

```
php bin/console make:sdc-component Page:Homepage --action
```

This will additionally create:

- `src/Component/Page/Homepage/HomepageAction.php` (Symfony controller)
- `src/Component/Page/Homepage/HomepageAction.html.twig` (page template rendering the component)

Generated files contents:

```
// src/Component/Page/Homepage/HomepageAction.php
namespace App\Component\Page\Homepage;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Attribute\Route;

class HomepageAction extends AbstractController
{
    #[Route('/en', name: 'app.homepage')]
    public function index(): \Symfony\Component\HttpFoundation\Response
    {
        return $this->render('Page/Homepage/HomepageAction.html.twig');
    }
}
```

```
{# src/Component/Page/Homepage/HomepageAction.html.twig #}
{% extends 'layout.html.twig' %}

{% block content %}

{% endblock %}
```

In interactive mode, you will be asked:

- for the component name (supports `:` or `/` separators, e.g. `UI:Alert` or `UI/Alert`)
- whether to generate a Stimulus controller
- whether to generate an Action class and template

---

How It Works
------------

[](#how-it-works)

1. **Discovery:** During container compilation, the bundle scans your component directory. It maps PHP classes to their neighboring `.twig`, `.css`, and `.js` files.
2. **Rendering:** When a component is used on a page, the bundle's listener intercepts the `PreCreateForRenderEvent` and logs its required assets.
3. **Injection:** The `AssetResponseListener` replaces your Twig placeholder with the actual `` and `` tags and adds HTTP preload headers to the response.

Why SDC?
--------

[](#why-sdc)

1. **Maintainability:** Everything related to a UI element is in one folder.
2. **Developer Experience:** No more jumping between four different directories to change one button's color.
3. **Efficiency:** Only the CSS/JS needed for the current page is sent to the user.

Benchmarks
----------

[](#benchmarks)

This bundle is designed for high performance with minimal overhead. We've conducted extensive benchmarks comparing the SDC approach with the classic Twig component approach.

### Performance Summary (500 Components)

[](#performance-summary-500-components)

ScenarioClassic ApproachSDC ApproachDifference**Warmup (Dev/Debug)**809.8ms782.0ms-27.8ms**Warmup (Prod)**583.1ms586.2ms+3.1ms**Render (Prod Runtime)**26.5ms31.6ms+5.1ms**Render (Dev Runtime - 500 unique)**26.5ms88.4ms+61.9ms**Render (Dev Runtime - 10 unique repeated)**26.5ms58.0ms+31.5ms### Key Findings

[](#key-findings)

- **Developer Experience (Dev Runtime):** In `dev` mode, there is a measurable overhead for **unique** components (~84µs per component) due to runtime autodiscovery. This allows developers to add CSS/JS/Twig files and see changes instantly without clearing the cache.
- **Caching:** Thanks to internal metadata caching, repeated rendering of the same component in `dev` is significantly faster as the file system is only scanned once per unique component class per request.
- **Production Performance:** In `prod` mode, the overhead for rendering 500 unique components is practically zero, as all metadata is pre-generated during container compilation.
- **Warmup:** The SDC approach slightly increases container compilation time in `prod` (~15ms for 500 unique components) but remains very efficient.
- **Memory Usage:** The SDC approach requires approximately **8MB** more memory during container compilation for 500 components, which is well within acceptable limits for modern applications.

For detailed results and methodology, see the [Full Benchmark Report](benchmark.md).

License
-------

[](#license)

MIT

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance84

Actively maintained with recent releases

Popularity22

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity40

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~9 days

Total

7

Last Release

95d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/11459248?v=4)[Jozef Môstka](/maintainers/tito10047)[@tito10047](https://github.com/tito10047)

---

Top Contributors

[![tito10047](https://avatars.githubusercontent.com/u/11459248?v=4)](https://github.com/tito10047 "tito10047 (72 commits)")

---

Tags

sdcsymfonytwigux-componentssymfonybundlecsssymfony-uxSymfony Bundlesdc

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/tito10047-ux-sdc/health.svg)

```
[![Health](https://phpackages.com/badges/tito10047-ux-sdc/health.svg)](https://phpackages.com/packages/tito10047-ux-sdc)
```

###  Alternatives

[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k17.5M376](/packages/easycorp-easyadmin-bundle)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.1k16.8k](/packages/prestashop-prestashop)[web-auth/webauthn-framework

FIDO2/Webauthn library for PHP and Symfony Bundle.

51390.8k2](/packages/web-auth-webauthn-framework)[spomky-labs/pwa-bundle

Progressive Web App Manifest Generator Bundle for Symfony.

6548.7k1](/packages/spomky-labs-pwa-bundle)[forumify/forumify-platform

122.0k12](/packages/forumify-forumify-platform)[web-auth/webauthn-symfony-bundle

FIDO2/Webauthn Security Bundle For Symfony

65474.5k9](/packages/web-auth-webauthn-symfony-bundle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
