PHPackages                             jasminecms/jasmine - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. jasminecms/jasmine

ActiveLibrary[Framework](/categories/framework)

jasminecms/jasmine
==================

A Laravel based CMS.

3.1.3(2w ago)615.4k—8.3%2[5 issues](https://github.com/JasmineCMS/jasmine/issues)4MITJavaScriptPHP ^8.4

Since May 17Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/JasmineCMS/jasmine)[ Packagist](https://packagist.org/packages/jasminecms/jasmine)[ RSS](/packages/jasminecms-jasmine/feed)WikiDiscussions master Synced 2w ago

READMEChangelogDependencies (45)Versions (220)Used By (4)

Jasmine CMS
===========

[](#jasmine-cms)

A Laravel based CMS inspired by [Voyager](https://voyager.devdojo.com/).

Screenshots
-----------

[](#screenshots)

Login [![Login](https://github.com/JasmineCMS/jasmine/raw/master/screenshots/login.png?raw=true)](https://github.com/JasmineCMS/jasmine/blob/master/screenshots/login.png?raw=true)

Bread index [![Bread index](https://github.com/JasmineCMS/jasmine/raw/master/screenshots/bread-index.png?raw=true)](https://github.com/JasmineCMS/jasmine/blob/master/screenshots/bread-index.png?raw=true)

Bread Edit [![Bread edit](https://github.com/JasmineCMS/jasmine/raw/master/screenshots/bread-edit.png?raw=true)](https://github.com/JasmineCMS/jasmine/blob/master/screenshots/bread-edit.png?raw=true)

Requirements
------------

[](#requirements)

- PHP &gt;= 8.4
- Laravel &gt;= 13

#### Note

[](#note)

Jasmine uses [alexusmai/laravel-file-manager](https://github.com/alexusmai/laravel-file-manager)
If you are using it already or planning to,
you might need to tweak some configurations to prevent conflicts.

Installation
------------

[](#installation)

Require JasmineCMS in your new or existing laravel app
`composer require jasminecms/jasmine`

Publish the config file (optional, to customize routes and other options)
`php artisan vendor:publish --tag=jasmine-config`

Link jasmine public assets to your public folder
`php artisan jasmine:link-public-assets`

Migrate the database (be sure to make any changes to the default laravel migration prior)
`php artisan migrate`

Create a user (1st user is super admin)
`php artisan jasmine:create-user`

You can now log in to Jasmine,
Navigate to `/jasmine`
And login

### Routes

[](#routes)

Unlike previous versions, Jasmine now registers its web and api routes automatically.
No need to add anything to your route files.

You can control registration, prefixes and middleware via the config file:

```
'routes' => [
    'web' => [
        'register'   => true,
        'prefix'     => 'jasmine',
        'middleware' => ['web'],
    ],
    'api' => [
        'register'   => true,
        'prefix'     => 'jasmine/api',
        'middleware' => ['api'],
    ],
],
```

Set `register` to `false` if you prefer to register the routes yourself using `Jasmine::routes()` and `Jasmine::apiRoutes()`.

### API documentation

[](#api-documentation)

When api routes are registered, Jasmine generates an OpenAPI specification for all `jasmine.api.*` routes using [Scramble](https://scramble.dedoc.co/):

- Interactive docs UI: `/{api-prefix}/docs`
- OpenAPI JSON spec: `/{api-prefix}/api.json`

The docs are only visible to authenticated Jasmine users.

Registering assets
------------------

[](#registering-assets)

You can register Jasmine assets in your `AppServiceProvider`.

### Locales (content)

[](#locales-content)

Jasmine supports multilingual content, define your content languages like so

```
Jasmine::registerLocales(['en', 'he']);
```

### Interface locale

[](#interface-locale)

Jasmine's interface language files are simple JSON files.
To add or override an interface locale, place a `{locale}.json` file in:

```
lang/vendor/jasmine/ui/he.json

```

Jasmine will automatically pick up any locale files in that directory, alongside its built-in locales. To get started quickly, publish the built-in locale files and edit or copy them:

```
php artisan vendor:publish --tag=jasmine-locales-ui

```

### Breadables

[](#breadables)

Breadables can be any model

In your model implement
`Jasmine\Jasmine\Bread\BreadableInterface`
use trait `Jasmine\Jasmine\Bread\Breadable`
if the model has multilingual columns, also use trait
`Jasmine\Jasmine\Bread\Translatable;`
implement missing methods

then register your model in `AppServiceProvider`

```
Jasmine::registerBreadable(\App\Models\MyModel::class);

// optionally control the sidebar menu item
Jasmine::registerBreadable(\App\Models\MyModel::class, addMenuItem: false);
Jasmine::registerBreadable(\App\Models\MyModel::class, menuPriority: 10);
```

Registering a breadable automatically registers its permissions (`browse`, `read`, `edit`, `add`, `delete`) and, unless disabled, a sidebar menu item that is hidden from users lacking the `browse` permission.

### Pages

[](#pages)

Pages are very similar to models, but function as a single entity instead of a table

Register your pages in `AppServiceProvider`

```
Jasmine::registerPage(\App\Pages\Home::class);

// optionally control the sidebar menu item
Jasmine::registerPage(\App\Pages\Home::class, addMenuItem: false);
Jasmine::registerPage(\App\Pages\Home::class, menuPriority: 10);
```

Registering a page automatically registers its permissions (`read`, `edit`, `add`) and, unless disabled, a submenu item under the "pages" sidebar menu that is hidden from users lacking the `read` permission.

### Custom assets

[](#custom-assets)

If for some reason you wish to load custom javascript or css you can do it like so

```
Jasmine::registerCustomStyle('https://example.com/path/to/style.css');
Jasmine::registerCustomScript('https://example.com/path/to/app.js');
```

Paths should be absolute URLs (prefer https).

### Permissions

[](#permissions)

Permissions are simple dot-notated string keys:

```
Jasmine::registerPermission('reports.sales.view');
Jasmine::registerPermission('reports.sales.export');
```

Registered permissions are automatically rendered in the role edit screen as grouped switches — each dot segment becomes a group.

Breadables and pages register their own permissions automatically (`models.{key}.{browse|read|edit|add|delete}` and `pages.{slug}.{read|edit|add}`).

You can check permissions on a user with `$user->jCan('models.post.edit')`.

### SideBarMenuItems

[](#sidebarmenuitems)

You can add items to the sidebar menu like so

```
// internal
\Jasmine::registerSideBarMenuItem('settings', fn() => [
    'title'    => __('Settings'),
    'icon'     => 'bi-gear',
    'href'     => route('jasmine.my.route', 'my-param-value'),
    'is-route' => ['r' => 'jasmine.my.route', 'p' => ['my-param' => 'my-param-value']],
], 70);

// external
\Jasmine::registerSideBarMenuItem('site-triple', fn() => [
    'href'   => 'https://triple.co.il',
    'title'  => 'Triple',
    'icon'   => 'bi-link-45deg text-danger',
    'target' => '_blank',
], 100);
```

Items accept: `title`, `href`, `target`, `icon`, `class`, `hidden`, `is-route`.
The third argument is the item's priority (lower = higher in the menu, default `50`).
Items with `hidden => true` (or no `href`) are not rendered — handy for permission checks:

```
\Jasmine::registerSideBarMenuItem('settings', fn() => [
    'title'  => __('Settings'),
    'href'   => route('jasmine.my.route'),
    'hidden' => !auth()->user()->jCan('settings.edit'),
]);
```

#### Submenu items

[](#submenu-items)

You can nest items under a parent menu item:

```
// the parent — only needs a title and icon
\Jasmine::registerSideBarMenuItem('reports', fn() => [
    'title'  => __('Reports'),
    'icon'   => 'bi-graph-up',
    'opened' => false, // whether the group starts expanded
], 60);

// children
\Jasmine::registerSideBarSubMenuItem('reports', 'sales', fn() => [
    'title'    => __('Sales'),
    'href'     => route('jasmine.my.reports', 'sales'),
    'is-route' => ['r' => 'jasmine.my.reports', 'p' => ['report' => 'sales']],
], 10);

\Jasmine::registerSideBarSubMenuItem('reports', 'traffic', fn() => [
    'title' => __('Traffic'),
    'href'  => route('jasmine.my.reports', 'traffic'),
], 20);
```

Registration order doesn't matter — submenu items are merged into their parent lazily, so you can register children before the parent (or from different service providers).
A parent with no visible children is not rendered.

Jasmine ships with a few built-in parent items you can attach submenu items to: `pages` (priority 30), `jasmine` (55) and `tools` (60).

### Dashboard cards

[](#dashboard-cards)

Dashboard cards let you add widgets to the Jasmine dashboard.
A card is either a **blade** card (server rendered HTML) or a **vue** card (a Vue SFC rendered client side).

```
use Jasmine\Jasmine\Dashboard\DashboardCard;

// blade card
Jasmine::registerDashboardCard('welcome', DashboardCard::blade(
    fn($request) => view('dashboard.welcome', ['user' => $request->user()])
)->width(6)->priority(10));

// vue card, SFC as a string
Jasmine::registerDashboardCard('stats', DashboardCard::vue(
     \App\Models\Post::count()],
)->width(4));

// vue card from a file
Jasmine::registerDashboardCard('orders', DashboardCard::vueFile(
    resource_path('js/jasmine-cards/Orders.vue'),
    props: fn($request) => ['recent' => \App\Models\Order::latest()->limit(5)->get()],
));
```

#### Card options

[](#card-options)

- `->width(int)` — grid width in columns, 1–12 (cards are always full width on mobile). Default `4`.
- `->priority(int)` — display order, lower comes first. Default `50`.

#### Card actions

[](#card-actions)

Cards can expose server side actions, callable from the card's frontend:

```
Jasmine::registerDashboardCard('cache', DashboardCard::blade(fn() => view('dashboard.cache'))
    ->get('status', fn($request) => ['size' => Cache::size()])
    ->post('clear', fn($request) => Cache::flush())
);
```

- `->get($name, $handler)` — read-only action (cacheable, no CSRF token)
- `->post($name, $handler)` — mutating action
- `->action($name, $handler, $method)` — any of `GET`, `POST`, `PUT`, `DELETE`

### Route groups

[](#route-groups)

You can register your own route groups inside Jasmine's route scope — useful both for packages extending Jasmine and for app specific admin routes.
Groups are registered in one of three scopes:

```
// routes behind Jasmine authentication (admin panel routes)
Jasmine::registerAuthenticatedRouteGroup(function () {
    Route::get('my-reports/{report}', MyReportController::class)->name('jasmine.my.reports');
});

// stateless api routes
Jasmine::registerApiRouteGroup(function () {
    Route::get('my-endpoint', MyApiController::class)->name('jasmine.api.my-endpoint');
});

// guest routes (no authentication)
Jasmine::registerGuestRouteGroup(function () {
    Route::get('public-status', PublicStatusController::class);
});
```

Groups can optionally be named, which allows replacing or removing them (registering the same id twice throws a `LogicException`):

```
Jasmine::registerAuthenticatedRouteGroup($closure, 'my-plugin');

// later, e.g. in an app overriding a plugin's routes
Jasmine::unregisterAuthenticatedRouteGroup('my-plugin');
Jasmine::registerAuthenticatedRouteGroup($otherClosure, 'my-plugin');
```

`unregisterApiRouteGroup()`, `unregisterGuestRouteGroup()` and `resetRouteGroups()`are also available.

### Oauth2 SSO

[](#oauth2-sso)

You can register oauth2 providers to enable sso login to jasmine

Facebook example

```
Jasmine::registerOauth2Sso(
    'Facebook', //name
    'https://www.facebook.com/images/fb_icon_325x325.png', //icon
    '{client_id}',
    '{client_secret}',
    'https://www.facebook.com/v3.3/dialog/oauth',
    'https://graph.facebook.com/v3.3/oauth/access_token',
    ['email'],
    false, // accepts boolean or callback
    function ($token) {
        $token = json_decode($token, true);

        $res = Http::asJson()->get('https://graph.facebook.com/v3.3/me', [
            'access_token' => $token['access_token'],
            'fields'       => 'name,email',
        ]);

        return [
            'name'  => $res->json('name'),
            'email' => $res->json('email'),
        ];
    },
);
```

###  Health Score

59

—

FairBetter than 98% of packages

Maintenance76

Regular maintenance activity

Popularity32

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity93

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~10 days

Recently: every ~0 days

Total

218

Last Release

19d ago

Major Versions

0.12.1 → 1.0.02021-10-03

1.4.0 → 2.0.02022-11-21

v2.x-dev → 3.x-dev2026-07-01

PHP version history (4 changes)1.0.0PHP ^8.0

2.4.0PHP ^8.1

2.12.0PHP ^8.2

3.x-devPHP ^8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/f843e1ac6ca3aabf914bae50226984d02b8def3482c8e826a7fcdc023c363fcd?d=identicon)[MordiSacks](/maintainers/MordiSacks)

---

Top Contributors

[![MordiSacks](https://avatars.githubusercontent.com/u/13218192?v=4)](https://github.com/MordiSacks "MordiSacks (127 commits)")

---

Tags

cmsjasminecmslaravelphp

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/jasminecms-jasmine/health.svg)

```
[![Health](https://phpackages.com/badges/jasminecms-jasmine/health.svg)](https://phpackages.com/packages/jasminecms-jasmine)
```

###  Alternatives

[craftcms/cms

Craft CMS

3.6k3.7M3.4k](/packages/craftcms-cms)[statamic/cms

The Statamic CMS Core Package

4.9k3.8M1.2k](/packages/statamic-cms)[code16/sharp

Laravel Content Management Framework

79466.1k10](/packages/code16-sharp)[symfony/framework-bundle

Provides a tight integration between Symfony components and the Symfony full-stack framework

3.6k257.3M12.4k](/packages/symfony-framework-bundle)[bagisto/bagisto

Bagisto Laravel E-Commerce

28.0k175.2k9](/packages/bagisto-bagisto)[unopim/unopim

UnoPim Laravel PIM

10.8k2.5k](/packages/unopim-unopim)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
