Scaffolding Sections

May 30, 2026 · View on GitHub

The adminlte:scaffold command publishes complete, working sections into your Laravel app — migrations, Eloquent models, controllers, seeders, Blade views, and routes — driven by a declarative manifest baked into ScaffoldCommand.

Usage

adminlte:scaffold [section] [--all] [--force] [--seed]
Argument / OptionDescription
sectionOne of the 18 section names (see below). Omit it (without --all) for an interactive multi-select prompt.
--allScaffold all 18 sections.
--forceOverwrite existing files instead of skipping them.
--seedAfter publishing, run php artisan migrate --force then db:seed for each scaffolded section's seeder.

Behavior:

  • Passing an unknown section aborts with an error listing the valid names.
  • With no section and no --all, you get a multi-select picker.
  • Files that already exist are skipped (printed as exists) unless --force is used.
  • Route registration is idempotent — a section's routes are added once and skipped on re-runs.

Available sections

SectionDescription
dashboardData-driven dashboard with real stats — see dashboard.md
mailboxMessages mailbox with inbox/read/compose
chatConversations and chat messaging
kanbanKanban boards with drag-to-reorder cards
calendarEvent calendar with FullCalendar
projectsProject management CRUD
file-managerFile browser using Laravel Storage
profileUser profile page
settingsUser settings page
invoiceInvoice generator
pricingPricing page
faqFAQ accordion
notificationsDatabase notifications + navbar bell wiring + page — see notifications.md
apiSanctum personal access tokens + management UI — see api.md
realtimeBroadcast event + Echo listeners for live chat/notifications — see realtime.md
impersonation"Log in as" another user (RBAC-gated) — see activity-log.md
activity-logActivity/audit log + LogsActivity trait + auto auth-event logging — see activity-log.md
rbacRoles & permissions, management UI, HasRoles on User — see authorization.md

Where files are published

ArtifactDestination
Migrationsdatabase/migrations/{timestamp}_{name}.php (timestamps staggered for deterministic order)
Modelsapp/Models/{Model}.php
Controllersapp/Http/Controllers/AdminLte/{Controller}.php
Form Requestsapp/Http/Requests/AdminLte/{Request}.php
Policiesapp/Policies/{Model}Policy.php
Model factoriesdatabase/factories/{Model}Factory.php
Notificationsapp/Notifications/{Notification}.php
Broadcast eventsapp/Events/{Event}.php
Model concerns (traits)app/Models/Concerns/{Trait}.php
Feature teststests/Feature/AdminLte/{Section}Test.php
Seedersdatabase/seeders/{Seeder}.php
Viewsresources/views/adminlte/{section}/
Routesappended into a managed group in routes/web.php (see below)

Deep Laravel artifacts

The DB-backed sections don't just publish a controller and a view — they generate the full set of building blocks a Laravel developer expects, so the scaffolded code is production-shaped from day one rather than a throwaway demo.

ArtifactWhat it gives you
Model factoriesEvery scaffolded model uses the HasFactory trait and ships a matching factory in database/factories/, so you can Message::factory()->count(10)->create() in seeders and tests immediately.
Form RequestsWrite operations are validated through dedicated Store* / Update* Form Request classes ($request->validated()), keeping validation rules out of the controller.
PoliciesEach DB-backed model gets a Policy with viewAny / view / create / update / delete methods (ownership-aware where relevant). Controllers call $this->authorize(...) on every action.
Feature testsEach section ships a tests/Feature/AdminLte/ test that asserts guests are redirected, authenticated users can view, and CRUD + authorization behave — runnable with php artisan test right after scaffolding.

The Policies are registered automatically by the package (guarded by class_exists), and authorization keys resolve through the optional RBAC layer. See authorization.md for roles, permissions, and how the menu and Policies tie into Gate.


Section manifest

The following tables list exactly what each section publishes, per the manifest in ScaffoldCommand.

mailbox

TypeItems
Migrationscreate_adminlte_messages_table
ModelsMessage
ControllersMailboxController
SeedersAdminLteMailboxSeeder
Viewsmailbox/ (inbox, read, compose)
Routesmailbox
Seeder run on --seedAdminLteMailboxSeeder

Routes (adminlte. prefix):

