nowo-tech / dashboard-menu-bundle
Symfony bundle for configurable dashboard menus with i18n (JSON translations), tree structure (parent/position), permissions, Twig and JSON API. No external ORM extensions.
Package info
github.com/nowo-tech/DashboardMenuBundle
Type:symfony-bundle
pkg:composer/nowo-tech/dashboard-menu-bundle
Fund package maintenance!
Requires
- php: >=8.2 <8.6
- doctrine/doctrine-bundle: ^2.8 || ^3.0
- doctrine/orm: ^2.13 || ^3.0
- nowo-tech/form-kit-bundle: ^2.0
- nowo-tech/ui-kit-bundle: ^1.4
- psr/cache: ^1.0 || ^2.0 || ^3.0
- psr/clock: ^1.0
- psr/log: ^1.0 || ^2 || ^3
- symfony/asset: ^7.4 || ^8.0
- symfony/clock: ^7.4 || ^8.0
- symfony/config: ^7.4 || ^8.0
- symfony/dependency-injection: ^7.4 || ^8.0
- symfony/form: ^7.4 || ^8.0
- symfony/framework-bundle: ^7.4 || ^8.0
- symfony/http-foundation: ^7.4 || ^8.0
- symfony/http-kernel: ^7.4 || ^8.0
- symfony/mime: ^7.4 || ^8.0
- symfony/routing: ^7.4 || ^8.0
- symfony/security-core: ^7.4 || ^8.0
- symfony/security-csrf: ^7.4 || ^8.0
- symfony/translation: ^7.4 || ^8.0
- symfony/twig-bundle: ^7.4 || ^8.0
- symfony/ux-autocomplete: ^2.33 || ^3.0
- symfony/ux-live-component: ^2.32 || ^3.0
- symfony/validator: ^7.4 || ^8.0
- twig/extra-bundle: ^3.12
- twig/string-extra: ^3.12
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- nowo-tech/phpstan-frankenphp: ^1.0
- phpstan/extension-installer: ^1.0
- phpstan/phpstan: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- phpstan/phpstan-symfony: ^2.0
- phpunit/phpunit: ^11.0
- rector/rector: ^2.0
- symfony/browser-kit: ^7.4 || ^8.0
- symfony/dom-crawler: ^7.4 || ^8.0
- symfony/yaml: ^7.4 || ^8.0
- vincentlanglet/twig-cs-fixer: ^3.0
Suggests
- doctrine/doctrine-migrations-bundle: To run the migration generated by nowo_dashboard_menu:generate-migration
- nowo-tech/icon-selector-bundle: For the icon selector widget in the dashboard item form (requires Symfony ^7.0 || ^8.0)
- symfony/ux-icons: For icon support in menu items (heroicons, bootstrap icons, etc.)
This package is auto-updated.
Last update: 2026-08-10 09:20:22 UTC
README
⭐ Found this useful? Install from Packagist · Give it a star on GitHub so more developers can find it.
Nowo Dashboard Menu Bundle — Configurable dashboard menus with i18n (JSON translations), tree structure (parent + position), permissions, Twig rendering and JSON API. No external ORM extensions (Gedmo/Stof). Minimum: PHP 8.2+, Symfony 7.4+ / 8 (^7.4 || ^8.0).
This bundle is FrankenPHP worker mode friendly.
Table of contents
- Features
- Installation
- Requirements
- Configuration
- Usage
- Demo
- Development
- Documentation
- Tests and coverage
- License
- Author
Features
- Menu & MenuItem entities: Tree (parent/children, ordered by position), labels with optional JSON translations per locale, optional icon per item (e.g. Symfony UX Icons)
- Context resolution: Same
codecan have multiple menus with different JSON context (e.g.partnerId,operatorId); pass an ordered list of context sets and the first match is used; empty context = fallback - Config: Doctrine connection and table prefix; cache (TTL + pool) for the menu tree;
icon_library_prefix_map(e.g.bootstrap-icons→bi); locales; per-menu options (classes, permission checker, depth limit, icons, collapsible) in the database - Permissions:
MenuPermissionCheckerInterface— implement and tag to filter items per user/context - Twig:
dashboard_menu_tree(menuCode, permissionContext?, contextSets?),dashboard_menu_href(item),dashboard_menu_config(menuCode, contextSets?); include@NowoDashboardMenuBundle/menu.html.twig - JSON API:
GET /api/menu/{code}for SPA consumption (optional_locale,_context_setsquery params) - Dashboard: CRUD at
/admin/menus(list, create, edit, copy menu, manage items); export/import menus as JSON; optional drag-and-drop tree reorder (SortableJS) on a dedicated route; forms split into definition (pencil) and configuration (gear); redirect to referer after successful actions; import available in a modal - Performance: Two SQL queries per menu (menu + items), optional PSR-6 cache (configurable TTL); labels by locale from JSON; tree built in PHP
- Dev: Web Profiler panel “Dashboard menus” (menus on page, query count, configuration tab: connection, cache, locales, icon map, permission checkers)
Installation
composer require nowo-tech/dashboard-menu-bundle
With Symfony Flex, the recipe (if available) registers the bundle and adds config/routes. Without Flex, see docs/INSTALLATION.md for manual steps.
Requirements
- PHP >= 8.2, < 8.6
- Symfony 7.4+ or 8.x (
^7.4 || ^8.0) — Symfony 7 floor is 7.4 (REQ-SF-001; FormKit^2.0) - Doctrine ORM ^2.13 || ^3.0 (no Gedmo/Stof required)
- UiKitBundle + FormKitBundle (required hard dependencies for the dashboard UI)
- Symfony UX Autocomplete & Live Component (installed with the bundle): 2.x (from 2.32 / 2.33) or 3.x
See docs/INSTALLATION.md and docs/UPGRADING.md for compatibility notes.
Configuration
Menus are defined in the database (dashboard at /admin/menus or fixtures): code, name, context (optional JSON), CSS classes. In YAML you only need defaults (and optional project, locales). See docs/CONFIGURATION.md.
# config/packages/nowo_dashboard_menu.yaml nowo_dashboard_menu: project: my_app doctrine: connection: default table_prefix: '' cache: ttl: 60 pool: cache.app icon_library_prefix_map: bootstrap-icons: bi locales: ['es', 'en'] api: enabled: true path_prefix: /api/menu
Usage
Twig:
{% set tree = dashboard_menu_tree('sidebar') %}
{% set config = dashboard_menu_config('sidebar') %}
{% include '@NowoDashboardMenuBundle/menu.html.twig' with { menuTree: tree, menuCode: 'sidebar', menuConfig: config } %}
With context sets (resolve which menu variant to show):
{% set contextSets = [{ 'partnerId': 1, 'operatorId': 1 }, { 'partnerId': 1 }, {}] %}
{% set tree = dashboard_menu_tree('sidebar', null, contextSets) %}
API: GET /api/menu/sidebar returns JSON tree with label, href, routeName, children. Optional query: _context_sets (JSON array of context objects).
Full details: docs/USAGE.md.
Demo
The in-repo demo is demo/symfony8 (FrankenPHP + Caddy; HTTP on port 80 in the container). The package still supports Symfony 7.4+ and 8 via Composer. Compose defaults to APP_ENV=dev and FRANKENPHP_MODE=worker; set FRANKENPHP_MODE=classic for hot-reload (Caddyfile.dev, no PHP worker) — docs/DEMO-FRANKENPHP.md. Quick start: docs/DEMO.md.
Default host port: 8011 via PORT in demo/symfony8/.env.
From bundle root:
make -C demo/symfony8 up
make -C demo/symfony8 install
# Open http://localhost:8011 (or PORT from demo/symfony8/.env)
Development
Run tests and QA with Docker: make up && make install && make test (or make test-coverage, make qa). Without Docker: composer install && composer test. Full details: docs/DEVELOPMENT.md.
Dashboard assets (TS → JS): Built with Vite (as in IconSelectorBundle). Sources under src/Resources/assets/src/ (dashboard.ts, stimulus-live.ts, logger.ts). Output: src/Resources/public/js/dashboard.js (IIFE) and js/stimulus-live.js (ESM), installed by Symfony to public/bundles/nowodashboardmenu/js/.
pnpm install pnpm run build # production build (dashboard.js + stimulus-live.js) pnpm run dev # watch dashboard.js pnpm run build:dashboard # only dashboard.js pnpm run build:stimulus-live # only stimulus-live.js
Then run php bin/console assets:install in the app so public/bundles/nowodashboardmenu/js/ is updated.
Documentation
- GitHub Actions CI requirements
- Installation
- Configuration
- Usage
- Contributing
- Code of Conduct
- Changelog
- Upgrading
- Release
- Security
- Engram
- Spec-driven development
- GitHub Spec Kit
Additional documentation
Tests and coverage
- Tests: PHPUnit (unit and integration suites) + Vitest for TypeScript (
make test-ts) - PHP (Lines): 99.27% on the includable
src/set — seedocs/COVERAGE.md. Runmake coverage-check/composer coverage-check. - TS/JS: 100% on
logger.ts(Vitest + v8); runmake test-ts(prints global TS coverage via.scripts/ts-coverage-percent.sh) - Python: N/A
License
The MIT License (MIT). Please see LICENSE for more information.
Author
Created by Héctor Franco Aceituno at Nowo.tech
