wexample / symfony-design-system
Design system assets for Symfony
Package info
github.com/wexample/symfony-design-system
Language:Twig
pkg:composer/wexample/symfony-design-system
Requires
- php: >=8.2
- wexample/symfony-loader: >=0.1.0
This package is auto-updated.
Last update: 2026-06-13 06:17:37 UTC
README
Version: 3.0.3
Design system assets for Symfony
Table of Contents
- Suite Integration
- Dependencies
- Versioning
- License
- Suite Integration
- Suite Signature
- Introduction
- Migration Notes
Integration in the Suite
This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
Related Packages
The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
Visit the Wexample Suite documentation for the complete package ecosystem.
Dependencies
- php: >=8.2
- wexample/symfony-loader: >=0.1.0
Versioning & Compatibility Policy
Wexample packages follow Semantic Versioning (SemVer):
- MAJOR: Breaking changes
- MINOR: New features, backward compatible
- PATCH: Bug fixes, backward compatible
We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Free to use in both personal and commercial projects.
Integration in the Suite
This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
Related Packages
The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
Visit the Wexample Suite documentation for the complete package ecosystem.
About us
Wexample stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.
This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.
Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.
Installation
PHP dependencies
Add to composer.json and run composer install:
"wexample/symfony-design-system": "*", "wexample/symfony-loader": "*", "wexample/symfony-routing": "*"
Register bundles in config/bundles.php:
Wexample\SymfonyDesignSystem\WexampleSymfonyDesignSystemBundle::class => ['all' => true], Wexample\SymfonyLoader\WexampleSymfonyLoaderBundle::class => ['all' => true], Wexample\SymfonyRouting\WexampleSymfonyRoutingBundle::class => ['all' => true], Wexample\SymfonyTranslations\WexampleSymfonyTranslationsBundle::class => ['all' => true],
Loader configuration
Create config/packages/wexample_symfony_loader.yaml:
wexample_symfony_loader: front_paths: front: '%kernel.project_dir%/front/' WexampleSymfonyDesignSystemBundle: '%kernel.project_dir%/front/' default_color_scheme: light # or dark
Both front and WexampleSymfonyDesignSystemBundle must point to the app's front/ directory so that app templates override DS bundle defaults and translations are scanned correctly.
Routing
Create config/routes/symfony_routing.yaml:
symfony_routing: resource: '@WexampleSymfonyRoutingBundle/Resources/config/routes.yaml'
Create config/routes/symfony_loader.yaml:
symfony_loader: resource: '@WexampleSymfonyLoaderBundle/Resources/config/routes.yaml'
Services
In config/services.yaml, declare the app home route parameter used by the ds_home_url() Twig function:
parameters: wexample_ds_app_home_route: 'your_home_route_name'
JS dependencies
In package.json, add (in addition to the standard encore/webpack stack):
"@wexample/js-api": "*", "@wexample/js-app": "*", "@wexample/js-helpers": "*", "@wexample/symfony-api": "file:vendor/wexample/symfony-api/assets", "@wexample/symfony-design-system": "file:vendor/wexample/symfony-design-system/assets", "@wexample/symfony-loader": "file:vendor/wexample/symfony-loader/assets", "@emoji-mart/data": "^1.2.1", "@fortawesome/free-brands-svg-icons": "*", "@fortawesome/free-solid-svg-icons": "*", "ajv": "*", "emoji-mart": "*", "fos-router": "file:vendor/friendsofsymfony/jsrouting-bundle/Resources", "glob": "*", "prismjs": "*", "vue": "^3", "vue-loader": "*", "webpack-virtual-modules": "*"
Webpack config
In webpack.config.mjs, use buildEncoreConfig from the loader. If the Node container does not have PHP available, bypass the PHP build hooks:
import { buildEncoreConfig } from './vendor/wexample/symfony-loader/src/Resources/js/webpack/encore.manifest.js'; import { createRequire } from 'node:module'; const require = createRequire(import.meta.url); const FosRouting = require('./vendor/friendsofsymfony/jsrouting-bundle/Resources/webpack/FosRouting'); const config = buildEncoreConfig({ clearCache: false, generateEncoreManifest: false, dumpFosRoutes: false, }); // Replace FosRouting plugin to skip PHP compilation hooks const fosIdx = config.plugins.findIndex(p => p.constructor?.name === 'FosRouting'); if (fosIdx !== -1) { config.plugins.splice(fosIdx, 1, new FosRouting({}, false)); } export default config;
Pre-generate the PHP artifacts from the PHP container before running webpack (see watch script below).
tsconfig.json
{
"ts-node": { "ignore": ["/node_modules/(?!@wexample/)"] },
"compilerOptions": {
"target": "ES6",
"module": "ESNext",
"moduleResolution": "bundler",
"baseUrl": ".",
"paths": {
"@front/*": ["./front/*"],
"@WexampleSymfonyDesignSystemBundle/*": ["./front/*"],
"@wexample/symfony-api/*": ["./vendor/wexample/symfony-api/assets/*"],
"@wexample/symfony-design-system/*": ["./vendor/wexample/symfony-design-system/assets/*"],
"@wexample/symfony-loader/*": ["./vendor/wexample/symfony-loader/assets/*"]
}
}
}
The ts-node.ignore pattern allows ts-node to process @wexample TypeScript packages during webpack config loading.
Note:
tsconfig.jsonis partially overwritten byphp bin/console loader:generate-encore-manifest. Only thets-nodeblock and manually added path aliases survive. Run the command first, then add custom paths.
Watch script (split PHP/Node containers)
If PHP and Node run in separate containers, create a host-side orchestration script (e.g. .wex/bash/watch.sh):
docker exec -i "$CONTAINER_FRANKENPHP" php bin/console cache:clear --no-warmup docker exec -i "$CONTAINER_FRANKENPHP" php bin/console loader:generate-encore-manifest docker exec -i "$CONTAINER_FRANKENPHP" php bin/console fos:js-routing:dump --target=var/cache/fosRoutes.json --format=json docker exec -it "$CONTAINER_NODE" /bin/sh -c "cd $APP_DIR && yarn watch"
The package.json watch script is the direct encore command; the shell script is the host-level orchestration.
Private layout
Create front/layouts/private/layout.html.twig extending the DS dashboard layout:
{%- extends '@WexampleSymfonyDesignSystemBundle/layouts/dashboard/layout.html.twig' -%}
{%- block layout_config -%}
{{- render_pass.layoutRenderNode.setDefaultView(_self) -}}
{{ parent() }}
{%- endblock -%}
Add the sidebar menu and page structure blocks as needed. See the DS bundle's layouts/design_system/layout.html.twig for the menu pattern using menu_get_routes_from_controller_namespace.
Create front/layouts/private/layout.ts to instantiate the JS app:
import App from '@wexample/symfony-loader/js/Class/App'; import AppService from '@wexample/symfony-loader/js/Class/AppService'; import VueService from '@wexample/symfony-loader/js/Services/VueService'; import IconService from '@wexample/symfony-loader/js/Services/IconService'; import ToastService from '@wexample/symfony-loader/js/Services/ToastService'; import ConfirmService from '@wexample/symfony-loader/js/Services/ConfirmService'; import KeyboardService from '@wexample/symfony-loader/js/Services/KeyboardService'; import ModalService from '@wexample/symfony-loader/js/Services/ModalService'; class AppCustom extends App { getServices(): (typeof AppService | [typeof AppService, any[]])[] { return [ ...super.getServices(), VueService, IconService, ToastService, ConfirmService, KeyboardService, ModalService, ]; } } new AppCustom();
Create front/layouts/private/layout.en.yml with at minimum:
layout: logo: alt: Your app name
Color palette
Create front/css/partials/_palette.scss to override DS bundle defaults:
$colorPrimary: #your-color; $colorSecondary: #your-color; $colorAccent: #your-color; $colorBlack: #000000;
The DS bundle provides assets/css/partials/_palette.scss with !default values that this file overrides.
App design system controller
Create src/Controller/DesignSystem/AppController.php to expose the /_design_system/app/ route:
#[Route(name: 'app_design_system_app_', path: AbstractDesignSystemController::CONTROLLER_BASE_ROUTE . '/app/')] final class AppController extends AbstractAppController { #[Route(name: 'index', path: '')] public function index(): Response { return $this->renderPage('index'); } }
Template at front/design_system/app/index.html.twig (path mirrors the controller namespace, stripping App\Controller\).
Known issues / TODOs
- Translations overwrite bug:
WexampleSymfonyTranslationsExtensionused to overwritetranslations_pathsinstead of merging, erasing paths set byWexampleSymfonyLoaderExtension. Fixed by merging in the translations extension. Verify this is resolved in your version. - TODO: Document how to add additional app-specific DS pages beyond
app/index. - TODO: Document the
has_simple_routes/has_template_routesservice tags and when#[TemplateBasedRoutes]is sufficient vs explicit route declarations.
Migration Notes
When upgrading between major versions, refer to the migration guides in the documentation.
Breaking changes are clearly documented with upgrade paths and examples.