posio / cabinet-kit
Base admin panel scaffolding extracted from posio.cabinet: multi-tenant accounts, per-account roles/permissions, bundled auth, settings shell, Inertia+Vue layout and UI kit.
Package info
github.com/AndreiDishlenko/posio-cabinet-kit
Language:Vue
pkg:composer/posio/cabinet-kit
Requires
- php: ^8.2
- illuminate/support: ^11.0|^12.0
- inertiajs/inertia-laravel: ^1.0|^2.0|^3.0
- opcodesio/log-viewer: ^3.22
- spatie/laravel-permission: ^6.0
- spatie/laravel-sitemap: ^7.3|^8.0
Requires (Dev)
None
Suggests
- laravel/socialite: Required for the bundled Google/Apple sign-in routes (config cabinet-kit.social_auth).
- socialiteproviders/apple: Required for Apple sign-in on top of laravel/socialite.
- tightenco/ziggy: Required in practice: CabinetKit Vue pages resolve every URL through route(), and the bundled root view prints @routes.
Provides
None
Conflicts
None
Replaces
None
- dev-main
- 2.3.30
- 0.4.27
- 0.4.26
- 0.4.25
- 0.4.24
- 0.4.23
- 0.4.22
- 0.4.21
- 0.4.20
- 0.4.19
- 0.4.18
- 0.4.17
- 0.4.16
- 0.4.15
- 0.4.14
- 0.4.13
- 0.4.12
- 0.4.11
- 0.4.10
- 0.4.9
- 0.4.8
- 0.4.7
- 0.4.6
- 0.4.5
- 0.4.4
- 0.4.3
- 0.4.2
- 0.4.1
- 0.4.0
- 0.3.58
- 0.3.57
- 0.3.56
- 0.3.55
- 0.3.54
- 0.3.53
- 0.3.52
- 0.3.51
- 0.3.50
- 0.3.49
- 0.3.48
- 0.3.47
- 0.3.46
- 0.3.45
- 0.3.44
- 0.3.43
- 0.3.42
- 0.3.41
- 0.3.40
- 0.3.39
- 0.3.38
- 0.3.37
- 0.3.36
- 0.3.35
- 0.3.34
- 0.3.33
- 0.3.32
- 0.3.31
- 0.3.30
- 0.3.29
- 0.3.28
- 0.3.27
- 0.3.26
- 0.3.25
- 0.3.24
- 0.3.23
- 0.3.22
- 0.3.21
- 0.3.20
- 0.3.19
- 0.3.18
- 0.3.17
- 0.3.16
- 0.3.15
- 0.3.14
- 0.3.13
- 0.3.12
- 0.3.11
- 0.3.9
- 0.3.8
- 0.3.7
- 0.3.6
- 0.3.5
- 0.3.4
- v0.3.3
- v0.3.1
- v0.3.0
- v0.1.3
- v0.1.2
- v0.1.1
- v0.1.0
This package is auto-updated.
Last update: 2026-09-30 00:17:41 UTC
README
Quick install
The package is not on Packagist — it is installed straight from its git repository, so any machine with network access to GitHub can install it; no local checkout of the package is needed.
Run inside an existing Laravel 11/12 + Inertia + Vue 3 project:
# 1. register the package repository composer config repositories.cabinet-kit vcs https://github.com/AndreiDishlenko/posio-cabinet-kit.git # 2. pull the package in composer require posio/cabinet-kit:^0.3 # 3. wire it into the host project (configs, migrations, seeds, vite/tailwind patches) php artisan cabinet-kit:install # 4. install the npm deps the command added to package.json, then build npm install npm run dev
Then open /cabinet/register to create a user. Registration creates the user
only — no company (account) and no follow-up onboarding steps; a registered
user joins an account when its owner invites them.
Signing in as one of the seeded accounts (sa / admin, see system_users
in config/cabinet-kit.php) instead opens the password screen and stops
there: their installed password is written in that config and is the same in
every project using this package, so the cabinet opens only after it has been
replaced. Set 'force_system_password_change' => false if those passwords are
managed outside the application.
Notes on the git source
- Composer needs
giton PATH; if it is missing, Composer falls back to downloading zip archives from GitHub, which also works. - To follow the unreleased tip instead of a tagged release, require
dev-mainand set"minimum-stability": "dev"+"prefer-stable": truein the hostcomposer.json. - Private-repo / rate-limit case: authenticate Composer once with a GitHub
token —
composer config --global github-oauth.github.com <token>. - Write the constraint as
^0.3, not0.3: a two-segment version is an exact version to composer (it normalizes to0.3.0), so0.3installs the very first release of the line and hides every later tag —composer updatethen reports the project as current forever.cabinet-kit:installandcabinet-kit:sync-configrewrite such a constraint to its range form, andcabinet-kit:doctorfails on it. - To pin an exact release, use a full tag instead of a range, e.g.
composer require posio/cabinet-kit:0.3.31(left alone by the commands above — a three-segment pin is read as deliberate). - Offline machines: clone or copy the repo to that machine and point the
repository at the local path —
composer config repositories.cabinet-kit vcs /path/to/posio-cabinet-kit(a plain filesystem path works as avcssource because the copy is a git repo).
Updating
composer update "posio/*" # the kit and every installed module php artisan migrate # new versions may ship migrations php artisan cabinet-kit:doctor # verifies frontend/backend wiring npm install && npm run build
The install command drops two launchers in the project root — updcab.bat for
Windows and updcab for a Linux/macOS host over ssh. Either one performs the
whole Update procedure except the build, in order, and stops at the
first failing step; the assets are built afterwards the project's own way:
cd /var/www/example.com && ./updcab && npm run build
Requirements and what those commands actually do — below; the full step-by-step is in Update.
Base admin-panel scaffolding extracted from posio.cabinet: multi-tenant
accounts, per-account roles/permissions (Spatie Permission teams), bundled
auth (login, register, logout, password reset, email verification), a
Settings shell, a log viewer, a collapsible side-menu layout, and a small
Vue 3 UI kit — for bootstrapping a new Laravel + Inertia + Vue 3 project's
admin part.
Not a finished product — a shell you extend per project. See
docs/ARCHITECTURE.md and docs/EXTENDING.md.
Requirements
- Laravel 11/12, PHP 8.2+
- Inertia.js (Laravel adapter) + Vue 3, Options API
spatie/laravel-permission,opcodesio/log-viewer(pulled in automatically)tightenco/ziggy(composer) + npm:vue,@inertiajs/vue3,ziggy-js,@iconify/vue,@headlessui/vue,@vuepic/vue-datepicker,vue-final-modal,vee-validate,vue-i18n,dayjs,axios,sweetalert2,vue3-toastify,date-fns,@fontsource/inter,@fontsource/roboto,@fontsource/open-sans,@fontsource/inter-tight,@fontsource/pt-sans— package pages resolve URLs throughroute()and use Iconify icons/date inputs with bundled fonts, confirmation dialogs and toasts.php artisan cabinet-kit:installadds them topackage.jsonfor you;cabinet-kit:doctorre-checks the list.- A
Usermodel withpassword/email_verified_atcolumns (Laravel's defaultusersmigration already has both) php artisan storage:link— the brand images an operator uploads in the site/cabinet settings sections are served fromstorage/app/public/site/
Install (in a consumer project)
Commands — see Quick install above.
The install command publishes config/cabinet-kit.php and
config/cabinet-kit-redirects.php, enables Spatie
Permission teams before migrations, resolves auth-route conflicts, scaffolds
the cabinet Vite entry (resources/_admin/js/cabinet.ts by default),
patches vite.config, tailwind.config and app/Models/User.php with
.bak backups, drops updcab.bat and updcab (the one-step update
launchers) in the project root, runs migrations, seeds base roles, and
finishes with cabinet-kit:doctor.
It also drops the project scripts. They are the package's own: the same in
every project, marked managed-by: posio/cabinet-kit, and overwritten from
stubs/ by cabinet-kit:sync-config on every update (./updcab). Never edit
them in a project — the change is lost on the next update. Change the stub in
this package instead; it then reaches every project at once.
| file | what it does |
|---|---|
deploy |
production deploy over ssh: git pull --ff-only, migrate, re-cache, queue:restart, sitemap:generate (when the host has it), ./build, site check; ./deploy --rollback returns the previous code; ./deploy --preprod updates a preprod that shares the production database |
build, build.bat, scripts/kit-build.mjs |
front-end build for the current environment (local / preprod / production from .env): npm dependencies, SSR process stop/start through pm2, vite build (+ --ssr) or the project's own command, the project's checks |
cc, cc.bat |
reset the Laravel caches |
release.bat |
one-step patch release (./release): runs scripts/pre-push-checks.sh, commits, tags, pushes |
All of them print the same way: a stage line ■ <script> · <stage> in the
script's own colour (deploy magenta, build cyan, cc blue, release orange),
OK / WARN / FAIL result lines and a closing ✓ / ✗. NO_COLOR=1
turns colour off.
What sets one project apart lives in two files the package creates once and never touches again:
| file | what it holds |
|---|---|
scripts/host-scripts.conf |
the project's settings for the scripts: its own build command, build checks, node heap, SSR process names, a step after the code update, cache mode, preprod build outputs |
scripts/pre-push-checks.sh |
the checks before a release: php artisan cabinet-kit:test, php artisan test, the build |
Copies of these scripts made before they were managed carry no marker. The
first update recognises them, replaces them with the managed version and keeps
the old file next to it as <name>.bak: move whatever it adapted into
scripts/host-scripts.conf, then delete the copy.
Tests in the host project
php artisan cabinet-kit:test runs the package's sign-in and registration
tests against this project — its migrations, user model and config — on an
in-memory SQLite database, so the working database is never touched. Every
./release runs them before committing; cabinet-kit:sync-config adds the
step to an existing scripts/pre-push-checks.sh and keeps it there.
php artisan cabinet-kit:test # all tests php artisan cabinet-kit:test --filter=Registration # a subset php artisan cabinet-kit:test --full # complete PHPUnit output with traces php artisan cabinet-kit:test --db-connection=mysql --db-database=myapp_test
A database other than in-memory SQLite must have test in its name — it is
wiped and migrated from scratch. The command refuses to run with cached config
(php artisan config:clear), and needs PHPUnit from the dev dependencies.
cabinet-kit:sync-config also adds a CabinetKit suite
(vendor/posio/cabinet-kit/tests/Host) to the project's phpunit.xml, so the
same tests show up in the editor's test explorer and run with
php artisan test, under that file's test environment.
If the database already contains users, the command asks whether to delete
them (with their accounts, memberships and role assignments) before seeding.
The default answer is no — say yes only on a database you are willing to
reset. --purge-users answers that prompt up front; with --no-interaction
and no flag nothing is deleted.
Every CabinetKit page renders into the package's own Blade root view
(cabinet-kit::app) with its own Vite entry — the host's main app view and
entry are untouched.
Visit /cabinet/register afterwards to create users. Registration creates the
user only; accounts come from the seeded system users and from invitations.
Update
Run the launcher from the project root — updcab.bat on Windows, ./updcab
on a Linux/macOS host (that one is the whole update on a production server
over ssh). Both are scaffolded by the install command, run the steps below
except step 5 and stop at the first one that fails. Step 5 — the build — is
left to the project: it knows its own bundles, SSR process and environments
(build.bat / ./build when the project has one, otherwise npm run build).
Everything after this paragraph describes what they do (and what to run by
hand elsewhere).
Both launchers carry a managed-by: posio/cabinet-kit line. While it is there,
cabinet-kit:sync-config — run by every composer update and by the launcher
itself — replaces the file with the one from the installed package version, so
a change to the launcher reaches every project with its next update. A project
linked to the package's working copy gets the change on its next run. To keep
an adapted launcher, delete that line: the file is then never rewritten.
updcab.bat cannot be rewritten while it runs — the new version waits next to
it as updcab.bat.new and takes its place on the launcher's last line.
./updcab differs from the batch file only where a server differs from a
workstation:
migrate --force— a production run has no tty to answer the confirmation prompt with;- when
APP_ENV=production,php artisan optimizeruns after the caches are cleared, so the site does not stay uncached (see the note after step 6); - the PHP is checked before anything runs. Shared hosting serves the site on the
version its panel selected while the shell of the same account still starts an
old default, and on that one step 1 fails with a wall of
your php version (7.4.33) does not satisfy that requirement. Whenphpis older than 8.2, the launcher picks another binary — from the usual names and per-version paths (php8.3,/opt/php83/bin/php,/opt/alt/php83/usr/bin/php,/opt/cpanel/ea-php83/root/usr/bin/php) — and says which one it took. Preference goes to the version the site is actually served with, read from the handler line of.htaccess; without one it takes the oldest supported, since what Composer resolves for 8.2 also runs on a newer binary while the reverse installs code the site cannot execute. Composer runs under the same interpreter — a phar and a shebang script both otherwise fall back to the defaultphp.PHP_BIN=/usr/bin/php8.3 ./updcaboverrides the choice.
When composer is not in PATH — the usual case on shared hosting — the
launcher looks for composer2, then for a phar or binary in the project root,
in ~, in ~/bin and in the common system locations, and finally asks the
login shell to resolve it (a host that adds Composer to PATH in ~/.bashrc,
or declares it there as an alias over a phar, gives it to an interactive
session only — which is why it runs by hand while the update does not find it).
If the host keeps it somewhere else, name it:
COMPOSER_BIN=/opt/php83/bin/composer ./updcab. If the host has no Composer at
all, install it once into the project root and the launcher picks it up from
there:
curl -sS https://getcomposer.org/installer | php
If the server answers Permission denied, the executable bit did not survive
the trip (a file committed from Windows carries none): chmod +x updcab there,
or git update-index --chmod=+x updcab in the repository so it arrives set on
the next deploy. sh updcab works regardless.
A posio/* package whose folder in vendor/ is a junction or symlink — a
developer's working copy of the package repository linked in for live editing —
is updated like any other, so composer.lock records the new release that the
servers then install. Its link is lifted for step 1, Composer installs the
release in its place, and the link is put back right after it, even when
Composer fails: the site keeps running on the working copy, and Composer never
writes into it. Updating the lock alone (--no-install) would not do: the list
of installed packages would keep the old version, and the next composer install or update would replace the link with a download to "repair" it.
Step 2 then re-applies the wiring from the working copy — the Composer hook ran
it on the downloaded release.
A module listed in require of composer.json but not yet in vendor/posio/
(just added with composer require … --no-update, or pulled in by another
developer's commit) is installed by the same composer update "posio/*". The
module's version constraint on posio/cabinet-kit must fit the one in the
project's composer.json; raise it there first if it does not.
--full also updates the packages' own Composer dependencies
(--with-all-dependencies); without it they are kept.
Full procedure, in order:
# 1. pull the new package version, together with the installed modules # (catalog-kit and the like) — they are released against the kit composer update "posio/*" # 2. only if the post-update hook is missing (see below) — re-apply host wiring php artisan cabinet-kit:sync-config # 3. apply migrations a new version may have added php artisan migrate # 4. drop caches built from package routes/config/views php artisan optimize:clear # 5. rebuild the frontend (sync-config may have added npm packages) npm install npm run build # 6. verify the result php artisan cabinet-kit:doctor
On production, re-cache after step 4 as usual (php artisan config:cache route:cache view:cache) — the caches must be rebuilt because package routes
and views changed, not because the update needs anything special.
Launchers scaffolded before 0.4 update the kit alone; sync-config switches
their step 1 to posio/* in place and leaves the rest of the file as you
had it.
cabinet-kit:install registers sync-config in your composer.json
post-update-cmd, so from then on composer update runs it for you (step 2
is then redundant): it keeps the npm dependency list and the Tailwind
content glob for the package templates current, creates config files a new
package version introduced, and only reports new config/cabinet-kit.php
keys (that file is never rewritten). Rebuild assets afterwards if it patched
anything.
Read its output: keys it lists are new settings your config/cabinet-kit.php
does not have yet — copy them in by hand, otherwise the package falls back to
its own defaults for them. cabinet-kit:doctor at the end reports anything
still unwired.
Vue/SCSS/routes/migrations are read straight from vendor/posio/cabinet-kit/
— nothing was copied into your project, so there's nothing to merge.
Anything you deliberately overrode in resources/_admin/overrides/ keeps
working untouched.
Which version you get
composer update posio/cabinet-kit only moves inside the range in your
composer.json (^0.3 stays on 0.3.*). A bare 0.3 there is not that
range — composer reads it as the single release 0.3.0 and silently stops
offering updates; cabinet-kit:doctor reports it, and cabinet-kit:sync-config
rewrites it to ^0.3 (run composer update posio/cabinet-kit once more
afterwards). Breaking changes — renamed config
keys, removed props on released Vue components, changed route names — arrive
as a major bump, so crossing one is a deliberate edit of the constraint
followed by composer update, plus a read of docs/CHANGELOG.md.
Before 1.0 a minor release is such a line too: ^0.3 never reaches 0.4.*.
Moving to 0.4 (the release that can host modules) is a one-time edit of the
constraint to ^0.4 — or the installer of the first module does it for you.
To see what is available before updating:
composer show posio/cabinet-kit --all | head -20 # versions offered by the repo composer outdated posio/cabinet-kit # installed vs latest in range
If a dev-main install stops picking up new commits, Composer is serving a
cached clone — composer clearcache, then update again.
Customizing
- Menu items, assignable roles, log-viewer path →
config/cabinet-kit.php(survives updates for free). - Where sign-in, registration, email confirmation and sign-out land →
config/cabinet-kit-redirects.php. Pointhome/after_loginat your own route to open the cabinet on your own page. - Styles →
resources/_admin/scss/cabinet-kit-overrides.scss(scaffolded by install, loaded after the kit so your rules win; redefine--ck-*tokens or re-declare element classes — never edit the package's own scss). - Deeper changes →
resources/_admin/overrides/pages/...(checked before the package's own version — seedocs/EXTENDING.md). - Brand (site name, favicon, logos, default theme) → the Site settings and
Cabinet settings sections of the cabinet itself. To make the host's own
public pages follow them, and to drive their meta from the SEO section,
follow
docs/cabinet-kit/— installed into the project and refreshed on every update (source:docs/host/here).
Uninstall (remove from a project)
There is no uninstall command — cabinet-kit:install patches the host's own
files, and undoing that automatically would mean rewriting files you have
edited since. The steps below are the exact reverse of what install did.
Back up the database first: step 1 drops tables and columns.
1. Roll back the package migrations (while the package is still installed — its migration files must be readable):
php artisan migrate:rollback --path=vendor/posio/cabinet-kit/database/migrations --step=20
That removes the accounts, user_has_accounts and admin_links tables,
the settings/social-id columns added to users, and the is_system columns
on roles/permissions. Migrations recorded from other paths are skipped
with a "migration not found" note — that is expected, not an error.
Spatie's own permission tables were published into
database/migrations/, so they are the host's files now: keep them if the
project still uses roles, otherwise roll them back and delete them too.
Seeded rows (roles, admin links, system users) disappear with their tables.
2. Remove the composer package:
composer remove posio/cabinet-kit
spatie/laravel-permission, opcodesio/log-viewer and inertiajs/inertia-laravel
came in as its dependencies and go with it. If the project keeps using any of
them, composer require it explicitly first.
3. Undo the host-file patches. Each patched file has a .bak copy from
install time — useful as a reference, but do not blindly restore it: it
predates every change you made since. Edit by hand:
| File | What to remove |
|---|---|
composer.json |
the @php artisan cabinet-kit:sync-config --ansi entry in scripts.post-update-cmd |
vite.config.js/.ts |
the cabinet-kit.js plugin import, the cabinetKit({ https: true }) call, and the cabinet entry in the vite-plugin input |
tailwind.config.js/.ts |
the tailwind-preset.cjs import, cabinetKitPreset in presets, and the vendor/posio/cabinet-kit/** glob in content |
app/Models/User.php |
use IsCabinetKitUser; and its use Posio\CabinetKit\Traits\IsCabinetKitUser; import |
package.json |
the npm packages install added (see Requirements) — only the ones nothing else in the project uses |
config/permission.php |
the CabinetKit shape (teams, user_has_roles, user_has_permissions, model_morph_key) — only if the project drops Spatie roles entirely; reverting those names while permission tables still hold data breaks them |
4. Delete the files install created:
config/cabinet-kit.php
config/cabinet-kit-redirects.php
public/cabinet-assets/
resources/_admin/overrides/
resources/_admin/scss/cabinet-kit-overrides.scss
resources/_admin/js/cabinet.ts # the Vite entry, if it serves nothing else
updcab.bat
updcab
*.bak # the install-time backups, once you are done with them
5. Rebuild and clear:
composer dump-autoload php artisan optimize:clear npm install npm run build
Nothing else of the package remains in the project: Vue/SCSS/routes/views
were always read from vendor/, which step 2 deleted. If the host relied on
the bundled auth routes (login, register, password.*,
verification.*), those names are now gone — restore the project's own auth
routes before deploying.
Developing this package itself
Open this repo directly (F:\Packages\posio-cabinet-kit) and follow its own
CLAUDE.md. Tag a new semver version after merging a change; consumer
projects pick it up with composer update posio/cabinet-kit.