VerbURIName
GET/admin/mailboxadminlte.mailbox.index
GET/admin/mailbox/composeadminlte.mailbox.create
POST/admin/mailboxadminlte.mailbox.store
GET/admin/mailbox/{message}adminlte.mailbox.show
DELETE/admin/mailbox/{message}adminlte.mailbox.destroy

chat

TypeItems
Migrationscreate_adminlte_conversations_table (creates 3 tables)
ModelsConversation, ChatMessage
ControllersChatController
SeedersAdminLteChatSeeder
Viewschat/
Routeschat
Seeder run on --seedAdminLteChatSeeder

Routes:

VerbURIName
GET/admin/chatadminlte.chat.index
GET/admin/chat/{conversation}adminlte.chat.show
POST/admin/chat/{conversation}adminlte.chat.store

kanban

TypeItems
Migrationscreate_adminlte_kanban_tables (creates 4 tables)
ModelsKanbanBoard, KanbanLane, KanbanCard
ControllersKanbanController
SeedersAdminLteKanbanSeeder
Viewskanban/
Routeskanban
Seeder run on --seedAdminLteKanbanSeeder

Routes:

VerbURIName
GET/admin/kanbanadminlte.kanban.index
POST/admin/kanban/cardsadminlte.kanban.cards.store
POST/admin/kanban/reorderadminlte.kanban.reorder

calendar

TypeItems
Migrationscreate_adminlte_events_table
ModelsEvent
ControllersCalendarController
SeedersAdminLteCalendarSeeder
Viewscalendar/ (FullCalendar)
Routescalendar
Seeder run on --seedAdminLteCalendarSeeder

Routes:

VerbURIName
GET/admin/calendaradminlte.calendar.index
GET/admin/calendar/feedadminlte.calendar.feed
POST/admin/calendaradminlte.calendar.store
PUT/admin/calendar/{event}adminlte.calendar.update
DELETE/admin/calendar/{event}adminlte.calendar.destroy

projects

TypeItems
Migrationscreate_adminlte_projects_table
ModelsProject
ControllersProjectsController
SeedersAdminLteProjectsSeeder
Viewsprojects/
Routesprojects
Seeder run on --seedAdminLteProjectsSeeder

Routes:

VerbURIName
GET/admin/projectsadminlte.projects.index
POST/admin/projectsadminlte.projects.store
PUT/admin/projects/{project}adminlte.projects.update
DELETE/admin/projects/{project}adminlte.projects.destroy

file-manager

No database. Browses files via Laravel's Storage.

TypeItems
ControllersFileManagerController
Viewsfile-manager/
Routesfile-manager

Routes:

VerbURIName
GET/admin/file-manageradminlte.file-manager.index
POST/admin/file-manager/uploadadminlte.file-manager.upload
DELETE/admin/file-manageradminlte.file-manager.destroy

profile

No database (operates on the authenticated user).

TypeItems
ControllersProfileController
Viewsprofile/
Routesprofile

Routes:

VerbURIName
GET/admin/profileadminlte.profile.show
PUT/admin/profileadminlte.profile.update

settings

No database.

TypeItems
ControllersSettingsController
Viewssettings/
Routessettings

Routes:

VerbURIName
GET/admin/settingsadminlte.settings.edit
PUT/admin/settingsadminlte.settings.update

invoice

No database.

TypeItems
ControllersInvoiceController
Viewsinvoice/
Routesinvoice

Routes:

VerbURIName
GET/admin/invoiceadminlte.invoice.show

pricing

View-only (no controller, no DB). Uses Route::view.

TypeItems
Viewspricing/
Routespricing

Routes:

VerbURIName
GET/admin/pricingadminlte.pricing.index

faq

View-only (no controller, no DB). Uses Route::view.

TypeItems
Viewsfaq/
Routesfaq

Routes:

VerbURIName
GET/admin/faqadminlte.faq.index

Database tables

The five DB-backed sections create the following tables.

Mailbox — adminlte_messages

ColumnTypeNotes
idbigint PK
from_user_idFK → users.idcascade on delete
to_user_idFK → users.idcascade on delete
subjectstring
bodytext
is_readbooleandefault false
is_starredbooleandefault false
created_at / updated_attimestamps

Chat — three tables

adminlte_conversations

