« Back
Written by Nuno Maduro on July 27, 2023

Todo Application With Laravel Folio and Volt

In case you missed it, at Laravel, we recently released two new packages:

  • Folio: a powerful page-based router designed to simplify routing in Laravel applications.
  • Volt: an elegantly crafted functional API for Livewire, allowing component’s PHP logic and Blade templates to coexist in the same file.

In this article, we will build a simple Todo application using these two packages. To get started, let’s first create a new Laravel application:

laravel new todo-app
cd todo-app

After, let’s create a new Todo model and migration:

php artisan make:model Todo -m

Next, let’s add the column description to the database/migrations/2023_xx_xx_xxxxxx_create_todos_table.php migration:

Schema::create('todos', function (Blueprint $table) {
    $table->id();
    $table->string('description'); // <-- Add this line
    $table->timestamps();
});

And, let’s allow the description column to be mass assignable in the app/Models/Todo.php model:

class Todo extends Model
{
    use HasFactory;

    protected $fillable = [
        'description', // <-- Add this line
    ];
}

After, lets set DB_CONNECTION=sqlite in the .env file and run the migrations:

php artisan migrate

At this point, we are ready to start building the “front-end” of our application. To do so, let’s install the laravel/folio and livewire/volt packages:

composer require laravel/folio:^1.0@beta livewire/livewire:^3.0@beta livewire/volt:^1.0@beta

Next, let’s install both Folio and Volt:

php artisan folio:install
php artisan volt:install

After, let’s create a new Folio page to list all the todos:

php artisan make:folio todos

This command will create an resources/views/pages/todos.blade.php file. Let’s open this file and replace its content with the following:

<?php

use function Livewire\Volt\state;
use App\Models\Todo;

state(description: '', todos: fn () => Todo::all());

$addTodo = function () {
    Todo::create(['description' => $this->description]);

    $this->description = '';
    $this->todos = Todo::all();
}; ?>

<html>
    <head>
        <title>Todos</title>
    </head>
    <body>
    @volt
        <div>
            <h1>Add Todo </h1>
            <form wire:submit="addTodo">
                <input type="text" wire:model="description">
                <button type="submit">Add</button>
            </form>

            <h1>Todos</h1>
            <ul>
                @foreach ($todos as $todo)
                    <li>{{ $todo->description }}</li>
                @endforeach
            </ul>
        </div>
    @endvolt
    </body>
</html>

And finally, lets php artisan serve our application and visit the /todos route:

Todo App Preview

Note that, with a single file, we have created a route and its related logic and template. This was possible because:

  • Folio automatically creates a route for Blade templates located in the resources/views/pages directory.
  • Volt allows us to create an anonymous Livewire component directly in our Folio page using the @volt Blade directive. This simply a shortcut to not have to create a new <livewire:todos /> component in a separate file.

And that’s it! We have built a simple Todo application using Laravel Folio and Volt. If you want to learn more about these two packages, check out their documentation:

We hope you enjoy this new addition to the Laravel and Livewire ecosystems. At Laravel, we’re committed to providing you with the most robust and developer friendly PHP experience in the world. Build something amazing!


I hope you have enjoyed this article. If yes, please consider supporting my work — my mission is to spend more time maintaining the dozens of projects that I've written/collaborated on over the years and continue developing new projects to make PHP development more productive and enjoyable.

github.com/sponsors/nunomaduro