This project walks you through building a complete blog platform from scratch using Laravel 12 and Livewire 3. By the end you will have a production-ready application with a public-facing blog and a reactive admin panel.
composer create-project laravel/laravel blog-platform
cd blog-platform
composer require livewire/livewire
php artisan livewire:install
php artisan make:model Post -mfsc
php artisan make:model Category -mfsc
php artisan make:model Tag -mfsc
php artisan make:model Comment -mfs
// Post migration
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->foreignId('category_id')->constrained();
$table->string('title');
$table->string('slug')->unique();
$table->text('excerpt')->nullable();
$table->longText('body');
$table->string('cover_image')->nullable();
$table->timestamp('published_at')->nullable();
$table->timestamps();
});
// Post model
class Post extends Model
{
use HasSlug, SoftDeletes;
public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
}
public function tags(): BelongsToMany
{
return $this->belongsToMany(Tag::class);
}
public function comments(): HasMany
{
return $this->hasMany(Comment::class)->whereNull('parent_id');
}
public function scopePublished(Builder $query): void
{
$query->whereNotNull('published_at')
->where('published_at', '<=', now());
}
}
php artisan make:livewire Admin/PostEditor
class PostEditor extends Component
{
public ?Post $post = null;
public string $title = '';
public string $body = '';
public ?int $categoryId = null;
public array $selectedTags = [];
#[Rule(['required', 'min:3'])]
public string $titleInput = '';
public function save(): void
{
$this->validate();
$this->post = Post::updateOrCreate(
['id' => $this->post?->id],
[
'title' => $this->title,
'slug' => Str::slug($this->title),
'body' => $this->body,
'category_id' => $this->categoryId,
]
);
$this->post->tags()->sync($this->selectedTags);
$this->dispatch('saved');
}
}
All Comments