{"id":13423020,"url":"https://github.com/bastinald/ui","last_synced_at":"2025-10-12T07:23:34.681Z","repository":{"id":46835166,"uuid":"369320892","full_name":"bastinald/ui","owner":"bastinald","description":"Laravel Livewire \u0026 Bootstrap 5 UI \u0026 CRUD starter kit.","archived":false,"fork":false,"pushed_at":"2023-01-23T02:08:39.000Z","size":206,"stargazers_count":112,"open_issues_count":4,"forks_count":33,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-24T10:53:49.314Z","etag":null,"topics":["auth","bootstrap","crud","laravel","livewire","package","php","scaffolding","ui"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bastinald.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-05-20T19:45:54.000Z","updated_at":"2025-02-04T23:43:37.000Z","dependencies_parsed_at":"2023-02-12T19:45:29.658Z","dependency_job_id":null,"html_url":"https://github.com/bastinald/ui","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bastinald%2Fui","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bastinald%2Fui/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bastinald%2Fui/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bastinald%2Fui/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bastinald","download_url":"https://codeload.github.com/bastinald/ui/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248675233,"owners_count":21143763,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auth","bootstrap","crud","laravel","livewire","package","php","scaffolding","ui"],"created_at":"2024-07-30T23:01:05.427Z","updated_at":"2025-10-12T07:23:29.662Z","avatar_url":"https://github.com/bastinald.png","language":"PHP","readme":"## bastinald/ui\n\nLaravel Livewire \u0026 Bootstrap 5 UI \u0026 CRUD starter kit. This package is a modernized version of the old `laravel/ui` package for developers who prefer using Bootstrap 5 and full page Livewire components to build their projects. It also comes with a few features to boost your development speed even more.\n\n### Requirements\n\n- Laravel 8\n- NPM\n\n### Features\n\n- Bootstrap 5 pre-configured\n- Full auth scaffolding including login, register, forgot password, profile updating, etc.\n- Commands for making models, components, and CRUD\n- PWA capabilities\n- Simply app versioning\n- Automatic model migrations\n- Automatic full page component routing\n- Automatic attribute hashing\n- Automatic user timezones\n- Easy form data manipulation via a single property\n- Dynamic Livewire Bootstrap modals\n- Custom Blade components\n- Font Awesome icons\n- \u0026 more\n\n### Documentation\n\n- [Installation](#installation)\n- [Commands](#commands)\n- [Automatic Migrations](#automatic-migrations)\n- [Automatic Routing](#automatic-routing)\n- [Automatic Attribute Hashing](#automatic-attribute-hashing)\n- [Form Data Manipulation](#form-data-manipulation)\n- [Dynamic Bootstrap Modals](#dynamic-bootstrap-modals)\n- [Blade Components](#blade-components)\n- [Font Awesome Icons](#font-awesome-icons)\n- [Publishing Assets](#publishing-assets)\n\n## Installation\n\nThis package was designed to work with fresh Laravel projects.\n\nInstall Laravel via Valet, Docker, or whatever you prefer:\n\n```console\nlaravel new my-project\n```\n\nConfigure the `.env` app, database, and mail variables:\n\n```env\nAPP_*\nDB_*\nMAIL_*\n```\n\nRequire this package via composer:\n\n```console\ncomposer require bastinald/ui\n```\n\nRun the `ui:install` command:\n\n```console\nphp artisan ui:install\n```\n\nOnce the installation is complete, you should be able to visit your app URL and login with `user@example.com` as the email, and `password` as the password. This was seeded for you to test with.\n\n## Commands\n\n### Installing UI\n\n```console\nphp artisan ui:install\n```\n\nThis command will create your Livewire auth components \u0026 views, update your User model \u0026 factory, migrate \u0026 seed a default User, configure Bootstrap 5 JavaScript \u0026 SCSS through NPM/Webpack, create an IDE helper file, and run the necessary NPM commands.\n\n### Making Models\n\n```console\nphp artisan ui:model {class} {--force}\n```\n\nThis will make a model with an automatic `migration` method included. It will also make a factory for the model whose definition points to the model `definition` method.\n\nUse the `--force` to overwrite existing models \u0026 factories.\n\n### Making Components\n\n```console\nphp artisan ui:component {class} {--f|--full} {--m|--modal} {--force}\n```\n\nThis will make a Livewire component and view depending on which option you pass to it. Use the `-f` option to create a full page component with a `route` method, the `-m` option to create a modal component, or neither to create a partial component.\n\nUse the `--force` to overwrite existing components \u0026 views.\n\n### Making CRUD\n\n```console\nphp artisan ui:crud {path}\n```\n\nThis will make CRUD components \u0026 views for a given component path/namespace. This includes an index, create, read, update, and delete. It also comes with searching, sorting, and filtering, which is easily customizable inside the index component class.\n\nFor making CRUD inside of subfolders, simply use slashes or dot notation:\n\n```console\n# no subfolder\nphp artisan ui:crud Users \n\n# in an \"Admin\" subfolder\nphp artisan ui:crud Admin/Users \n```\n\nIf the model (e.g. `User` in the example above) does not already exist when making CRUD, it will ask if you want to make it. After generating CRUD, all you need to do is add your model fields to the component views. Check out the `Users` component \u0026 views that come with the package when you run `ui:install` for an example.\n\nUse the `--force` to overwrite existing CRUD components \u0026 views.\n\n### Running Automatic Migrations\n\n```console\nphp artisan ui:migrate {--f|--fresh} {--s|--seed} {--force}\n```\n\nThis command goes through your model `migration` methods and compares their schema's with the existing database table schema's. If any changes need to be made, it applies them automatically via Doctrine.\n\nThis command works well alongside traditional migration files. When you run this command, it will run your traditional migrations first, and the automatic migrations after. This is useful for cases where you don't need to couple a database table with a model (pivots, etc.).\n\nUse the `-f` option to wipe the database (fresh), and the `-s` option to run your seeders after migration is complete. The `--force` is required to run migrations in production environments.\n\n## Automatic Migrations\n\nThis package promotes the usage of automatic migrations.\n\nTo use automatic migrations, specify a `migration` method inside your models:\n\n```php\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Schema\\Blueprint;\n\nclass User extends Model\n{\n    public function migration(Blueprint $table)\n    {\n        $table-\u003eid();\n        $table-\u003estring('name');\n        $table-\u003estring('email')-\u003eunique();\n        $table-\u003etimestamp('email_verified_at')-\u003enullable();\n        $table-\u003estring('password');\n        $table-\u003erememberToken();\n        $table-\u003etimestamp('created_at')-\u003enullable();\n        $table-\u003etimestamp('updated_at')-\u003enullable();\n    }\n}\n```\n\nOr, make a new model via the `ui:model` command, which will include a `migration` method for you:\n\n```console\nphp artisan ui:model Vehicle\n```\n\nThe `migration` method uses the `$table` Blueprint variable, just like in traditional Laravel migration files. As mentioned previously, when you run the `ui:migrate` command, it will compare your existing database table schema's to your model `migration` methods and apply the necessary changes via Doctrine. With this, you'll no longer have to manage tons of migration files.\n\n## Automatic Routing\n\nThis package also promotes the usage of automatic routing.\n\nTo use automatic routing, specify a `route` method inside your full page Livewire components:\n\n```php\nuse Illuminate\\Support\\Facades\\Route;\nuse Livewire\\Component;\n\nclass Home extends Component\n{\n    public function route()\n    {\n        return Route::get('/home', static::class)\n            -\u003ename('home')\n            -\u003emiddleware('auth');\n    }\n}\n```\n\nOr, just run the `ui:component` command with the `-f` option to quickly make a full page component including a `route` method:\n\n```console\nphp artisan ui:component ContactUs -f\n```\n\nThe `route` method returns the Laravel `Route` facade, just like you would use in route files. This means that your component route can do anything a normal Laravel route can do. These routes are registered through the package service provider automatically, so you'll no longer have to manage messy route files.\n\n## Automatic Attribute Hashing\n\nThe `HasHashes` traits allows you to specify model attributes you want to hash automatically when they are saving to the database.\n\nTo use automatic hashing, use the `HashHashes` trait and specify a `hashes` property with the attributes that should be automatically hashed:\n\n```php\nuse Bastinald\\Ui\\Traits\\HasHashes;\nuse Illuminate\\Foundation\\Auth\\User as Authenticatable;\n\nclass User extends Authenticatable\n{\n    use HasHashes;\n\n    protected $hashes = ['password'];\n}\n```\n\nThis trait will only automatically hash attribute values that are not already hashed, so it will not slow down seeders.\n\n## Form Data Manipulation\n\nThe `WithModel` traits makes managing form data inside your Livewire components easy. Normally, you'd have to specify a property for every one of your form inputs. With this trait, all of your form data will be present in a `$model` property array. This trait also comes with some handy methods to get, set, and validate the data.\n\n### Binding Model Data\n\nPlease note that all of the package `x-ui` Blade components will properly map the inputs to the component `$model` property and show relevant errors. If you are using your own HTML inputs, just be sure to prepend `model.` to the `wire:model` attribute.\n\nFor example, if you're using the package components, just specify the `$model` key directly via the `model` attribute:\n\n```html\n\u003cx-ui::input :label=\"__('First Name')\" type=\"text\" model=\"first_name\"/\u003e\n```\n\nIf you're using your own HTML inputs, make sure you prepend `model.` to the `wire:model.*` attribute:\n\n```html\n\u003clabel\u003eFirst Name\u003c/label\u003e\n\u003cinput type=\"text\" wire:model.defer=\"model.first_name\"/\u003e\n@error('first_name') \u003cp class=\"text-danger\"\u003e{{ $message }}\u003c/p\u003e @enderror\n```\n\nNotice how you don't prepend `model.` to the `@error`. Error messages use the `$model` key via the `validateModel` method, so you only need to prepend `model.` on the inputs.\n\n### Getting Model Data\n\nGetting all model data as an array:\n\n```php\n$this-\u003egetModel();\n```\n\nGetting an array of data:\n\n```php\n$this-\u003egetModel(['email', 'password']);\n```\n\nIf you pass an array to the `getModel` property, it will always return an array, even if you only use a single key. This is useful for quickly updating a single model column via `create` or `update`.\n\nGetting a single value:\n\n```php\n$this-\u003egetModel('first_name', 'Joe');\n```\n\nYou can specify a default value via the second parameter, or omit it entirely.\n\n### Setting Model Data\n\nSetting an array of values:\n\n```php\n$this-\u003esetModel([\n    'name' =\u003e 'Joe',\n    'email' =\u003e 'joe@example.com',\n]);\n```\n\nSetting a single value:\n\n```php\n$this-\u003esetModel('name', 'Joe');\n```\n\n### Resetting Model Data\n\nYou can reset all model data easily:\n\n```php\n$this-\u003eresetModel();\n```\n\n### Validating Model Data\n\nThe `validateModel` method works the same as the Livewire `validate` method, but will use the `$model` data for validation.\n\nYou can use it alongside a `rules` method:\n\n```php\npublic function rules()\n{\n    return [\n        'email' =\u003e ['required', 'email'],\n        'password' =\u003e ['required'],\n    ];\n}\n\npublic function login()\n{\n    $this-\u003evalidateModel();\n    \n    // log the user in\n}\n```\n\nOr by itself, with rules passed directly:\n\n```php\npublic function login()\n{\n    $this-\u003evalidateModel([\n        'email' =\u003e ['required', 'email'],\n        'password' =\u003e ['required'],\n    ]);\n    \n    // log the user in\n}\n```\n\n## Dynamic Bootstrap Modals\n\nThis package allows you to show Livewire components as modals dynamically by emitting a simple event. No more having to manage modal components everywhere in your views.\n\n### Making Modals\n\nJust use the `ui:component` command with the `-m` option to make a new modal component:\n\n```console\nphp artisan ui:component TermsOfService -m\n```\n\nThis will create a partial Livewire component and a view that contains the Bootstrap modal classes.\n\n### Showing Modals\n\nTo show modals, just emit the `showModal` event.\n\nYou can emit this from your component views:\n\n```html\n\u003cbutton type=\"button\" wire:click=\"$emit('showModal', 'auth.password-change')\"\u003e\n    {{ __('Change Password') }}\n\u003c/button\u003e\n```\n\nOr from the component classes themselves:\n\n```php\n$this-\u003eemit('showModal', 'auth.password-change');\n```\n\nNotice that the second parameter is using the Livewire component class alias. So in this example, `auth.password-change` actually points to the `Auth\\PasswordChange` component.\n\n### Passing Mount Parameters\n\nYou can pass any parameters you want to your modal component `mount` method by specifying them in the `showModal` event:\n\nPassing parameters via component views:\n\n```html\n\u003cbutton type=\"button\" wire:click=\"$emit('showModal', 'users.update', {{ $user-\u003eid }})\"\u003e\n    {{ __('Update User') }}\n\u003c/button\u003e\n```\n\nOr from a component class:\n\n```php\n$this-\u003eemit('showModal', 'users.update', $user-\u003eid);\n```\n\nNow, in our component `mount` method, we can use this parameter:\n\n```php\npublic $user;\n\npublic function mount(User $user)\n{\n    $this-\u003euser = $user;\n}\n```\n\nNotice how even model binding works here. If you need to pass more than one parameter, just keep adding them to the `showModal` emit, separated by a comma.\n\n### Hiding Modals\n\nHide the currently open modal via the `hideModal` event:\n\n```html\n\u003cbutton type=\"button\" wire:click=\"$emit('hideModal')\"\u003e\n    {{ __('Close') }}\n\u003c/button\u003e\n```\n\nOr, through component classes:\n\n```php\n$this-\u003eemit('hideModal');\n```\n\nYou can also hide the modal through regular Bootstrap `data-bs-toggle` buttons:\n\n```html\n\u003cbutton type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\"\u003e\n    {{ __('Cancel') }}\n\u003c/button\u003e\n```\n\n## Blade Components\n\nThis package comes with some handy Blade components, ensuring that you stay DRY, while keeping your markup nice and neat.\n\n### Input\n\nA form input:\n\n```html\n\u003cx-ui::input :label=\"__('Email')\" type=\"email\" model=\"email\"/\u003e\n```\n\nAvailable props:\n\n- `label`: the input label\n- `type`: the input type e.g. `text`, `email`, `file`\n- `model`: the key for the component `$model` property\n- `lazy`: bind the model value on change\n- `debounce=\"x\"`: debounce the model value after `x` ms (defaults to `150`)\n\nIf `lazy` and `debounce` are not used, `defer` is the default.\n\n### Textarea\n\nA textarea input:\n\n```html\n\u003cx-ui::textarea :label=\"__('Biography')\" rows=\"5\" model=\"biography\"/\u003e\n```\n\nAvailable props:\n\n- `label`: the textarea label\n- `model`: the key for the component `$model` property\n- `lazy`: bind the model value on change\n- `debounce=\"x\"`: debounce the model value after `x` ms (defaults to `150`)\n\nThe `lazy` and `debounce` props work the same as the `input` component.\n\n### Select\n\nA select input:\n\n```html\n\u003cx-ui::select :label=\"__('Color')\" :options=\"['Red', 'Blue']\" model=\"color\"/\u003e\n```\n\nAvailable props:\n\n- `label`: the select label\n- `options`: an array of select options\n- `model`: the key for the component `$model` property\n- `lazy`: bind the model value on change\n\nThe `options` array can be an indexed or associative array. If the array is associative, the array keys will be used for the option values, and the array values will be used for the option labels. If the array is indexed, it's values will be used for both the option values and labels.\n\n### Radio\n\nA radio input:\n\n```html\n\u003cx-ui::radio :label=\"__('Color')\" :options=\"['Red', 'Blue']\" model=\"color\"/\u003e\n```\n\nAvailable props:\n\n- `label`: the radio label\n- `options`: an array of radio options\n- `model`: the key for the component `$model` property\n- `lazy`: bind the model value on change\n\nThe `options` array works the same as the `select` component.\n\n### Checkbox\n\nA checkbox input:\n\n```html\n\u003cx-ui::checkbox :label=\"__('Agree to TOS')\" model=\"agree\"/\u003e\n```\n\nAvailable props:\n\n- `label`: the checkbox label\n- `model`: the key for the component `$model` property\n- `lazy`: bind the model value on change\n\n### Dropdown\n\nA dropdown button:\n\n```html\n\u003cx-ui::dropdown icon=\"filter\" :label=\"__($filter)\"\u003e\n    @foreach($filters as $filter)\n        \u003cx-ui::dropdown-item :label=\"__($filter)\" click=\"$set('filter', '{{ $filter }}')\"/\u003e\n    @endforeach\n\u003c/x-ui::dropdown\u003e\n```\n\nAvailable props:\n\n- `icon`: the dropdown button icon (Font Awesome)\n- `label`: the dropdown button label\n- `position`: the dropdown menu position (defaults to `end`)\n- `slot`: the dropdown items\n\n### Dropdown Item\n\nA dropdown item button:\n\n```html\n\u003cx-ui::dropdown-item :label=\"__('Logout')\" click=\"logout\"/\u003e\n```\n\nAvailable props:\n\n- `label`: the dropdown item button label\n- `route`: the route to link to\n- `url`: the URL to link to\n- `href`: the link href\n- `click`: the Livewire click action\n\n### Action\n\nA CRUD action button:\n\n```html\n\u003cx-ui::action icon=\"eye\" :title=\"__('Read')\"\n    click=\"$emit('showModal', 'users.read', {{ $user-\u003eid }})\"/\u003e\n```\n\nAvailable props:\n\n- `icon`: the action button icon (Font Awesome)\n- `title`: the action button title\n- `route`: the route to link to\n- `url`: the URL to link to\n- `href`: the link href\n- `click`: the Livewire click action\n\n### Pagination\n\nResponsive pagination links:\n\n```html\n\u003cx-ui::pagination :links=\"$users\"/\u003e\n```\n\nAvailable props:\n\n- `links`: the pagination link results\n- `count`: show the count to the left (`true` or `false`)\n- `justify`: the justification for the links\n\n### Icon\n\nA Font Awesome icon:\n\n```html\n\u003cx-ui::icon name=\"laravel\" style=\"brands\"/\u003e\n```\n\nAvailable props:\n\n- `name`: the icon name\n- `style`: the icon style e.g. `solid`, `regular` (default set in config)\n\n## Font Awesome Icons\n\nWhen running the `ui:install` command, you are given the option to install Font Awesome free or pro. If you select pro, you are required to have a global NPM token configured.\n\nFor information on how to configure this token, [please see the Font Awesome documentation](https://fontawesome.com/v5.15/how-to-use/on-the-web/setup/using-package-managers#installing-pro).\n\n## Publishing Assets\n\nPublish the package config, stubs, and views via the `vendor:publish` command:\n\n```console\nphp artisan vendor:publish\n```\n\nSelect `ui:config`, `ui:stubs`, `ui:views`, or `ui` for all assets.\n\n### Using Custom Stubs\n\nOnce you have published the package config and stub files, the stubs will be located in the `resources/stubs/vendor/ui` folder.\n\nUpdate the `config/ui.php` file and point the `stub_path` to this path:\n\n```php\n'stub_path' =\u003e resource_path('stubs/vendor/ui'),\n```\n\nThe commands will now use this path for the stubs. Customize them to your needs.\n","funding_links":[],"categories":["UI"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbastinald%2Fui","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbastinald%2Fui","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbastinald%2Fui/lists"}