PHPackages                             redbastie/swift - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. redbastie/swift

AbandonedArchivedLibrary[Framework](/categories/framework)

redbastie/swift
===============

A SwiftUI-inspired spin on Laravel Livewire.

1.2.2(5y ago)68893[1 issues](https://github.com/redbastie/swift/issues)MITPHP

Since Oct 13Pushed 4y ago4 watchersCompare

[ Source](https://github.com/redbastie/swift)[ Packagist](https://packagist.org/packages/redbastie/swift)[ Docs](https://github.com/redbastie/swift)[ RSS](/packages/redbastie-swift/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (3)Versions (23)Used By (0)

No Longer Maintained
====================

[](#no-longer-maintained)

Please check out my new package here:

It's a much better implementation of what this package was trying to do.

---

Laravel Swift
=============

[](#laravel-swift)

Say goodbye to HTML, CSS, and Javascript! Laravel Swift is a SwiftUI-inspired spin on Laravel Livewire. It utilizes Laravel, Livewire, Bootstrap, Font Awesome, &amp; more under the hood.

This package is my vision for the future of PHP development. It was created with backend/CRUD apps in mind, but will work for any type of application. It also comes with useful features like automatic routing and migrations, to speed you up and lower code abstractions even more.

In order to best utilize Swift, you should be familiar with the following:

- [Laravel](https://laravel.com)
- [Livewire](https://laravel-livewire.com)
- [Bootstrap](https://getbootstrap.com)
- [Font Awesome](https://fontawesome.com)

Requirements:

- A web server that can run Laravel 8
- NPM

Links:

- Support: [GitHub Issues](https://github.com/redbastie/swift/issues)
- Contribute: [GitHub Pulls](https://github.com/redbastie/swift/pulls)
- Donate: [PayPal](https://www.paypal.com/paypalme2/kjjdion)

[![](https://camo.githubusercontent.com/97df668b6f512889dc316972c212974841926b967149b78208679f9a1dfbef7d/68747470733a2f2f692e696d6775722e636f6d2f325a4c377242422e706e67)](https://www.youtube.com/watch?v=tyxeGM5ak1g)

Installation
------------

[](#installation)

This package was designed to work with clean Laravel 8 installs. All Swift apps come with basic auth scaffolding and user CRUD by default.

Install Laravel:

```
laravel new app

```

Configure the database in your `.env` file:

```
DB_DATABASE=app
DB_USERNAME=root
DB_PASSWORD=

```

Require Swift via composer:

```
composer require redbastie/swift

```

Run the installation command:

```
php artisan install:swift

```

Now you can visit your app URL and login using `user@example.com:password`, which was created via the `DatabaseSeeder` class.

Making Components
-----------------

[](#making-components)

Generate a basic component:

```
php artisan make:swift ComponentName

```

This will create a component inside of the `app/Http/Livewire` directory.

Generate a basic full page component:

```
php artisan make:page PageName

```

This will create a full page component inside of the `app/Http/Livewire` directory.

Generate CRUD scaffolding for a new model:

```
php artisan make:crud ModelName

```

This will create the model, factory, nav item, and CRUD components.

Generate CRUD for a new model with a shared trait for form fields &amp; rules:

```
php artisan make:crudtrait ModelName

```

This will create the model, factory, nav item, CRUD components and trait.

Generate a new Swift model:

```
php artisan make:swiftmodel ModelName

```

This will create the model and factory.

Using Components
----------------

[](#using-components)

Full page components should specify `$routeUri` &amp; `$pageTitle` properties:

```
public $routeUri = '/tao';
public $routeName = 'tao'; // optional
public $routeMiddleware = 'auth'; // optional
public $pageTitle = 'The Tao';

```

Swift components must implement a `view` method:

```
public function view()
{
    return S::div(
        S::livewire('layouts.navbar'),

        S::container(
            S::paragraph('Stop trying to control.')
        )
    );
}

```

Using child components in the `view`:

```
S::livewire('layouts.navbar'),

```

Available Components
--------------------

[](#available-components)

### Alert

[](#alert)

```
S::alert('Something happened!')->success(),

```

Methods: `dismissable`, `fade`, `primary`, `secondary`, `success`, `info`, `danger`, `warning`, `light`, `dark`

### Badge

[](#badge)

```
S::badge('New')->primary(),

```

Methods: `primary`, `secondary`, `success`, `info`, `danger`, `warning`, `light`, `dark`, `pill`

### Blockquote

[](#blockquote)

```
S::blockquote('Be like water.')->footer('The Tao'),

```

Methods: `footer`

### Breadcrumb

[](#breadcrumb)

```
S::breadcrumb(
    S::breadcrumbItem('Home'),
    S::breadcrumbItem('Page'),
),

```

Methods: none

### Breadcrumb Item

[](#breadcrumb-item)

```
S::breadcrumbItem('Home')->active(Route::is('home')),

```

Methods: `active`

### Button

[](#button)

```
S::button('Do Something')->primary()->click('doSomething'),

```

Methods: `submit`, `primary`, `secondary`, `success`, `info`, `danger`, `warning`, `light`, `dark`, `outlinePrimary`, `outlineSecondary`, `outlineSuccess`, `outlineInfo`, `outlineDanger`, `outlineWarning`, `outlineLight`, `outlineDark`, `link`, `active`, `sm`, `lg`, `block`, `disabled`

### Button Group

[](#button-group)

```
S::buttonGroup(
    S::button('Do Something')->primary()->click('doSomething'),
    S::button('Something Else')->secondary()->click('somethingElse'),
),

```

Methods: none

### Button Toolbar

[](#button-toolbar)

```
S::buttonToolbar(
    S::buttonGroup(
        S::button('Do Something')->primary()->click('doSomething'),
        S::button('Something Else')->secondary()->click('somethingElse'),
    ),
),

```

Methods: none

### Card

[](#card)

```
S::card()
    ->header('Hello World')
    ->body('The whole world belongs to you')
    ->footer('The Tao'),

```

Methods: `header`, `image`, `body`, `footer`

### Checkbox

[](#checkbox)

```
S::checkbox('agree')->label('Agree to TOS')->modelDefer(),

```

Methods: `label`, `checkboxLabel`, `help`, `switch`, `inline`, `disabled`, `model`, `modelDebounce`, `modelDefer`, `modelLazy`

### Code

[](#code)

```
S::code('$hello = $world;'),

```

Methods: none

### Col (Grid)

[](#col-grid)

```
S::col('Be like water.')->md(2),

```

Methods: `xs`, `auto`, `sm`, `smAuto`, `md`, `mdAuto`, `lg`, `lgAuto`, `xl`, `xlAuto`, `offset`, `offsetSm`, `offsetMd`, `offsetLg`, `offsetXl`

### Container

[](#container)

```
S::container(
    S::paragraph('In work, do what you enjoy.'),
),

```

Methods: none

### Div

[](#div)

```
S::div('The best athlete wants his opponent at his best.'),

```

Methods: none

### Dropdown

[](#dropdown)

```
S::dropdown()
    ->toggle(
        S::button('Dropdown')->primary()->dropdownToggle()
    )
    ->items(
        S::button('Do Something')->dropdownItem(),
        S::button('Something Else')->dropdownItem(),
    ),

```

Methods: `toggle`, `items`, `right`, `smRight`, `mdRight`, `lgRight`, `xlRight`, `left`, `smLeft`, `mdLeft`, `lgLeft`, `xlLeft`

### Each (Loop)

[](#each-loop)

```
S::each(['Red', 'Green', 'Blue'], function ($color, $key) {
    return S::div($key . ': ' . $color);
})->empty(
    S::paragraph('No colors to display.')
),

```

Methods: `empty`

### File

[](#file)

```
S::file('avatar')->label('Avatar')->placeholder('Choose avatar')->modelDefer(),

```

Methods: `label`, `placeholder`, `help`, `model`, `modelDebounce`, `modelDefer`, `modelLazy`

### Form

[](#form)

```
S::form(
    S::input('first_name')->label('First Name')->modelDefer(),
    S::input('last_name')->label('Last Name')->modelDefer(),
    S::button('Submit')->submit()->primary(),
)->submitPrevent('submitForm'),

```

Methods: `inline`, `submit`, `submitPrevent`, `submitSelf`, `submitStop`

### Form Group

[](#form-group)

```
S::formGroup(
    S::label('First Name'),
    S::input('first_name')->modelDefer(),
),

```

Methods: `label`

### Form Row

[](#form-row)

```
S::formRow(
    S::col(S::input('first')->placeholder('First')->model())->md(),
    S::col(S::input('last')->placeholder('Last')->model())->md(),
),

```

Methods: none

### Heading

[](#heading)

```
S::heading('Laravel Swift')->size(2),

```

Methods: `size`

### Horizontal Rule

[](#horizontal-rule)

```
S::horizontalRule(),

```

Methods: none

### Icon (Font Awesome)

[](#icon-font-awesome)

```
S::icon('pastafarianism'),

```

Methods: `solid`, `regular`, `light`, `duotone`, `brand`, `fw`, `xs`, `sm`, `lg`, `x`, `spin`, `pulse`

### If (Conditional)

[](#if-conditional)

```
// $color = 'Green';

S::if($color == 'Red', function () {
    return S::paragraph('The color is red.');
})->elseif($color == 'Green', function () {
    return S::paragraph('The color is green.');
})->else(function () {
    return S::paragraph('The color is blue.');
}),

```

Methods: `elseif`, `else`

### Iframe

[](#iframe)

```
S::iframe('http://maps.google.com/maps?q=pizza+pizza+oshawa&z=10&output=embed')->width('100%')->height(300),

```

Methods: `width`, `height`

### Image

[](#image)

```
S::image('https://i.imgur.com/zplGJnj.png')->alt('Time to kick it!'),

```

Methods: `alt`, `fluid`, `thumbnail`

### Input

[](#input)

```
S::input('email')->type('email')->label('Email Address')->modelDefer(),

```

Methods: `type`, `label`, `help`, `placeholder`, `sm`, `lg`, `disabled`, `readonly`, `keydown`, `model`, `modelDebounce`, `modelDefer`, `modelLazy`

### Input Group

[](#input-group)

```
S::inputGroup(
    S::input('first_name')->placeholder('First Name')->modelDefer(),
    S::input('last_name')->placeholder('First Name')->modelDefer(),
)->prepend(
    S::icon('user'),
),

```

Methods: `label`, `prepend`, `append`, `sm`, `lg`

### Label

[](#label)

```
S::label('Email Address'),

```

Methods: `for`

### Linebreak

[](#linebreak)

```
S::linebreak(),

```

Methods: none

### Link

[](#link)

```
S::link('Go To Reddit')->href('https://reddit.com'),

```

Methods: `href`, `target`, `active`, `disabled`, `stretched`

### List

[](#list)

```
S::list(
    S::listItem('Broccoli'),
    S::listItem('Carrot'),
    S::listItem('Lettuce'),
),

```

Methods: `ordered`, `unstyled`, `inline`

### List Item

[](#list-item)

```
S::listItem('Carrot'),

```

Methods: none

### List Group

[](#list-group)

```
S::listGroup(
    S::listGroupItem('Broccoli'),
    S::listGroupItem('Carrot'),
    S::listGroupItem('Lettuce'),
),

```

Methods: `flush`, `horizontal`

### List Group Item

[](#list-group-item)

```
S::listGroupItem('Broccoli'),

```

Methods: `primary`, `secondary`, `success`, `info`, `danger`, `warning`, `light`, `dark`, `action`, `active`, `disabled`

### Livewire (Component)

[](#livewire-component)

```
S::livewire('home', ['hello' => 'world']),

```

Methods: none

### Modal

[](#modal)

```
S::modal('create-modal')->heading('Create Contact')
    ->body(
        S::input('first_name')->label('First Name')->modelDefer(),
        S::input('last_name')->label('Last Name')->modelDefer(),
    )
    ->footer(
        S::button('Cancel')->secondary()->click('$emit', 'hideModal', 'create-modal'),
        S::button('Save')->primary()->click('save')
    )

```

Methods: `heading`, `body`, `footer`, `fade`, `sm`, `lg`, `xl`

### Navbar

[](#navbar)

```
S::navbar(
    S::navbarBrand(config('app.name'))->href('/'),
    S::navbarToggler(),
    S::navbarCollapse(
        S::navbarNav(
            S::navItem(S::navLink('Login')->href(route('login'))),
            S::navItem(S::navLink('Register')->href(route('register'))),
        ),
    ),
)->expandMd()->light(),

```

Methods: `expand`, `expandSm`, `expandMd`, `expandLg`, `expandXl`, `light`, `dark`

### Navbar Brand

[](#navbar-brand)

```
S::navbarBrand(config('app.name'))->href('/'),

```

Methods: `href`, `active`, `disabled`, `stretched`

### Navbar Collapse

[](#navbar-collapse)

```
S::navbarCollapse(
    S::navbarNav(
        S::navItem(S::navLink('Login')->href(route('login'))),
        S::navItem(S::navLink('Register')->href(route('register'))),
    ),
),

```

Methods: none

### Navbar Nav

[](#navbar-nav)

```
S::navbarNav(
    S::navItem(S::navLink('Login')->href(route('login'))),
    S::navItem(S::navLink('Register')->href(route('register'))),
),

```

Methods: none

### Navbar Toggler

[](#navbar-toggler)

```
S::navbarToggler(),

```

Methods: none

### Nav

[](#nav)

```
S::nav(
    S::navItem(S::navLink('First Tab')->active()),
    S::navItem(S::navLink('Second Tab')),
)->tabs(),

```

Methods: `tabs`, `pills`, `fill`, `justified`,

### Nav Dropdown

[](#nav-dropdown)

```
S::navDropdown()
    ->toggle(
        S::navLink(auth()->user()->name)->dropdownToggle(),
    )
    ->items(
        S::link('Profile')->dropdownItem()->href('/profile'),
        S::button('Logout')->dropdownItem()->click('logout'),
    ),

```

Methods: `toggle`, `items`, `right`, `smRight`, `mdRight`, `lgRight`, `xlRight`, `left`, `smLeft`, `mdLeft`, `lgLeft`, `xlLeft`

### Nav Link

[](#nav-link)

```
S::navLink('Home')->href('/'),

```

Methods: `href`, `active`, `disabled`, `stretched`

### Pagination

[](#pagination)

```
// $users = User::query()->paginate();

S::pagination($users),

```

Methods: none

### Paragraph

[](#paragraph)

```
S::paragraph('Close your eyes. Count to one. That is how long forever feels.'),

```

Methods: none

### Pre

[](#pre)

```
S::pre(json_encode(['Red', 'Green', 'Blue'], JSON_PRETTY_PRINT)),

```

Methods: none

### Progress Bar

[](#progress-bar)

```
S::progressBar(25)->label('Completed'),

```

Methods: `label`, `striped`, `animated`

### Radio

[](#radio)

```
S::radio('gender')->options(['Male', 'Female'])->modelDefer(),

```

Methods: `options`, `label`, `help`, `inline`, `disabled`, `model`, `modelDebounce`, `modelDefer`, `modelLazy`

### Row (Grid)

[](#row-grid)

```
S::row(
    S::col('Hello')->xs(),
    S::col('World')->xs(),
),

```

Methods: `noGutters`

### Select

[](#select)

```
S::select('gender')->options(['Male', 'Female'])->modelDefer(),

```

Methods: `options`, `label`, `placeholder`, `help`, `sm`, `lg`, `disabled`, `model`, `modelDebounce`, `modelDefer`, `modelLazy`

### Span

[](#span)

```
S::span('Do your work, then step back.'),

```

Methods: none

### Table

[](#table)

```
S::table(
    S::tableBody(
        S::tableRow(
            S::tableData('Name'),
            S::tableData('Email'),
        ),
    ),
),

```

Methods: `responsive`, `dark`, `striped`, `bordered`, `borderless`, `hover`, `sm`

### Table Body

[](#table-body)

```
S::tableBody(
    S::tableRow(
        S::tableData('Name'),
        S::tableData('Email'),
    ),
),

```

Methods: none

### Table Data

[](#table-data)

```
S::tableData('Name'),

```

Methods: `active`, `primary`, `secondary`, `success`, `info`, `danger`, `warning`, `light`, `dark`

### Table Head

[](#table-head)

```
S::tableHead(
    S::tableRow(
        S::tableHeader('Name'),
        S::tableHeader('Email'),
    ),
),

```

Methods: `light`, `dark`

### Table Header

[](#table-header)

```
S::tableHeader('Name'),

```

Methods: `active`, `primary`, `secondary`, `success`, `info`, `danger`, `warning`, `light`, `dark`

### Table Row

[](#table-row)

```
S::tableRow(
    S::tableHeader('Name'),
    S::tableHeader('Email'),
),

```

Methods: `active`, `primary`, `secondary`, `success`, `info`, `danger`, `warning`, `light`, `dark`

### Textarea

[](#textarea)

```
S::textarea('bio')->label('Biography')->modelDefer(),

```

Methods: `rows`, `label`, `help`, `placeholder`, `sm`, `lg`, `disabled`, `readonly`, `keydown`, `model`, `modelDebounce`, `modelDefer`, `modelLazy`

### View

[](#view)

```
S::view('my-view-name', ['hello' => 'world']),

```

Methods: none

Component Utilities
-------------------

[](#component-utilities)

### Bootstrap

[](#bootstrap)

All components have access to Bootstrap utilities. Their methods are named similar to the corresponding Bootstrap CSS classes.

For example, setting a background color:

```
S::div('Hello world!')->bgDanger(),

```

Adjusting paddings, margins, etc:

```
S::div('Hello world!')->bgDanger()->p(2)->mb(3),

```

A couple of Bootstrap Javascript utilities are available as well, like collapse:

```
S::button('Collapse Paragraph')->info()->collapseToggle('para'),
S::paragraph('In work, do what you enjoy.')->collapse('para'),

```

Showing/hiding modals:

```
S::button('Show Modal')->primary()->click('$emit', 'showModal', 'the-modal'),

S::modal('the-modal')->heading('The Modal')
    ->body(S::paragraph('Stop trying to control.'))
    ->footer(S::button('Close')->secondary()->click('$emit', 'hideModal', 'the-modal'),

```

Showing toasts:

```
$this->emit('toastError', 'Oh no! There was a problem.');

```

### Livewire

[](#livewire)

Livewire actions are mapped using the corresponding `wire:` conventions.

For example, setting `click` actions:

```
S::button('Delete')->danger()->click('deleteItem'),

```

In this case, you would have a `deleteItem` function inside your component.

`click` actions with one or more parameters:

```
S::link('Update')->clickPrevent('updateItem', $item->id),
S::button('Close')->secondary()->click('$emit', 'hideModal', 'the-modal'),

```

Modelling input elements:

```
S::input('name')->label('Name')->modelLazy(),
S::textarea('desc')->label('Description')->modelDefer(),

```

The input name is automatically wired via the specified model methods. You may access this data via the `$this->model` property array inside of your component. For example, `$this->model['name']`.

`loading` and `polling`:

```
S::span('Loading...')->loading(),
S::span(now())->poll(),

```

### Digging Deeper

[](#digging-deeper)

Take a look at the package [Traits](src/Traits) for a complete list of all utility methods along with their parameters.

Automation
----------

[](#automation)

### Automatic Routes

[](#automatic-routes)

When creating a full page Swift component, simply declare a `$routeUri` property in order to auto-route the component:

```
class Login extends SwiftComponent
{
    public $routeUri = '/login';

```

You can view a list of your routes via the `route:list` artisan command.

### Automatic Migrations

[](#automatic-migrations)

In order to use automatic migrations, simply specify a `migration` method in your model:

```
class Lead extends Model
{
    use SwiftModel;

    public function migration(Blueprint $table)
    {
        $table->id();
        $table->string('name');
        $table->timestamps();
    }

```

Now run the automatic migration command:

```
php artisan migrate:auto

```

The package uses Doctrine DBAL in order to diff the existing model table and make the necessary changes to it. If the table does not exist, it will create it.

You can also pass `--fresh` and/or `--seed` to the `migrate:auto` command in order to get fresh migrations and/or run your seeders afterwards:

```
php artisan migrate:auto --fresh --seed

```

If your app contains traditional migrations in the `database/migrations` folder, they will be handled before the automatic migrations.

### Automatic Fillables

[](#automatic-fillables)

Models containing the `SwiftModel` trait have automatic fillables, meaning their `$fillable` property is automatically generated via the model table column names.

Config, Views, &amp; Translations
---------------------------------

[](#config-views--translations)

The config, views, &amp; translation files can be published using the `vendor:publish` command.

###  Health Score

33

—

LowBetter than 75% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity22

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity64

Established project with proven stability

 Bus Factor1

Top contributor holds 93.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Recently: every ~8 days

Total

21

Last Release

1999d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/64050101?v=4)[redbastie](/maintainers/redbastie)[@redbastie](https://github.com/redbastie)

---

Top Contributors

[![redbastie](https://avatars.githubusercontent.com/u/64050101?v=4)](https://github.com/redbastie "redbastie (29 commits)")[![lancepioch](https://avatars.githubusercontent.com/u/1296882?v=4)](https://github.com/lancepioch "lancepioch (2 commits)")

### Embed Badge

![Health badge](/badges/redbastie-swift/health.svg)

```
[![Health](https://phpackages.com/badges/redbastie-swift/health.svg)](https://phpackages.com/packages/redbastie-swift)
```

###  Alternatives

[mhmiton/laravel-modules-livewire

Using Laravel Livewire in Laravel Modules package with automatically registered livewire components for every modules.

236409.6k9](/packages/mhmiton-laravel-modules-livewire)[raugadh/fila-starter

Laravel Filament Starter.

614.9k](/packages/raugadh-fila-starter)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
