Search by

j87nl / laravel-vue-cms

J87.nl

Vue and Inertia admin for j87nl/laravel-cms.

Package info

github.com/J87NL/laravel-vue-cms

pkg:composer/j87nl/laravel-vue-cms

Statistics

Installs: 53

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.2.0 2026-10-19 18:55 UTC

This package is auto-updated.

Last update: 2026-10-20 20:23:16 UTC


README

Inertia and Vue admin for j87nl/laravel-cms: pages, blocks, media, menus, redirects and site settings, built on TranquilTools CrudBuilder, FormBuilder and TableBuilder.

The Vue pages stay inside the package. The app's Inertia resolver loads them from the package, and an app overrides a single page through the configurable page names in config/vue-cms.php.

Requirements

  • PHP 8.5, Laravel 13 and Inertia 3 with Vue 3
  • j87nl/laravel-cms
  • tranquil-tools/laravel-vue-form-builder and tranquil-tools/laravel-vue-table-builder (installed as dependencies)
  • laravel-vue-i18n and a $can(permission) helper on the Vue app

Installation

composer require j87nl/laravel-vue-cms
php artisan vendor:publish --tag=vue-cms-config

The admin routes live under vue-cms.admin.prefix (default admin/cms) behind vue-cms.admin.middleware (default web and auth), and every screen checks one of the CMS permissions.

Vite and the page resolver

Add the aliases and load the package pages next to your own:

// vite.config.ts
resolve: {
    alias: {
        '@cms': fileURLToPath(new URL('./vendor/j87nl/laravel-vue-cms/resources/js', import.meta.url)),
        '@form-builder': fileURLToPath(new URL('./vendor/tranquil-tools/laravel-vue-form-builder/resources/js', import.meta.url)),
        '@table-builder': fileURLToPath(new URL('./vendor/tranquil-tools/laravel-vue-table-builder/resources/js', import.meta.url)),
    },
},
// resources/js/app.ts
const appPages = import.meta.glob<DefineComponent>('./pages/**/*.vue');
const cmsPages = import.meta.glob<DefineComponent>('@cms/pages/**/*.vue');

resolve: async (name) => {
    const page = name.startsWith('cms/')
        ? Object.entries(cmsPages).find(([path]) => path.endsWith(`/pages/${name.slice(4)}.vue`))?.[1]
        : appPages[`./pages/${name}.vue`];

    return (await page!()).default;
},

Add "@cms/*": ["./vendor/j87nl/laravel-vue-cms/resources/js/*"] to the paths in tsconfig.json, and add the package's .vue files to Tailwind's sources so their classes are generated:

@source '../../vendor/j87nl/laravel-vue-cms/resources/js/**/*.vue';

Host app contract

  • Confirm dialog: the package never uses window.confirm. Provide a promise-based confirm function from your layout: provide('confirm', (message: string) => Promise<boolean>). Without it every confirmation resolves to false, so destructive actions do nothing.
  • Breadcrumbs: pages set a breadcrumbs layout prop through setLayoutProps. Your admin layout reads it and renders the trail.
  • Translations: strings use vue-cms:: keys through laravel-vue-i18n. Make the package's lang directory available to the i18n Vite plugin, for example with a lang/vendor/vue-cms symlink to vendor/j87nl/laravel-vue-cms/lang.

Navigation and permissions

The package pushes its menu items into the config key named by vue-cms.navigation_config_key (default j87nl.navigation). Each item has a key, a translation label, a route, a Lucide icon name (FileText, Image, Menu, Signpost, Settings2), a permission and an order. The app builds its sidebar from that key.

Map the CMS permissions to your roles: cms.pages.edit, cms.pages.publish, cms.menus, cms.media, cms.redirects and cms.settings. Publishing, taking offline, planning and changing a published page all need cms.pages.publish.

Toasts

Success messages are flashed with Inertia::flash() under vue-cms.toast_flash_key (default toast) as { type, message }.

Testing

composer update
vendor/bin/pest

License

MIT