Rapyd CRUD demo

Three pages, three files each: a Livewire component, a Blade view and a route. Every page shows its own source code underneath, so you can see exactly how little it takes.

No demo data yet. Populate the database

module structure

demo-module/
├─ Livewire/
│  ├─ Home.php
│  ├─ ArticlesTable.php
│  ├─ ArticlesView.php
│  └─ ArticlesEdit.php
├─ Views/
│  ├─ home.blade.php
│  ├─ articles_table.blade.php
│  ├─ articles_view.blade.php
│  ├─ articles_edit.blade.php
│  ├─ menu.blade.php
│  └─ frontend_menu.blade.php
├─ Models/               Article.php, Author.php
├─ Database/             Migrations/, Seeders/
├─ config.php            layout, menu entry
├─ routes.php
└─ DemoModuleServiceProvider.php

route

routes.php


Route::get('demo'Home::class)
    ->
middleware(['web'])
    ->
name('demo')
    ->
crumbs(fn ($crumbs) => $crumbs->push('Demo'route('demo')));

component

Livewire/Home.php


<?php

namespace App\Modules\Demo\Livewire;

use 
App\Modules\Demo\Database\Seeders\DemoSeeder;
use 
App\Modules\Demo\Models\Article;
use 
Illuminate\Support\Facades\Artisan;
use 
Livewire\Component;

class 
Home extends Component
{
    public 
bool $db_filled false;

    public function 
mount(): void
    
{
        
$this->db_filled Article::query()->exists();
    }

    public function 
populate()
    {
        
// Re-populating an existing dataset can be disabled (config demo.repopulate);
        // filling an empty database is always allowed.
        
if ($this->db_filled && ! config('demo.repopulate'true)) {
            
abort(403);
        }

        
Artisan::call('db:seed', ['--class' => DemoSeeder::class, '--no-interaction' => true]);

        
session()->flash('message''Demo data (re)populated.');

        return 
redirect()->to(route('demo'));
    }

    public function 
render()
    {
        return 
view('demo::home')->layout('layout::admin');
    }
}

view

Views/home.blade.php


<x-rpd::card title="Rapyd CRUD demo">
    @if(
session('message'))
        <
div class="alert alert-success">{{ session('message') }}</div>
    @endif

    <
p>
        
Three pagesthree files eacha Livewire componenta Blade view and a route.
        
Every page shows its own source code underneathso you can see exactly how little it takes.
    </
p>

    @if(
$db_filled)
        <
class="mb-3">
            <
x-rpd::button route="demo.articles" color="primary" label="Open the articles table" />
        </
p>
        @if(
config('demo.repopulate'true))
            <
class="small text-muted mb-0">
                
Want a clean slate? <a href="#" wire:click.prevent="populate">Re-populate the demo data</a>
                (
replaces all authors and articleson a shared demo disable it with <code>DEMO_REPOPULATE=false</code>).
            </
p>
        @endif
    @else
        <
class="mb-0">
            
No demo data yet.
            <
a href="#" wire:click.prevent="populate" class="btn btn-outline-primary btn-sm">Populate the database</a>
        </
p>
    @endif
</
x-rpd::card>

Support
How can I help you today?