ColumnTypeNotes
idbigint PK
namestringnullable
timestamps

adminlte_conversation_user (pivot)

ColumnTypeNotes
idbigint PK
conversation_idFK → adminlte_conversations.idcascade on delete
user_idFK → users.idcascade on delete
timestamps
unique(conversation_id, user_id)

adminlte_chat_messages

ColumnTypeNotes
idbigint PK
conversation_idFK → adminlte_conversations.idcascade on delete
user_idFK → users.idcascade on delete
bodytext
timestamps

Kanban — four tables

adminlte_kanban_boards

ColumnTypeNotes
idbigint PK
user_idFK → users.idcascade on delete
namestring
timestamps

adminlte_kanban_lanes

ColumnTypeNotes
idbigint PK
board_idFK → adminlte_kanban_boards.idcascade on delete
namestring
positionunsigned intdefault 0
timestamps

adminlte_kanban_cards

ColumnTypeNotes
idbigint PK
lane_idFK → adminlte_kanban_lanes.idcascade on delete
titlestring
descriptiontextnullable
colorstringdefault primary
positionunsigned intdefault 0
timestamps

adminlte_kanban_card_user (pivot)

ColumnTypeNotes
idbigint PK
card_idFK → adminlte_kanban_cards.idcascade on delete
user_idFK → users.idcascade on delete
unique(card_id, user_id)

Calendar — adminlte_events

ColumnTypeNotes
idbigint PK
user_idFK → users.idcascade on delete
titlestring
start_atdatetime
end_atdatetimenullable
all_daybooleandefault false
colorstringdefault #0d6efd
timestamps

Projects — adminlte_projects

ColumnTypeNotes
idbigint PK
namestring
descriptiontextnullable
statusenumplanning, active, on_hold, completed (default planning)
progressunsigned tiny intdefault 0
due_datedatenullable
timestamps

Route group injected into routes/web.php

The scaffolder appends section routes into a managed block in routes/web.php. The block is created once and reused for subsequent sections.

The generated group:

// AdminLTE scaffold routes
Route::middleware(['web', 'auth'])->prefix('admin')->name('adminlte.')->group(function () {
    // [adminlte:mailbox]
    // ... the section's route lines ...
});

Key points:

  • Middleware: web + authall scaffolded pages require authentication.
  • URI prefix: /admin.
  • Route-name prefix: adminlte. (so a section route mailbox.index becomes adminlte.mailbox.index).
  • Each section is wrapped behind a // [adminlte:{section}] marker. If that marker is already present, the section's routes are not added again (idempotent).
  • New sections are inserted right after the opening of the managed group; if the managed group doesn't exist yet, it's created at the end of the file.

If routes/web.php is missing, route registration is skipped with a warning.


Seeders and --seed

Each DB-backed section ships a demo-data seeder:

SectionSeeder classPublished to
mailboxAdminLteMailboxSeederdatabase/seeders/
chatAdminLteChatSeederdatabase/seeders/
kanbanAdminLteKanbanSeederdatabase/seeders/
calendarAdminLteCalendarSeederdatabase/seeders/
projectsAdminLteProjectsSeederdatabase/seeders/

When --seed is passed, for each scaffolded section that defines a seeder the command runs:

php artisan migrate --force
php artisan db:seed --class={Seeder} --force

(View-only sections — file-manager, profile, settings, invoice, pricing, faq — have no seeder and are skipped by --seed.)


Getting started example

Scaffold the mailbox, create its table, seed demo data, and view it:

# 1. Scaffold the mailbox section (publishes migration, model, controller,
#    seeder, views, and routes) and run migrate + seed in one shot.
php artisan adminlte:scaffold mailbox --seed

# If you prefer to do it in steps:
php artisan adminlte:scaffold mailbox
php artisan migrate
php artisan db:seed --class=AdminLteMailboxSeeder

Then:

  1. Add a sidebar menu item in config/adminlte.php pointing at the new route:

    ['text' => 'Mailbox', 'route' => 'adminlte.mailbox.index', 'icon' => 'bi bi-envelope'],
    
  2. Log in (the /admin group is auth-protected — scaffold auth first with php artisan adminlte:make-auth if needed; see authentication.md).

  3. Visit /admin/mailbox.