serverfireteam/rapyd-laravel
Rapyd Laravel is a CRUD and admin panel toolkit for Laravel that helps you rapidly build data grids, forms, filters, and back-office interfaces with reusable widgets, reducing boilerplate and speeding up internal tool development.
Rapyd is a server-side CRUD scaffolder: you describe a model's fields in PHP, and it renders the grid (list), form (create/edit), and validation for you using Blade templates it ships. The fastest path is controller → view, not route closures.
Install (works best on Laravel 5.x; on 5.5+ auto-discovery is not wired, so register manually):
composer require serverfireteam/rapyd-laravel
In config/app.php (if < 5.5):
'providers' => [
Serverfireteam\Rapyd\RapydServiceProvider::class,
],
'aliases' => [
'Rapyd' => Serverfireteam\Rapyd\Facades\Rapyd::class,
],
Publish the config and templates — this is the first place to look because almost every behavior (template paths, pagination, buttons, field presets) is driven by it:
php artisan vendor:publish --provider="Serverfireteam\Rapyd\RapydServiceProvider"
Review config/rapyd.php end-to-end before writing anything. The templates, pagination, and field blocks decide what you actually get out of the box.
Pick one resource and build both views against it. Start with users on a throwaway DB. Add a controller:
class UsersController extends Controller
{
public function index()
{
$grid = \Rapyd::grid('users')
->title('Users')
->fields([
'id' => 'ID',
'name' => 'Name',
'email' => 'Email',
'status' => 'Status',
])
->searchable(['name', 'email'])
->sortable(['name', 'email'])
->actions('edit,delete');
return view('rapyd::grid', compact('grid'));
}
public function edit($id)
{
$form = \Rapyd::form('users')
->title('Edit user')
->fields([
'name',
'email',
'password:password',
'status:select',
])
->load($id);
return view('rapyd::form', compact('form'));
}
}
Register resource routes. Rapyd does not generate controllers; it renders grids and forms, so you wire CRUD routes yourself (Route::resource('/admin/users', 'UsersController') minus store/update, or add handlers that call $form->save() / $grid->delete()).
Your first real use case is "list + edit screen for one table, in one afternoon." If that works, expand to a second resource before committing to a full admin panel — the API surface is small but under-documented, and you want to hit the edge cases with two resources, not ten.
Grid + form pairs per resource. Build them as private methods on the controller (protected function userGrid(), protected function userForm()) so index/create/edit reuse the same field definitions. Duplication between grid and form is the biggest source of drift in Rapyd projects.
Field definition syntax is string-based. Rapyd parses 'name' (inferred type) and 'password:password' (explicit type) in the same array. Keep the type suffix consistent and centralize it — define a const array of field specs per model and pass it around rather than scattering strings.
Validation lives on the form, not in a FormRequest. Each field accepts a validation key in the field spec or via a chained call. This is convenient but diverges from standard Laravel; reviewers looking for FormRequests won't find them. If you need complex conditional rules, either accept Rapyd's rules or override the save path.
$form = \Rapyd::form('users')->fields([
'name' => ['validation' => 'required|min:3'],
'email' => ['validation' => 'required|email|unique:users,email'],
]);
Relationship inputs. Select fields bound to another model use the field's options/relation config (check config/rapyd.php under field for what's supported). In practice you'll pass ->options(Model::pluck('name', 'id')->toArray()) for small tables and skip Rapyd's relation helpers for larger ones — they don't lazy-load well.
Grid actions are hooks, not routes. ->actions('edit,delete') renders buttons; the actual routing is your responsibility. Add ->url('edit', '/admin/users/{id}/edit') style mappings or wrap the grid actions to point at your routes. Delete goes through POST with a CSRF token by default — confirm the template you published includes @csrf or {{ csrf_field() }}.
Widgets for dashboards. \Rapyd::widget('users') is for single stat blocks (counts, latest rows). Use them on a dashboard page; do not try to fit an entire admin UI into widgets.
Custom templates are the real extension point. After publishing, the Blade views under resources/views/vendor/rapyd/ are yours. To change button markup, wrap it in a partial and point config/rapyd.php at it — do not patch the vendor copy. Anything beyond a field-level tweak should go here rather than in the controller.
Routing and middleware. Rapyd assumes it's mounted under a prefix with auth. Put the whole admin group behind auth + an admin middleware, and never expose the grid publicly — search/sort params go straight into orderBy/LIKE clauses.
Filters for scoped lists. Use ->filter([...]) (or the widget-based filter) rather than manual where in a closure — it keeps the query params Rapyd generates consistent with the pagination links.
rapyd::grid and rapyd::form view namespaces are fixed. If publishing templates fails silently, check that resources/views/vendor/rapyd/ actually exists — a missing template produces a blank page rather than an error, which is the #1 debugging trap.$fillable/$guarded still controls persistence. Rapyd reads from the form but writes via Eloquent. Missing fillables on a $guarded = ['*'] model silently drop fields, and you'll blame the form.password; if you include it in a create form, hash it before save or Rapyd will store plaintext. Never rely on Rapyd's save for sensitive fields.ORDER BY on the raw column name. For belongs-to names, join the related table or precompute a denormalized column.->searchable() is literal. It only LIKEs the columns you list. Date ranges and enums need a custom filter or a post-query filter closure; check config/rapyd.php under grid for the exact keys.delete() on the grid or a dedicated DELETE route — otherwise you'll reintroduce the CSRF hole you thought Laravel closed for you.dd($grid->getData()) on the grid works, but dumping the grid after a sort can re-run the query; dump the query builder instead if you need to inspect SQL.extra.laravel.providers in this package's composer.json; if you see Class 'Rapyd' not found, that is the cause, not a namespace typo.src/Field/ (you can subclass and register via config) and the template overrides. Everything else (Rapyd::grid, Rapyd::form, Rapyd::widget, config) is closed enough that forking is usually cleaner than monkey-patching.config/rapyd.php and views to your own repo (with a note on origin) so a future composer update can't silently change the UI.How can I help you explore Laravel packages today?