Recipe — CRUD Module
Goal: Ship a working admin CRUD (list, create, edit, delete) for a new entity, wired up to permissions and the module sidebar.
Time: ~10 minutes.
Prerequisites
- You have Modularous installed and can run
php artisan modularous:list. - You have a module in mind — we'll use
Billingand an entity calledInvoicefor this recipe.
1. Scaffold the module
php artisan modularous:make:module Billing invoices \
--fields="number:string,total:decimal,issued_at:datetime" \
--traits="HasSlug" \
--testThis creates:
modules/Billing/Entities/Invoice.php— model with the listed fields +HasSlugtraitmodules/Billing/Repositories/InvoiceRepository.php— repositorymodules/Billing/Http/Controllers/InvoiceController.php— CRUD controllermodules/Billing/Http/Requests/*— store / update form requestsmodules/Billing/Database/Migrations/*_create_invoices_table.php— migrationmodules/Billing/Hydrates/Inputs/InvoiceHydrate.php— form schema hydrate- Route entries in
routes/admin.php(or the module's route file)
See make:module for every flag.
2. Run the migration
php artisan modularous:migrate3. Register the sidebar entry
In the module's config (typically modules/Billing/Config/billing.php):
'sidebar' => [
'invoices' => [
'title' => 'Invoices',
'icon' => 'receipt_long',
'route' => 'admin.billing.invoices.index',
'allowedRoles' => ['admin', 'accounting'],
],
],Role filtering uses the Allowable generic.
4. Create permissions
php artisan modularous:create:route:permissions Billing invoicesThis generates Spatie permission records for index / create / update / destroy and attaches them to the default admin role.
5. Add custom fields to the form
Open modules/Billing/Hydrates/Inputs/InvoiceHydrate.php and adjust the schema returned by getInputs(). Typical additions:
public function getInputs(): array
{
return [
['type' => 'text', 'name' => 'number', 'label' => 'Invoice #'],
['type' => 'price', 'name' => 'total', 'label' => 'Total'],
['type' => 'date', 'name' => 'issued_at', 'label' => 'Issued'],
['type' => 'textarea', 'name' => 'notes'],
];
}See Hydrates for the schema contract and Form Inputs for every input type.
6. Warm caches
php artisan modularous:cache:warm Billing7. Verify
- Log in to the admin panel as an admin user.
- Click Invoices in the sidebar — you should see an empty data table.
- Click Create — the form should render the fields from step 5.
- Save — the record appears in the table; edit/delete actions work.
Common Variations
Add a relationship
php artisan modularous:make:route Billing invoices \
--relationships="Customer:belongsTo"See Relationships for belongsToMany pivots.
Add file attachments
Add HasFileponds to the model and an input:
// Invoice.php
use HasFileponds;
// InvoiceHydrate.php
['type' => 'filepond', 'name' => 'attachments', 'max' => 5]See File Uploads recipe for full walkthrough.
Add a state workflow
See State Machine recipe.
Next Steps
- Module Features — stack traits for richer behaviour
- Data Tables — customise the list view
- Repositories — lifecycle hooks (
hydrate,afterSave)