Kritim Yantra
Jun 10, 2025
Imagine building a LEGO castle:
No glue, no duct tape β everything snaps together perfectly! Today, weβll build a fully functional Todo app without writing a single API endpoint. Letβs dive in!
laravel new inertia-todo
cd inertia-todo
composer require inertiajs/inertia-laravel
npm install @inertiajs/react react react-dom
Update resources/views/app.blade.php
:
<!DOCTYPE html>
<html>
<head>
@vite('resources/js/app.js')
</head>
<body>
<div id="app" data-page="{{ json_encode($page) }}"></div>
</body>
</html>
Create resources/js/app.js
:
import { createInertiaApp } from '@inertiajs/react';
import { createRoot } from 'react-dom/client';
createInertiaApp({
resolve: name => require(`./Pages/${name}`),
setup({ el, App, props }) {
createRoot(el).render(<App {...props} />);
},
});
php artisan make:model Todo -m
Edit migration file (database/migrations/..._create_todos_table.php
):
public function up() {
Schema::create('todos', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->boolean('completed')->default(false);
$table->timestamps();
});
}
Run migration:
php artisan migrate
php artisan make:controller TodoController
Edit app/Http/Controllers/TodoController.php
:
use App\Models\Todo;
use Inertia\Inertia;
use Illuminate\Http\Request;
class TodoController extends Controller {
// Show all todos
public function index() {
return Inertia::render('Todos/Index', [
'todos' => Todo::latest()->get()
]);
}
// Add new todo
public function store(Request $request) {
Todo::create($request->validate(['title' => 'required|min:3']));
return redirect()->back();
}
// Update completion status
public function update(Request $request, Todo $todo) {
$todo->update(['completed' => $request->completed]);
return redirect()->back();
}
// Delete todo
public function destroy(Todo $todo) {
$todo->delete();
return redirect()->back();
}
}
Edit routes/web.php
:
use App\Http\Controllers\TodoController;
Route::get('/', [TodoController::class, 'index']);
Route::post('/todos', [TodoController::class, 'store']);
Route::put('/todos/{todo}', [TodoController::class, 'update']);
Route::delete('/todos/{todo}', [TodoController::class, 'destroy']);
resources/js/Pages/Todos/Index.jsx
)import { Head, Link } from '@inertiajs/react';
import TodoForm from './Form';
import TodoList from './List';
export default function TodoIndex({ todos }) {
return (
<div className="max-w-2xl mx-auto p-8">
<Head title="Your Todo List" />
<h1 className="text-3xl font-bold mb-6">β¨ Your Todo List</h1>
<TodoForm />
<TodoList todos={todos} />
</div>
);
}
resources/js/Pages/Todos/Form.jsx
)import { useForm } from '@inertiajs/react';
export default function TodoForm() {
const { data, setData, post, processing } = useForm({
title: ''
});
const submit = (e) => {
e.preventDefault();
post('/todos');
};
return (
<form onSubmit={submit} className="mb-8">
<input
type="text"
value={data.title}
onChange={e => setData('title', e.target.value)}
placeholder="Buy groceries..."
className="w-full p-3 border rounded"
disabled={processing}
/>
<button
type="submit"
className="mt-2 bg-blue-500 text-white p-2 rounded"
disabled={processing}
>
{processing ? 'Adding...' : 'Add Task'}
</button>
</form>
);
}
resources/js/Pages/Todos/List.jsx
)import { Link } from '@inertiajs/react';
export default function TodoList({ todos }) {
return (
<div className="space-y-4">
{todos.map(todo => (
<div key={todo.id} className="flex items-center justify-between p-4 bg-white shadow rounded">
<div className="flex items-center">
<input
type="checkbox"
checked={todo.completed}
onChange={() => Inertia.put(`/todos/${todo.id}`, {
completed: !todo.completed
})}
className="mr-3 h-5 w-5"
/>
<span className={todo.completed ? 'line-through text-gray-500' : ''}>
{todo.title}
</span>
</div>
<button
onClick={() => Inertia.delete(`/todos/${todo.id}`)}
className="text-red-500 hover:text-red-700"
>
Delete
</button>
</div>
))}
</div>
);
}
php artisan serve
npm run dev
http://localhost:8000
Behold! Your fully functional Todo app:
User adds task:
store()
method β Database User checks todo:
update()
method User deletes item:
destroy()
π‘ Pro Tip: Add Laravel Breeze for authentication:
composer require laravel/breeze --dev php artisan breeze:install react
Enhance your Todo app with:
Questions? Drop them below! π
Transform from beginner to Laravel expert with our personalized Coaching Class starting June 20, 2025. Limited enrollment ensures focused attention.
1-hour personalized coaching
Build portfolio applications
Industry-standard techniques
Interview prep & job guidance
Complete your application to secure your spot
Thank you for your interest in our Laravel mentorship program. We'll contact you within 24 hours with next steps.
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google