Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Bootstrap Ui Laravel Package

nexus633/laravel-bootstrap-ui

Laravel Bootstrap UI provides ready-made Blade components for building Bootstrap-styled interfaces in Laravel apps. Speed up development with reusable, consistent UI elements and less repetitive markup.

View on GitHub
Deep Wiki
Context7

Getting Started

This release (1.1.0) turns the package from a pure Bootstrap component library into one with an opinionated app-shell feature: a searchable command palette with both backend and Blade registration. If you are installing fresh, start there — it is the fastest way to see the whole stack (Blade component → service → facade → JS) working.

1. Install and publish

composer require <vendor>/<package>
php artisan vendor:publish --tag=<package>-config   # check `php artisan vendor:publish` for the exact tags

Look first at three places in the package source, in this order:

  1. src/Providers/*ServiceProvider.php — where components are registered (Blade::componentNamespace), where the CommandPalette and BootstrapUi facades are bound, and whether any JS/CSS is pushed to a stack or published to public/.
  2. resources/views/components/ — the actual Blade files. This is the real documentation for props/slots; the README lags behind on prop names.
  3. config/ — anything toggleable (default shortcut, palette defaults, prefix for component names).

2. Drop the palette into your layout

{{-- resources/views/layouts/app.blade.php --}}
<body>
    {{ $slot }}

    <x-bs::command-palette />
</body>

3. Register your first commands from the backend

// app/Providers/AppServiceProvider.php
use <Vendor>\<Package>\Facades\CommandPalette;

public function boot(): void
{
    CommandPalette::register('Create invoice', route('invoices.create'))
        ->keywords(['new', 'billing']);

    CommandPalette::register('Log out', route('logout'), method: 'POST');
}

First real use case: replace the scattered "quick actions" dropdown in your admin header. Backend-register everything that maps to a route or a named action (global, works on every page), and use declarative Blade items only for page-local commands.

If you are upgrading from 1.0.x, do the breaking-change sweep before anything else — see Gotchas and Tips — because nav and tab/* no longer exist and your views will throw Unable to locate a class or view for component [bs::nav] at render time, not at build time.

Implementation Patterns

Backend registration belongs in a dedicated service provider

Keep palette registration out of AppServiceProvider once you have more than a handful of commands. A CommandPaletteServiceProvider (or a Palette bootstrapper class) keeps it greppable and lets you wrap registration in an if (app()->isProduction()) / permission check:

CommandPalette::register('Invite user', route('users.invite'))
    ->visible(fn () => auth()->user()->can('invite-users'));

Treat visible/authorization callbacks as mandatory for anything that isn't purely navigational — a command palette is a global, always-mounted surface, and a client-side filter over the item list is not access control.

Declarative items for page-local commands

<x-bs::command-palette.item> is the right tool when the command only makes sense on the current page (a "Export this report" action). Put them inside the page view, not the layout:

<x-bs::command-palette>
    <x-bs::command-palette.item
        label="Export this report"
        :action="route('reports.export', $report)"
    />
    <x-bs::command-palette.item label="Duplicate" wire:click="duplicate" />
</x-bs::command-palette>

The trade-off: declarative items only exist on pages that render them, so anything a user expects to find "everywhere" (dashboard, settings, logout) must go through the backend facade.

Centralise your own markup on BootstrapUi too

The new BootstrapUi facade is the most under-hyped part of this release. Internally it builds class strings, styles and attributes; use it in your own custom components instead of hand-concatenating Bootstrap classes. That is the extension point that makes your in-house components survive the next theme/purge change:

use <Vendor>\<Package>\Facades\BootstrapUi;

$classes = BootstrapUi::classes('btn', ['btn-primary' => $primary, 'btn-sm' => $small]);

If you maintain an internal component library layered on top of this package, migrate your own components to BootstrapUi before the next minor release — the 1.1.0 refactor signals the package is now opinionated about class generation, and hand-rolled strings are exactly what will drift.

Migrating nav → tabs

<x-bs::nav> and its children are gone. Anything that was a tab strip becomes <x-bs::tabs>:

{{-- 1.0.x --}}
<x-bs::nav>
    <x-bs::nav.link :href="route('profile')" active>Profile</x-bs::nav.link>
    <x-bs::nav.link :href="route('security')">Security</x-bs::nav.link>
</x-bs::nav>

{{-- 1.1.x --}}
<x-bs::tabs>
    {{-- check resources/views/components/tabs/ for the exact child API,
         it does not map 1:1 to the old nav.link / tab.pane pair --}}
</x-bs::tabs>

Do not assume the new API is a rename. The release notes describe tabs as "more flexible", which usually means the children changed shape (tabs declared as a collection rather than as pre-rendered panes). Read the component source, and migrate one page first before a global find-and-replace.

Command palette + Livewire/Inertia navigation

The palette's value in an SPA-ish setup is that navigation commands should behave like links (full page visit) while actions dispatch events or call $wire methods. Keep two registration helpers in your app — registerNavigation() and registerAction() — so the two kinds never get mixed up, and so you can later swap one to wire:navigate without touching every call site.

Gotchas and Tips

The 1.1.0 upgrade is hard-breaking — sweep with grep

Removed: nav, nav/dropdown, nav/dropdown-item, nav/link, tab/content, tab/pane, partials/button-content. Note that the package refers to components both with slashes and dots, so search both forms:

grep -rnE '<x-bs::(nav|tab)[./]|<x-bs::partials[./]button-content' resources/

Every hit is a broken page. There is no deprecation shim, so pin ^1.0 in composer.json on branches you are not ready to migrate, and do this sweep as the first commit of the upgrade branch — not the last.

Published views silently defeat the refactor

If you ever ran vendor:publish --tag=<package>-views, you now have stale copies of the old components in resources/views/vendor/. Those override the package's new ones, so the BootstrapUi refactor and the tabs component simply will not take effect — and you will debug the wrong layer. Check resources/views/vendor/ before anything else when a component "still looks like 1.0". Re-publish with --force only after diffing your customisations.

Shortcut collisions on Ctrl+K

Ctrl+K is the default, and it collides in three common ways: browser/OS shortcuts (Firefox and some Linux DEs), editor-like bindings your users expect (Slack/GitHub-style search), and other in-app libraries. Two mitigations: make the shortcut configurable via the config file rather than hardcoding, and make sure the handler ignores keypresses while focus is inside input, textarea, select or a contenteditable — otherwise typing k after a Ctrl chord in a form opens the palette. Test on macOS (Cmd) and Windows/Linux separately; a German-locale release note means the maintainers are testing on non-US keyboards too, but verify.

Command items are global — watch page weight and duplication

The palette is mounted in your layout, so its item list ships on every request. Two failure modes:

  • Duplication: the same command registered by the backend facade and declared in a Blade view appears twice. Decide a rule (backend = global, Blade = page-local) and enforce it in review.
  • Bloat: dozens of Blade-declared items inside a layout produce a large DOM/hydration payload on pages that never use them.

If you have a very large command set, defer it: register a small static set and fetch the rest on open, rather than shipping hundreds of items on every render.

The JS/styling story is not in the release notes

The release notes describe the palette (opening on Ctrl+K, being searchable) but say nothing about assets. Before you conclude it is broken, confirm how the package delivers its JavaScript: check the service provider for Blade::directive, @push to a stack, or a published asset, and confirm you have included it in your layout (and that Vite is building it if it is a published module). Symptom of a missing asset: the component markup renders but Ctrl+K does nothing — which looks identical to a shortcut collision.

partials/button-content removal has a wider blast radius than it looks

That partial was a shared internal used to standardise button internals (icons + text + spinner). If you referenced it directly in your own components, the replacement is the <x-bs::text> / <x-bs::icon> pairing that is now standardised across the package. If you did not reference it directly, you still might be affected indirectly if you extended package button components with custom slots — re-check buttons with badges, icons and loading states after upgrading.

Debugging checklist

  • Unable to locate a class or view for component [bs::nav] → you missed the sweep, or a cached compiled view: php artisan view:clear.
  • New tabs renders empty → children API changed; inspect resources/views/components/tabs/.
  • Palette shows no items → registration runs after the component renders (check provider order), or your visible callback returns false.
  • Classes look wrong after upgrade → your app has its own class strings; consider moving to BootstrapUi::classes().
  • After any component-level change: php artisan view:clear && php artisan optimize:clear. Blade component caches are the most common source of "the upgrade did nothing".

Extension points worth knowing

  • BootstrapUi facade — build your own class/style/attribute strings so custom components track package conventions.
  • CommandPalette facade — the single place to add, group, keyword-tag and authorise commands; wrap it in your own thin service so a future API change is a one-file edit.
  • Published config — check for shortcut and default-behaviour keys; prefer config over hardcoding in views, so ops can change them per environment.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib