patricktalmadge/bootstrapper
Bootstrapper provides Laravel helpers for generating Bootstrap 3 markup, with fluent builders for forms, buttons, navbars, alerts, panels, and icons. Keep Blade templates clean and consistent by writing PHP instead of repetitive HTML.
patricktalmadge/bootstrapper:~4.0 targets Bootstrap 3 markup and Laravel 4.2/5.x. Bootstrap 4 or 5 CSS will render half-broken components (col-xs-*, pull-right, btn-default all differ). Require ~3.0 only if you're on Bootstrap 2.composer require patricktalmadge/bootstrapper:~4.0
php artisan vendor:publish # pulls config/bootstrapper.php (+ views)
The tagged releases predate extra.laravel auto-discovery, so add to config/app.php:
'providers' => [Bootstrapper\BootstrapperServiceProvider::class],
'aliases' => [
'Button' => Bootstrapper\Facades\Button::class,
'Alert' => Bootstrapper\Facades\Alert::class,
'BsForm' => Bootstrapper\Facades\Form::class, // avoid clashing with laravelcollective/html
'Icon' => Bootstrapper\Facades\Icon::class,
'Table' => Bootstrapper\Facades\Table::class,
],
You only need aliases for components you actually use; fully-qualified \Bootstrapper\Facades\Button::success(...) works without them.src/Bootstrapper/ and src/Bootstrapper/Facades/. Each component is a small class holding an $attributes array plus a toHtml()/render() that compiles a package view. The published config tells you where the templates and icon set live; the test suite is the best API reference because it exercises every chainable method.<button class="btn btn-success"><i class="fa fa-check"></i> Save</button>
write:
{!! Button::success('Save')->withIcon(Icon::create('check')) !!}
Set the icon set once in config/bootstrapper.php (glyphicons vs font-awesome) so Icon::create('check') maps to the right class prefix.{!! !!} in Blade (or ->render()). {{ }} double-escapes the tags into visible text.$btn = Button::success('Save');
$btn->large(); // throws away the large() result
echo $btn; // plain btn-success
echo Button::success('Save')->large()->block(); // correct
$btn = $btn->large(); // also correct
{!! Form::open()->horizontal()->withAttributes(['route' => 'users.store']) !!}
{!! Form::text('name')->placeholder('Full name')->help('As it appears on invoices') !!}
{!! Form::email('email')->value(old('email', $user->email)) !!}
{!! Form::select('role')->options($roles)->select($user->role) !!}
{!! Form::checkbox('active')->check($user->active) !!}
{!! Form::submit('Save')->success() !!}
{!! Form::close() !!}
Form::open() renders the tag only — add the CSRF field (@csrf / Form::token()) and @method('PUT') yourself.old('field', $default) into ->value().Arrayable; nested keys aren't resolved, so map first:
{!! Table::striped()->hover()->responsive()
->headers('Name', 'Email', 'Role')
->rows($users->map(fn ($u) => [$u->name, $u->email, $u->role])->all()) !!}
Append $users->links() beneath rather than relying on the table for pagination.partials/navbar.blade.php once with Navbar::create()->withBrand(...) + Nav::create()->withItems([...]); mark the active link in the item definition (->active()) rather than post-processing HTML. Same for a partials/flash.blade.php that loops over session('flash') into Alert::success()/danger()/warning().app/Support/Ui.php in front of it (Ui::saveButton(), Ui::statusLabel($state)). That gives you one place to enforce icon conventions, extra aria-* attributes, and — later — a migration to Blade components without touching every view.ButtonGroup/ButtonToolbar rather than hand-writing wrappers, and Tabbable/Panel/Modal/ProgressBar for the structural pieces. Bootstrapper generates markup only — the Bootstrap JS bundle is still your responsibility for dropdowns, modals and tabs.$this->assertStringContainsString('btn-success', Button::success('Save')->render()); is stable and fast; full-page HTML assertions break on every Bootstrap bump.Bootstrapper\Facades\Form vs laravelcollective/html's Form is the classic failure — only one wins config/app.php. Alias Bootstrapper's as BsForm, or skip the alias and use the FQCN.$x->large(); on its own line does nothing. This is the single most common "the class isn't applied" bug.Icon::create('ok') (Glyphicon) becomes a blank box under Font Awesome, where the name is check. Changing 'icons' in config can quietly break dozens of views — grep for Icon::create before switching.resources/views/vendor/..., then php artisan view:clear. If you've run config:cache, re-run it after touching config/bootstrapper.php or your icon/template paths revert to defaults.$errors bag. Add has-error / feedback markup yourself — either in the Blade partial or inside your Ui wrapper — otherwise failed submissions look identical to successful ones.withAttributes() are escaped; string bodies handed to withBody()/withHeader()/Alert::danger($msg) are not. Never interpolate raw user input there — pass e($input).<tbody>; add a "No records found" row explicitly. responsive() only works if a wrapping div is actually emitted — verify in the DOM if columns overflow on mobile.->render() (not string casting, which can swallow exceptions on older PHP), paste the output next to the official Bootstrap 3 docs for that component, then check config/bootstrapper.php for icons and templates. Nine times out of ten the diff is a version mismatch or a template override pointing at a stale view.withAttributes([...]) → one-off classes, IDs, data-*, aria-*; (3) subclass a component and bind it in a service provider if you need new chainable methods. Don't fork the package for markup.Ui wrapper at Blade components one method at a time and delete the facade call. No rewrite weekend required.How can I help you explore Laravel packages today?