⭐ Found this useful? Install from Packagist · Give it a star on GitHub so more developers can find it.
Routing Kit Bundle — DB-driven (pluggable storage) locale paths for Symfony: dual /foo + /{locale}/foo access, admin-defined canonical URLs, Twig CRUD panel, route-cache invalidation, and SeoKitBundle path bridge. Tested on Symfony 7.4, 8.0, and 8.1 · PHP 8.2+ (Symfony 8.x requires PHP 8.4+).
This bundle is FrankenPHP worker mode friendly.
- Storage — One row per
(routeName, locale); filesystem JSON by default; swap viaRoutePathStorageInterface. - Locales — YAML
default_locale+locales, or a customLocaleProviderInterface. - Canonical definition — Paths stored without
{_locale}; the loader always builds/{_locale}/…. - Styles —
canonical_style, trailing slash, alias mode (redirect/alias). - Fallback — Missing locale row → default-locale path for that route name.
#[Routable]— Controllers offered in the CRUD; params + constraints validated on save.- Loader —
type: nowo_routing_kitregisters{name}.{locale}with_canonical_route(import last). - Panel — Twig CRUD under
/_routing+ clear routing cache (auto after save/delete). - SeoKit — Optional bridge decorates
SeoPathBuilderInterfacefor canonical/hreflang paths.
composer require nowo-tech/routing-kit-bundleWith Symfony Flex, the recipe registers the bundle and adds config (see .symfony/recipe). Without Flex, see docs/INSTALLATION.md.
# config/routes.yaml — panel, then app routes, then DB loader LAST
nowo_routing_kit_panel:
resource: '@NowoRoutingKitBundle/Resources/config/routes.yaml'
# … application routes …
nowo_routing_kit_db:
resource: .
type: nowo_routing_kitThe loader registers {name}.{locale} with _canonical_route. Protect /_routing with your firewall.
nowo_routing_kit:
default_locale: en
locales: [en, es]
panel:
path_prefix: /_routing
redirects:
canonical_enabled: true
seo_kit_bridge: trueuse Nowo\RoutingKitBundle\Attribute\Routable;
use Nowo\RoutingKitBundle\Attribute\RouteParam;
#[Routable(name: 'app_about')]
public function about(): Response { … }
#[Routable(name: 'app_blog_show', params: [
new RouteParam('slug', required: true, requirement: '[a-z0-9-]+'),
])]
public function show(string $slug): Response { … }Open /_routing to manage paths. See docs/USAGE.md.
- Installation
- Configuration
- Usage
- Contributing
- Code of Conduct
- Changelog
- Upgrading
- Release
- Security
- Engram
- Spec-driven development
- GitHub Spec Kit
- PHP
>=8.2(<8.6); Symfony 8.0 and 8.1 require PHP 8.4+ - Symfony 7.4, 8.0, or 8.1
- Twig for the CRUD panel templates
make up
make install
make test
make cs-check
make phpstan
make release-checkInstall git hooks once per clone: make setup-hooks (REQ-GIT-001).
make -C demo up-symfony8Open http://localhost:8058 — panel at /_routing. FrankenPHP mode is controlled by FRANKENPHP_MODE (classic | worker, default worker) in the demo .env.
PHPUnit with 100% line coverage of production PHP under src/ (optional SeoKit bridge files excluded when SeoKit is not a require-dev dependency):
make test-coverage
make coverage-checkMIT
