wexample / symfony-design-system
Design system assets for Symfony
Package info
github.com/wexample/symfony-design-system
Language:SCSS
pkg:composer/wexample/symfony-design-system
Requires
- php: >=8.5
- symfony/security-bundle: ^7.4 || ^8.0
- wexample/symfony-loader: >=25.0.1
- wexample/symfony-preference: >=2.0.2
- wexample/symfony-routing: >=2.2.0
- wexample/symfony-template: >=2.1.2
Requires (Dev)
- phpunit/phpunit: ^13
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- 39.0.3
- 39.0.2
- 39.0.1
- 39.0.0
- 38.0.0
- 37.0.1
- 37.0.0
- 35.0.1
- 35.0.0
- 34.0.0
- 32.0.3
- 32.0.2
- 32.0.1
- 32.0.0
- 31.0.0
- 30.0.0
- 29.0.5
- 29.0.4
- 29.0.3
- 29.0.2
- 29.0.1
- 29.0.0
- 26.0.0
- 25.0.0
- 23.0.0
- 22.0.0
- 21.0.0
- 20.0.3
- 20.0.2
- 20.0.1
- 20.0.0
- 19.0.0
- 18.0.0
- 16.0.1
- 16.0.0
- 15.0.0
- 14.0.0
- 13.0.2
- 13.0.1
- 13.0.0
- 11.0.2
- 11.0.1
- 11.0.0
- 10.0.2
- 10.0.1
- 10.0.0
- 9.0.0
- 8.0.1
- 8.0.0
- 7.0.0
- 6.0.0
- 4.0.1
- 4.0.0
- 3.0.5
- 3.0.4
- 3.0.3
- 3.0.2
- 3.0.1
- 3.0.0
- 1.0.82
- 1.0.81
- 1.0.80
- 1.0.78
- 1.0.77
- 1.0.76
- 1.0.75
- 1.0.74
- 1.0.73
- 1.0.72
- 1.0.71
- 1.0.70
- 1.0.69
- 1.0.68
- 1.0.67
- 1.0.66
- 1.0.65
- 1.0.64
- 1.0.63
- 1.0.62
- 1.0.60
- 1.0.59
- 1.0.58
- 1.0.56
- 1.0.55
- 1.0.51
- 1.0.50
- 1.0.49
- 1.0.48
- 1.0.47
- 1.0.46
- 1.0.45
- 1.0.44
- 1.0.43
- 1.0.42
- 1.0.41
- 1.0.40
- 1.0.39
- 1.0.38
- 1.0.37
- 1.0.36
- 1.0.35
- 1.0.34
- 1.0.33
- 1.0.32
- 1.0.31
- 1.0.30
- 1.0.29
- 1.0.28
- 1.0.27
- 1.0.26
- 1.0.24
- 1.0.23
- 1.0.22
- 1.0.21
- 1.0.20
- 1.0.19
- 1.0.18
- 1.0.17
- 1.0.16
- 1.0.11
- 1.0.10
- 1.0.9
- 1.0.8
- 1.0.7
- 1.0.6
- 1.0.5
- 1.0.4
- 1.0.3
- 1.0.2
- 1.0.1
- 1.0.0
- 0.1.78
- 0.1.77
- 0.1.76
- 0.1.75
- 0.1.74
- 0.1.73
- 0.1.72
- 0.1.71
- 0.1.70
- 0.1.69
- 0.1.68
- 0.1.67
- 0.1.66
- 0.1.65
- 0.1.64
- 0.1.63
- 0.1.62
- 0.1.61
- 0.1.60
- 0.1.59
- 0.1.57
- 0.1.55
- 0.1.54
- 0.1.53
- 0.1.52
- 0.1.51
- 0.1.50
- 0.1.48
- 0.1.47
- 0.1.46
- 0.1.45
- 0.1.44
- 0.1.43
- 0.1.42
- 0.1.41
- 0.1.40
- 0.1.39
- 0.1.38
- 0.1.37
- 0.1.36
- 0.1.35
- 0.1.34
- 0.1.33
- 0.1.32
- 0.1.31
- 0.1.30
- 0.1.28
- 0.1.27
- 0.1.26
- 0.1.25
- 0.1.24
- 0.1.23
- 0.1.22
- 0.1.21
- 0.1.20
- 0.1.19
- 0.1.18
- 0.1.17
- 0.1.16
- 0.1.14
- 0.1.13
- 0.1.12
- 0.1.11
- 0.1.10
- 0.1.8
- 0.1.7
- 0.1.6
- 0.1.5
- 0.1.2
- 0.1.1
- 0.1.0
This package is auto-updated.
Last update: 2026-10-22 17:09:19 UTC
README
Version: 39.0.3
Design system assets for Symfony
Table of Contents
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.