roland-solutions / vilt-cms
A page builder CMS for Laravel projects using Vue, Inertia, Laravel, and Tailwind (VILT stack) — with Filament admin, media library, and navigation management.
Requires
- php: ^8.3
- filament/filament: ^5.0
- filament/spatie-laravel-media-library-plugin: ^5.0
- inertiajs/inertia-laravel: ^3.0
- laravel/framework: ^13.0
- tightenco/ziggy: ^2.3
This package is auto-updated.
Last update: 2026-04-05 20:47:25 UTC
README
A CMS package for the VILT stack — Vue · Inertia · Laravel · Tailwind. It provides the CMS infrastructure while each project supplies its own design, blocks, and layouts.
What's included
- Page builder — pages with a layout slot + N content blocks, draft/published status, frontpage flag, and SEO meta
- Media library — uploads, folder organisation, grid/list browser, responsive WebP conversions, bulk operations
- Navigation — header and footer nav builder with links and dropdowns
- User management — admin user CRUD
- Filament 5 admin — all resources wired up and ready via
CmsPlugin - Inertia middleware base — shared props (title, ziggy, navigation) with overridable hooks
- Vue plugin + components —
createCms(),Wrapper,Head,Navigation,LinkItem,Blocks,Accordion - Block / layout generators —
cms:make-blockandcms:make-layout
Requirements
| Dependency | Version |
|---|---|
| PHP | ^8.3 |
| Laravel | ^13.0 |
| Filament | ^5.0 |
| Inertia Laravel | ^3.0 |
| Vue | 3 |
| Tailwind CSS | 4 |
| Ziggy | ^2.3 |
Installation
1. Require the package
composer require roland-solutions/vilt-cms
2. Run the installer
php artisan cms:install
On a fresh Laravel project, the installer handles everything automatically:
- Publishes and runs migrations
- Publishes
config/cms.phpandresources/views/app.blade.php - Creates
app/Http/Middleware/HandleInertiaRequests.phpand registers it - Creates a Filament panel and registers
CmsPlugin - Adds
FilamentUserto yourUsermodel - Publishes
resources/js/app.tsandresources/css/app.css - Replaces
vite.config.jswith a Vue + Tailwind +@cmsalias config - Publishes starter blocks, layouts, and Vue components to your app
- Installs npm packages and builds assets
- Seeds an example page and navigation via
CmsShowcaseSeeder - Prompts you to create a Filament admin user
On an existing project, it prints manual steps for anything it cannot safely automate.
Security note: The installer adds
canAccessPanel(): bool { return true; }to yourUsermodel so you can reach the admin panel immediately. Before deploying to production, replace this with a real check (e.g. anis_admincolumn or a role).
Adding blocks
Scaffold a new block:
php artisan cms:make-block Hero
This creates:
app/Cms/Blocks/HeroBlock.php— Filament form schemaresources/js/cms/blocks/HeroBlock.vue— Vue front-end component
Both files are discovered automatically — no registration needed. The PHP class is picked up by the CMS service provider at boot, and the Vue component is loaded via a glob import in app.ts.
Edit the generated files to define your block's fields and template.
Adding layouts
php artisan cms:make-layout TwoColumn
Creates:
app/Cms/Layouts/TwoColumnLayout.phpresources/js/cms/layouts/TwoColumnLayout.vue
Same as blocks — both are discovered automatically.
Updating frontend files after a package upgrade
Use cms:publish to selectively re-publish stub files:
# Publish everything php artisan cms:publish # Publish only specific groups php artisan cms:publish --only=vue --only=ts # Overwrite without confirmation php artisan cms:publish --force
Available groups:
| Group | What it publishes |
|---|---|
ts |
resources/js/app.ts |
vue |
Vue components and pages |
css |
resources/css/app.css |
config |
config/cms.php |
php |
Starter PHP block and layout classes |
Configuration
Publish the config file:
php artisan vendor:publish --tag=cms-config
config/cms.php
return [ // Eloquent model used for authentication and the admin user resource. // Must implement \Filament\Models\Contracts\FilamentUser. 'user_model' => env('CMS_USER_MODEL', \App\Models\User::class), // Filesystem disk for uploaded media. Defaults to "public". 'media_disk' => env('CMS_MEDIA_DISK', 'public'), // Options shown in the Button block's style selector. // [ value => label ] 'buttons' => [ 'primary' => 'Primary', 'secondary' => 'Secondary', ], // Vertical padding options shown in the Video block's spacing selector. // [ value => label ] 'padding' => [ 'sm' => 'Small', 'md' => 'Medium', 'lg' => 'Large', ], ];
buttons and padding default to empty arrays — the corresponding selectors are hidden if the array is empty.
Translations
The package ships English labels by default. To use Danish or override any string:
php artisan vendor:publish --tag=cms-lang
Published to lang/vendor/cms/. Activate Danish with APP_LOCALE=da in your .env.
Customising shared Inertia props
Override extraProps() in your HandleInertiaRequests middleware to add or override shared props:
protected function extraProps(Request $request): array { return [ 'user' => $request->user()?->only('id', 'name'), ]; }
Customising navigation loading
Override loadNavigation() to change how (or whether) header/footer nav is loaded:
protected function loadNavigation(string $type): array { if ($type === 'footer') { return []; // disable footer nav } return parent::loadNavigation($type); }
Block resource resolution
If a block field stores a PHP class name in a _resource key, the package will instantiate it on every page render and inject the result back into the block data. This is useful for blocks that need to load dynamic data (e.g. a list of products).
Any class used as a block resource must implement RolandSolutions\ViltCms\Contracts\BlockResource:
use RolandSolutions\ViltCms\Contracts\BlockResource; class LatestPosts implements BlockResource { public function __construct(array $data) { $this->posts = Post::latest()->take($data['count'] ?? 3)->get(); } }
License
MIT — see LICENSE.
© 2025–2026 Roland Solutions