fi/bootstrapitaliabundle
Symfony bundle for integrating Bootstrap Italia, the Italian government design system, into PHP applications. It supplies ready-to-use templates, form themes, assets, and configuration so teams can build accessible, consistent public-sector interfaces faster.
This bundle is small, archived, and has essentially no downstream usage — treat it as a reference implementation or seed, not a maintained dependency. Realistically you will vendor it (fork or path repository) into your project and own it from day one.
Minimal steps:
composer require fi/bootstrapitaliabundle (if the packagist entry is still resolvable) or, preferred given the archived state, add a path/vcs repository in composer.json pointing at your fork.src/*ServiceProvider.php and look for:
loadViewsFrom(...) → tells you the Blade view namespace (e.g. bootstrapitalia::)mergeConfigFrom(...) / publishes(...) → tells you what config and assets are publishableBlade::directive(...) or view composer registrationsphp artisan vendor:publish --provider="FI\BootstrapitaliaBundle\...ServiceProvider"
Do this for config, views, and public tags individually if the provider defines them; many FI-era packages only tag config.resources/views/layouts/ (or resources/views/ root) for the master Blade. This is almost certainly a Bootstrap Italia shell: the <header class="it-header-wrapper">, <nav class="it-nav-wrapper">, <main>, and <footer class="it-footer"> blocks defined by the Designers Italia kit.fifree layout (or theme override), replace the existing @extends target with the bundle's layout, or @include its header/footer partials into an existing layout. That single swap is what the package is for — giving a fifree site the AGID/Bootstrap Italia chrome without hand-writing the markup.Sanity check before committing: open composer.json in the package and confirm the illuminate/* constraints match your Laravel version. Archived FI packages are typically pinned to Laravel 5.x–8.x era constraints and will refuse to install on 10/11 without a --ignore-platform-reqs hack you should not use.
Override, don't edit vendor. Copy the published views into resources/views/vendor/bootstrapitalia/ (or whatever the namespace resolves to — check loadViewsFrom) and edit there. You keep upgradeability if a fork ever appears, and you keep the diff reviewable.
Treat the layout as a shell, not a page. Structure your integration as:
resources/views/vendor/bootstrapitalia/
layouts/app.blade.php # header, nav, main, footer, asset stacks
partials/header.blade.php
partials/footer.blade.php
partials/breadcrumbs.blade.php
Then every fifree page does @extends('bootstrapitalia::layouts.app') and fills @section('content'). Keep fifree's own blocks (@yield('title'), meta, etc.) mapped in the layout so nothing in the parent theme breaks.
Asset wiring. Bootstrap Italia ships its own compiled CSS/JS and expects its own DOM contract. In practice you'll:
@push('styles')
<link rel="stylesheet" href="{{ asset('vendor/bootstrap-italia/css/bootstrap-italia.min.css') }}">
@endpush
@push('scripts')
<script src="{{ asset('vendor/bootstrap-italia/js/bootstrap-italia.bundle.min.js') }}"></script>
@endpush
and pull bootstrap-italia from npm into your Vite/Mix config rather than trusting whatever stale copy the bundle may ship. The bundle's public/ assets, if any, are frozen at whatever Bootstrap Italia version existed when it was archived.
Component usage. Build pages from the Designers Italia markup patterns, not from bootstrap-italia as a generic CSS framework:
<div class="card-wrapper"> + <div class="card"> with card-body, card-title, card-text<div class="callout"> with callout-titlebreadcrumb-container block, driven by a view composer so every controller doesn't repeat itit-header-center-wrapper / it-header-navbar-wrapper split, with the sticky variant enabled via data-sticky-headerView composer for navigation. Rather than passing menu links into the layout from every controller, register a composer in AppServiceProvider:
View::composer('bootstrapitalia::partials.header', function ($view) {
$view->with('navItems', Menu::for('main-navigation'));
});
This is the main extension point in practice — the bundle's Blade has no idea about your fifree menus, so composers are how you inject them cleanly without forking every partial.
Multi-area / tenant sites. If your fifree install serves multiple comuni, keep the layout generic and drive the header (ente name, logo, social links) from config or a tenant-aware composer, not from hardcoded Blade.
Form integration. Bootstrap Italia styles Bootstrap 4-era form controls; if fifree's form builder emits Bootstrap 5 class names (form-control, form-select, mb-3) you'll get visual drift. Align on one baseline before adding pages.
Archived means pinned. Add a comment in composer.json and a README note in your fork stating the exact upstream commit you vendored, and the Bootstrap Italia version the markup targets. Six months from now nobody will remember.
Version skew is the big one. Bootstrap Italia has moved through Bootstrap 4 → Bootstrap 5 across its own majors, and the component JS became web-component based in later versions. The bundle was written against one specific major. Mixing a newer bootstrap-italia npm package with the bundle's Blade will produce silent breakage — dropdowns that don't open, sticky headers that don't stick. Pin bootstrap-italia in package.json to the version the bundle's markup assumes.
Config caching bites. If the bundle ships a config file, php artisan config:cache after publishing — and remember that any env() calls inside the bundle's config will return null once cached. Move those to your own config/ file.
View cache. When you override a partial and don't see the change: php artisan view:clear. The namespace resolution order (app overrides → vendor) is easy to get wrong if the override directory name doesn't exactly match the namespace string in loadViewsFrom.
jQuery. Bootstrap Italia's earlier JS builds expect jQuery to be present. If fifree's layout has already dropped jQuery, the bundle's scripts will fail with $ is not defined — add it, or you'll spend an hour on a "broken dropdown" that's just a missing dependency.
Accessibility is the point. Bootstrap Italia exists to satisfy AGID/Designers Italia requirements. Skipping the semantic structure (proper <nav> landmarks, skip-link, aria-* on the header toggle) means you've paid the integration cost without getting the compliance benefit. Check markup against the Designers Italia component docs, not against what renders.
Debugging strategy. Since there's no upstream support, work top-down: (1) php artisan route:list and confirm the view namespace is registered via php artisan tinker → View::exists('bootstrapitalia::layouts.app'); (2) if that's false, the provider isn't loaded — check bootstrap/providers.php / config/app.php package discovery; (3) if it's true but the page looks wrong, diff your override against the published vendor file.
Extension points that actually exist. Realistically only three: config values, view overrides in resources/views/vendor/, and view composers. Don't expect events, contracts, or driver patterns — this is a Blade-and-assets bundle. Plan your customization around those three and you won't fight it.
Recommendation. For new work, skip the dependency and copy the Blade partials you need plus a current bootstrap-italia npm package directly. Two stars, zero dependents, and an archived flag means the only thing this bundle gives you is a starting markup snapshot — which you can take in five minutes without inheriting its version constraints.
How can I help you explore Laravel packages today?