Download the PHP package tbtop/admin without Composer
On this page you can find all versions of the php package tbtop/admin. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Package admin
Short Description Inertia admin builder - PHP DSL pages rendered by the @tbtop React client
License MIT
Homepage https://github.com/tbtop/admin
Informations about the package admin
Tabletop — Laravel + Inertia admin builder
An admin builder: pages are authored in a PHP DSL, serialized to a JSON structure in Inertia props, and rendered by a React interpreter. Filament's authoring model, without Livewire.
Layout
| Package | What it is |
|---|---|
packages/php |
composer tbtop/admin — DSL, controllers, Effects, nav, uploads |
packages/client |
npm @tbtop/inertia-admin — render layer + Inertia integration |
packages/contracts |
JSON Schema grammar + kitchen-sink fixture (the contract shared by both sides) |
apps/demo |
Laravel 12 + Inertia v3 reference app (acceptance) |
Run the demo
A page in 30 seconds
Registration: add the class to config/tbtop-admin.php → 'pages'. Routes and
the table/data/form/action endpoints are wired automatically under the
configured prefix + middleware.
Forms
- Laravel owns validation: rules are collected from the fields (repeater →
parent.*.child),validate()→ 422 → errors land on the fields. Regex rules must use the array form. - The declarative subset of rules ships to the client as
constraintsfor on-blur validation. - Submit goes through Inertia
router.post(errors bag, history); success effects arrive via flash. - A field with no rules gets a baseline
nullable(otherwise Laravel drops it from the validated payload).
Actions — five kinds
| Spec | What it does |
|---|---|
->visit(url) |
Inertia visit; supports {row.id} templates |
->submit() |
submit the nearest (or a named) form |
->handle(fn, needs: [...]) |
POST to a server closure; payload by needs: form/row/selection |
->modal(title, $node) |
client modal with a StructureNode body |
->custom('name', params) |
client registry via defineCustomAction() |
->confirm(title) wraps a server action in a confirm modal. Server closures
resolve by name per-request — they never travel over the wire.
Effects (a closed set): notify | redirect | refreshTable | resetForm | closeModal.
Extending the set is a minor contract bump; anything non-standard goes through
custom.
Uploads
Profiles live in config ('uploads' => ['media' => [disk, dir, accept, maxSize, sizes]]),
the endpoint is POST {prefix}/uploads/{profile}, with GD fit-inside variants.
The field $s->upload('file')->set('entity', 'media') delivers a full UploadRow
to $ctx->form['file'] (url, mimeType, filesize, width/height, sizes).
The contract
contracts/structure.schema.json is the wire grammar. Gates:
- PHP: the kitchen-sink page validates against the schema + a snapshot
(
UPDATE_FIXTURES=1 vendor/bin/pestto regenerate); - client: the same fixture passes the zod mirror and a render smoke test.
A new block = update the schema + the zod mirror + the fixture in one PR.
Quality gates
phpstan runs at level 5 (the skeleton default; raise it in phpstan.neon.dist).
Status
See docs/roadmap.md for the release plan and the current gap list (auth-page
layout and the relation field are the known blockers). Per-package contributor
notes live in the root CLAUDE.md.
All versions of admin with dependencies
illuminate/contracts Version ^11.0||^12.0||^13.0
inertiajs/inertia-laravel Version ^3.1
spatie/laravel-package-tools Version ^1.16