Jetstream & Breeze

If you have a project with Jetstream/Breeze the maryUI installer adds a global prefix x-mary- on maryUI components to avoid naming collision. You are ready to go, just add maryUI components to your project.

Trade-off

Remember that starter kits add a dozen files that you probably will not use. You have to tweak and maintain them by yourself, because they are copied into your project.

On the other hand you can think it is a waste of time to build everything from the ground. But at least later you will have minimal code to maintain.

  • Stater kit: works out of the box, but adds extra code to maintain.
  • From the ground: needs extra time to setup, but adds minimal code.

Let's see how easy it is to implement exactly the features we need from the ground in no time, without starter kits.

  • Layout
  • Components
  • Authentication
  • Register
Go ahead and add Authentication and Register as described on the following sections.

Layout

There's not much to say here. As you can see on this Bootcamp, maryUI ships with a default layout. You can look for another layout alternative in the docs, but this is very personal.

Components

The maryUI components provide a great DX and you don't have to worry about maintaining the components by yourself.

Breeze

<div>
<x-input-label for="name" :value="__('Name')" />
<x-text-input id="name" class="block mt-1 w-full" type="text" name="name" :value="old('name')" required autofocus autocomplete="name" />
<x-input-error :messages="$errors->get('name')" class="mt-2" />
</div>

Jetstream

<div>
<x-label for="name" value="{{ __('Name') }}" />
<x-input id="name" class="block mt-1 w-full" type="text" name="name" :value="old('name')" required autofocus autocomplete="name" />
</div>

maryUI

<x-mary-input label="Name" wire:model="name" />

Authentication

Here is what routes/web.php looks like with Authentication.

  • Login route.
  • Logout route.
  • Protect some routes.

Go ahead and copy/paste this.

use Illuminate\Support\Facades\Route;
use Livewire\Volt\Volt;
 
// Users will be redirected to this route if not logged in
Volt::route('/login', 'login')->name('login');
 
// Define the logout
Route::get('/logout', function () {
auth()->logout();
request()->session()->invalidate();
request()->session()->regenerateToken();
 
return redirect('/');
});
 
// Protected routes here
Route::middleware('auth')->group(function () {
Volt::route('/', 'index');
Volt::route('/users', 'users.index');
Volt::route('/users/create', 'users.create');
Volt::route('/users/{user}/edit', 'users.edit');
// ... more
});

Create an empty layout at resources/views/components/layouts/empty.blade.php to use it as our login page.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, viewport-fit=cover">
<meta name="csrf-token" content="{{ csrf_token() }}">
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="min-h-screen font-sans antialiased bg-base-200/50 dark:bg-base-200">
{{-- You could elaborate the layout here --}}
{{-- The important part is to have a different layout from the main app layout --}}
<x-main full-width>
<x-slot:content>
{{ $slot }}
</x-slot:content>
</x-main>
</body>
</html>

And here is the login component.

php artisan make:volt login --class
use Livewire\Attributes\Layout;
use Livewire\Attributes\Rule;
use Livewire\Attributes\Title;
use Livewire\Volt\Component;
 
new
#[Layout('components.layouts.empty')] // <-- Here is the `empty` layout
#[Title('Login')]
class extends Component {
 
#[Rule('required|email')]
public string $email = '';
 
#[Rule('required')]
public string $password = '';
 
public function mount()
{
// It is logged in
if (auth()->user()) {
return redirect('/');
}
}
 
public function login()
{
$credentials = $this->validate();
 
if (auth()->attempt($credentials)) {
request()->session()->regenerate();
 
return redirect()->intended('/');
}
 
$this->addError('email', 'The provided credentials do not match our records.');
}
}
<div class="md:w-96 mx-auto mt-20">
<div class="mb-10">Cool image here</div>
 
<x-form wire:submit="login">
<x-input label="E-mail" wire:model="email" icon="o-envelope" inline />
<x-input label="Password" wire:model="password" type="password" icon="o-key" inline />
 
<x-slot:actions>
<x-button label="Create an account" class="btn-ghost" link="/register" />
<x-button label="Login" type="submit" icon="o-paper-airplane" class="btn-primary" spinner="login" />
</x-slot:actions>
</x-form>
</div>

That is it!

Try to navigate to a protected route, and you will be redirected to the login page. The default app layout shipped with maryUI shows the authenticated user and logout button for you.

Register

Add this public extra route to web.php.

use Livewire\Volt\Volt;
 
Volt::route('/register', 'register');

Create the registration form.

php artisan make:volt register --class
use App\Models\User;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Rule;
use Livewire\Attributes\Title;
use Livewire\Volt\Component;
use Illuminate\Support\Facades\Hash;
 
new
#[Layout('components.layouts.empty')] // <-- The same `empty` layout
#[Title('Login')]
class extends Component {
 
#[Rule('required')]
public string $name = '';
 
#[Rule('required|email|unique:users')]
public string $email = '';
 
#[Rule('required|confirmed')]
public string $password = '';
 
#[Rule('required')]
public string $password_confirmation = '';
 
public function mount()
{
// It is logged in
if (auth()->user()) {
return redirect('/');
}
}
 
public function register()
{
$data = $this->validate();
 
$data['avatar'] = '/empty-user.jpg';
$data['password'] = Hash::make($data['password']);
 
$user = User::create($data);
 
auth()->login($user);
 
request()->session()->regenerate();
 
return redirect('/');
}
}
<div class="md:w-96 mx-auto mt-20">
<div class="mb-10">Cool image here</div>
 
<x-form wire:submit="register">
<x-input label="Name" wire:model="name" icon="o-user" inline />
<x-input label="E-mail" wire:model="email" icon="o-envelope" inline />
<x-input label="Password" wire:model="password" type="password" icon="o-key" inline />
<x-input label="Confirm Password" wire:model="password_confirmation" type="password" icon="o-key" inline />
 
<x-slot:actions>
<x-button label="Already registered?" class="btn-ghost" link="/login" />
<x-button label="Register" type="submit" icon="o-paper-airplane" class="btn-primary" spinner="register" />
</x-slot:actions>
</x-form>
</div>

It is done!

Hit the /register route on browser and create an account.

As you are logged in, file uploads will work in the HTML Editor component

maryUI
Sponsor