lc-generate-crud
Generate complete CRUD scaffolding - migration, model, controller, routes, views (index + create/edit modal).
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Generate complete CRUD scaffolding - migration, model, controller, routes, views (index + create/edit modal).
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Create a Larascraper scraper (v2 or v3) for a target website, chaining browser actions (click, type, wait, scroll), conditional flow (when/repeatUntil), captcha solving, and file/PDF downloads. Detects the installed major and generates the matching style.
Add or edit a Laracrate file collection in config/laracrate.php with the correct anatomy (disk, access, types, variants, previews, extract/embed, flags, per-model scoping).
Runtime-verified Laravel inspection using the Laravel Boost MCP server (Tinker, Database Query/Schema, Last Error) instead of static grep. Falls back to Docker/Tinker if Boost is not installed.
Scaffold spatie/laravel-permission setup - add the HasRoles trait to a model and generate a roles & permissions seeder.
Audit spatie/laravel-permission usage - permissions used in code but undefined, defined but unused, unprotected routes, guard mismatches, and cache pitfalls.
Extract business logic from a controller or Livewire component method into a Laractions Action class.
| name | lc:generate-crud |
| description | Generate complete CRUD scaffolding - migration, model, controller, routes, views (index + create/edit modal). |
| argument-hint | [ModelName] |
| user-invocable | true |
| allowed-tools | Read Grep Bash Edit Write Glob Agent |
| Subcommand | Description |
|---|---|
<ModelName> | Generate full CRUD scaffolding for the given model (e.g., Invoice, Task, Document) |
This is a generator skill. It creates a complete CRUD setup following the project's conventions: migration, model, controller, routes, Volt table component (index), create/edit modal, and delete confirmation modal. Every generated file follows the project's established patterns.
Ask the user for the following (or infer from context):
organization_id and office_id? (default: yes for most models)If the user provides enough context, infer sensible defaults and proceed.
Before generating ANY files, read existing implementations to match conventions exactly:
Read an existing model for patterns:
app/Models/Property.php or app/Models/Client.php
Note: fillable, casts, relationships, traits, soft deletes, slug usage
Read an existing migration for conventions:
database/migrations/ (find a recent one)
Note: foreign key patterns, index names, column ordering
Read the base TableComponent:
Search for class TableComponent to understand the exact interface
Read an existing table Volt component:
resources/views/livewire/ (find one extending TableComponent)
Read an existing modal Volt component:
resources/views/livewire/modals/ (any existing modal)
Read routes/app.php for route registration patterns
Read an existing controller for the standard pattern
Create migration file using artisan via Docker:
docker exec abodara_app php artisan make:migration create_model_names_table
Then edit the generated file to add the schema.
Migration conventions:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('model_names', function (Blueprint $table) {
$table->id();
$table->string('slug')->unique();
$table->foreignId('organization_id')->constrained()->onDelete('cascade');
$table->foreignId('office_id')->nullable()->constrained()->onDelete('set null');
$table->foreignId('user_id')->nullable()->constrained()->onDelete('set null');
// ... model-specific fields
$table->string('name');
$table->text('description')->nullable();
$table->enum('status', ['draft', 'active', 'archived'])->default('draft');
$table->boolean('active')->default(true);
$table->timestamps();
$table->softDeletes();
});
}
public function down(): void
{
Schema::dropIfExists('model_names');
}
};
Key migration rules:
slug with unique index for URL-friendly identifiersforeignId()->constrained() for relationshipstimestamps() and softDeletes() lastenum for finite status setsdecimal(12, 2) for monetary valuestext for long content, string for short contentCreate file at app/Models/ModelName.php.
Model conventions:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class ModelName extends Model
{
use SoftDeletes;
protected $fillable = [
'slug',
'organization_id',
'office_id',
'user_id',
'name',
'description',
'status',
'active',
];
protected $casts = [
'active' => 'boolean',
];
public function organization(): BelongsTo
{
return $this->belongsTo(Organization::class);
}
public function office(): BelongsTo
{
return $this->belongsTo(Office::class);
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}
Key model rules:
use statements: BelongsTo, : HasMany)SoftDeletes trait when migration has softDeletes()id, created_at, updated_at, deleted_at in fillableCreate file at app/Http/Controllers/ModelNameController.php.
Controller conventions:
<?php
namespace App\Http\Controllers;
use App\Models\ModelName;
use Illuminate\Http\Request;
class ModelNameController extends Controller
{
public function index()
{
return view('model-names.index');
}
public function show(ModelName $modelName)
{
return view('model-names.show', compact('modelName'));
}
}
Key controller rules:
Create resources/views/model-names/index.blade.php:
<x-app-layout>
<livewire:model-names.index />
</x-app-layout>
Create resources/views/livewire/model-names/index.blade.php.
Follow the EXACT same pattern as the lc:generate-table skill. Key points:
TableComponentwire:key on every rowx-tables.dropdown for row actions (NOT in columns array)x-intersect@text() for all visible stringsInclude the modals at the bottom of the component:
<div>
{{-- Filters and table content --}}
{{-- Modals --}}
<livewire:modals.create-model-name />
<livewire:modals.edit-model-name />
<livewire:modals.confirm-delete-model-name />
</div>
Create resources/views/livewire/modals/create-model-name.blade.php and resources/views/livewire/modals/edit-model-name.blade.php.
Follow the EXACT same pattern as the lc:generate-modal skill. Key points:
<x-modal> with proper id and titlex-fields.* components for inputs (already include @error - NO duplicate error display)For the create modal:
Str::uuid() or Str::slug()organization_id and office_id from the authenticated user's contextmodel-name-created event after creationFor the edit modal:
#[On('open-edit-model-name')] eventmodel-name-updated event after updateCreate resources/views/livewire/modals/confirm-delete-model-name.blade.php.
Use the confirmation modal variant from lc:generate-modal. Dispatch model-name-deleted event.
Edit routes/app.php to add the new routes.
Read the file first to find the right location, then add:
Route::get('/model-names', [ModelNameController::class, 'index'])->name('model-names.index');
Route::get('/model-names/{modelName}', [ModelNameController::class, 'show'])->name('model-names.show');
Add the use import for the controller at the top of the routes file.
docker exec abodara_app php artisan migrate
After generating all files, display a complete summary:
## CRUD Generated: ModelName
### Files created:
1. database/migrations/YYYY_MM_DD_HHMMSS_create_model_names_table.php
2. app/Models/ModelName.php
3. app/Http/Controllers/ModelNameController.php
4. resources/views/model-names/index.blade.php
5. resources/views/livewire/model-names/index.blade.php
6. resources/views/livewire/modals/create-model-name.blade.php
7. resources/views/livewire/modals/edit-model-name.blade.php
8. resources/views/livewire/modals/confirm-delete-model-name.blade.php
### Routes added to routes/app.php:
- GET /model-names -> model-names.index
- GET /model-names/{modelName} -> model-names.show
### Migration status:
Migration executed successfully.
### Next steps:
- Add navigation link to sidebar/menu
- Add authorization policies if needed
- Customize table columns and filters
- Add any additional business logic to actions
@text() for all user-visible text - Defaults in English, no hardcoded stringsuse - Never inline \App\Models\bg-pink-600 hover:bg-pink-700)wire:navigate on internal linksorganization_id by default