Symfony Bundle Patterns (6.4+)
SkillDev toolsReference patterns for creating Symfony 6.4+ reusable bundles using AbstractBundle. Auto-loaded when working on InertiaBundle.php, config/definition.php, config/services.yaml, or any DI configuration.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Symfony Bundle Patterns (6.4+) skill
What this skill tells your AI
The instructions your AI receives, as published by nytodev/inertia-bundle in .claude/skills/symfony-bundle-patterns/SKILL.md and read by ahel’s review.
AbstractBundle — Canonical Pattern
Main Bundle Class
<?php
declare(strict_types=1);
namespace Nytodev\InertiaBundle;
use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
/**
* Main bundle class. Uses AbstractBundle (Symfony 6.1+) — no separate Extension class needed.
* - configure() defines the config schema (called compile-time only)
* - loadExtension() loads services and injects config values (called compile-time only)
*/
final class InertiaBundle extends AbstractBundle
{
public function configure(DefinitionConfigurator $definition): void
{
// Import from separate file to keep this class clean
$definition->import('../config/definition.php');
}
public function loadExtension(
array $config, // Already merged & validated by AbstractBundle — use directly
ContainerConfigurator $container,
ContainerBuilder $builder
): void {
// Load service definitions
$container->import('../config/services.yaml');
// Inject config values into services
// Note: physical path used above, not logical '@InertiaBundle/config/...'
$container->services()
->get('inertia.service')
->arg('$rootView', $config['root_view'])
->arg('$version', $config['version'])
->arg('$ssrEnabled', $config['ssr_enabled'])
->arg('$ssrUrl', $config['ssr_url'])
;
}
}
Config Definition File
<?php
// config/definition.php
declare(strict_types=1);
use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
return static function (DefinitionConfigurator $definition): void {
$definition->rootNode() // Root key = 'inertia' (bundle alias)
->children()
->scalarNode('root_view')
->defaultValue('base.html.twig')
->info('Twig template used as the application root on first visit')
->end()
->scalarNode('version')
->defaultNull()
->info('Asset version for cache-busting (string, hash, or null to disable)')
->end()
->booleanNode('ssr_enabled')
->defaultFalse()
->info('Enable Server-Side Rendering via a Node.js SSR server')
->end()
->scalarNode('ssr_url')
->defaultValue('http://127.0.0.1:13714')
->info('URL of the Node.js SSR server (only used when ssr_enabled is true)')
->end()
->end()
;
};
Services YAML (explicit, no autowiring)
# config/services.yaml
services:
# --- Main service ---
inertia.service:
class: Nytodev\InertiaBundle\Service\Inertia
arguments:
$requestStack: '@request_stack'
$twig: '@twig'
$rootView: 'base.html.twig' # overridden by loadExtension()
$version: null # overridden by loadExtension()
$ssrEnabled: false # overridden by loadExtension()
$ssrUrl: 'http://127.0.0.1:13714'
public: false
# Public alias for autowiring: inject Inertia type-hint in controllers
Nytodev\InertiaBundle\Service\Inertia:
alias: inertia.service
public: true
# --- Event Listener ---
inertia.listener:
class: Nytodev\InertiaBundle\EventListener\InertiaListener
arguments:
$inertia: '@inertia.service'
tags:
- { name: kernel.event_subscriber }
public: false
# --- Twig Extension ---
inertia.twig_extension:
class: Nytodev\InertiaBundle\Twig\InertiaTwigExtension
arguments:
$inertia: '@inertia.service'
tags:
- { name: twig.extension }
public: false
Config Usage in Applications
# config/packages/inertia.yaml (application side)
inertia:
root_view: 'base.html.twig'
version: '%env(ASSET_VERSION)%'
ssr_enabled: '%env(bool:SSR_ENABLED)%'
ssr_url: '%env(SSR_URL)%'
Key Principles
- AbstractBundle over Bundle: No
DependencyInjection/directory needed $configis pre-merged:loadExtension()receives flat config, noprocessConfiguration()call- Services prefixed:
inertia.*(DI alias =inertia) - No autowire/autoconfigure: All services declared explicitly
- Physical paths:
../config/services.yamlnot@InertiaBundle/config/... - Private by default: Services have
public: false; only aliases are public - Compile-time only: Both
configure()andloadExtension()are called at compile time
Signals
- GitHub stars
- 22
- Last commit
- Jul 2026
Advanced
- Catalog kind
- skill
- Gateway key
symfony-bundle-patterns- Source
- github.com/nytodev/inertia-bundle