littleboy130491/cms
| Install | |
|---|---|
composer require littleboy130491/cms |
|
| PHP: | ^8.2 |
| License: | MIT |
| Last Updated: | Mar 16, 2026 |
| Links: | GitHub · Packagist |
Sumimasen CMS
A powerful, multilingual Laravel CMS package built with Filament v3. Features hierarchical content management, role-based permissions, dynamic components, and extensive customization options.
Features
- Multilingual content with smart fallback, localized slugs, and automatic redirection
- Rich content management for pages, posts, categories, tags, menus, and comments
- Role-based access control powered by Filament Shield
- Dynamic components and flexible content blocks for reusable layouts
- Built-in SEO suite integration with sitemap generation and Open Graph tags
- Responsive, Filament-powered admin interface
- WordPress-like template hierarchy with custom slug overrides
- Form system with email notifications, throttling, and optional bot protection
- Page view and like tracking with Livewire-powered widgets
- Scheduled publishing and queue-friendly operations
- Media management through Curator and optimized image handling
- Advanced caching layers for routes, configuration, and templates
Requirements
- PHP 8.2+
- Laravel 12.0+
- MySQL 8.0+ / PostgreSQL 13+
- Node.js 18+ (for asset compilation)
Installation
Step 1: Install Package
composer require littleboy130491/cms
Step 2: Run Installation Command
php artisan cms:install
This command will:
- Publish configuration files
- Publish and run migrations
- Publish views and assets
- Generate default permission roles
- Guide you through the setup process
Step 3: Configure Environment
Add required environment variables to your .env file:
# reCAPTCHA (optional but recommended)
NOCAPTCHA_SITEKEY=your_recaptcha_site_key
NOCAPTCHA_SECRET=your_recaptcha_secret_key
# Instagram Integration (optional)
INSTAGRAM_ACCESS_TOKEN=your_instagram_access_token
# Admin Email for Notifications
MAIL_ADMIN_EMAIL=admin@yoursite.com
# Debug Mode (development only)
CMS_DEBUG_MODE_ENABLED=false
Note: The CMS plugin is automatically registered with all Filament panels. No manual plugin registration is required!
Quick Start
1. Create Your First Admin User
php artisan make:filament-user
2. Access Admin Panel
Visit /admin and log in with your newly created admin account.
3. Configure General Settings
Navigate to Settings > General in the admin panel to configure:
- Site name and description
- Contact information
- Social media links
- Logo and favicon
4. Create Your First Content
- Pages: Create static pages like "About", "Contact", etc.
- Posts: Create blog posts or news articles
- Categories & Tags: Organize your content
- Menus: Build navigation menus
- Comments: Manage user comments and feedback
Configuration
Content Models Configuration
The CMS supports multiple content types with custom slug support defined in config/cms.php:
'content_models' => [
'pages' => [
'model' => \Littleboy130491\Sumimasen\Models\Page::class,
'name' => 'Pages',
'type' => 'content',
'has_archive' => false,
'has_single' => true,
],
'posts' => [
'model' => \Littleboy130491\Sumimasen\Models\Post::class,
'name' => 'Posts',
'type' => 'content',
'has_archive' => true,
'has_single' => true,
'archive_SEO_title' => 'Blog Posts',
'archive_SEO_description' => 'Latest news and articles',
'eager_load' => ['categories', 'tags'],
],
'categories' => [
'model' => \Littleboy130491\Sumimasen\Models\Category::class,
'name' => 'Categories',
'type' => 'taxonomy',
'has_archive' => true,
'has_single' => false,
'display_content_from' => 'posts',
],
// Add your custom content types here
],
Adding Custom Content Types
Extend this array in your application to register additional models or override the defaults. For example, to expose a Facility model with a localized slug:
'facilities' => [
'model' => \App\Models\Facility::class,
'name' => 'Facilities',
'type' => 'content',
'slug' => 'fasilitas', // Localized slug shown in URLs
'has_archive' => true,
'has_single' => true,
],
Key defaults to note:
fallback_content_typedefaults toposts, so unresolved static slugs fall back to the posts model.static_page_modeldefaults toLittleboy130491\Sumimasen\Models\Page.static_page_slug(pages) andfront_page_slug(beranda) control static page lookups and the home page redirect.template_base(templates) andpackage_namespace(sumimasen-cms) define where templates are resolved.
Custom Slug Support
The CMS supports custom URL slugs different from the configuration key:
- Without custom slug:
/{lang}/facilities(uses the config key) - With custom slug:
/{lang}/fasilitas(uses the custom slug value)
This allows you to have:
- Clean, localized URLs
- SEO-friendly paths
- Maintain internal code organization
Multilingual Setup
Configure supported languages:
'multilanguage_enabled' => true,
'default_language' => 'en',
'language_available' => [
'id' => 'Indonesian',
'en' => 'English',
'zh-cn' => 'Chinese',
'ko' => 'Korean',
],
The first segment of every public URL must match one of these keys. The package falls back to cms.default_language (default: en) and ships with a front page slug of beranda, both of which can be overridden in your configuration.
Comments System Configuration
Enable comments on your content models by adding the HasComments trait:
use Littleboy130491\Sumimasen\Traits\HasComments;
class Post extends Model
{
use HasComments;
// Your model code...
}
Comments support:
- Hierarchical Structure: Nested replies with unlimited depth
- Moderation Workflow: Pending, approved, and rejected status
- Admin Management: Full CRUD operations in Filament admin
- Frontend Integration: Ready-to-use comment components
Frontend Routing
All public-facing routes include the language segment defined in cms.language_available:
/-> redirects to/{default_language}based oncms.default_language/{lang}-> home page handled byHomeController/{lang}/{slug}-> static pages resolved byStaticPageController, with archive fallback when a matching content type hashas_archive = true/{lang}/{content_type_key}/{content_slug}-> single content handled bySingleContentController/{lang}/{taxonomy_key}/{taxonomy_slug}-> taxonomy archives handled byTaxonomyController/{lang}/preview/...-> authenticated preview routes for emails, components, and submission forms
The fallback route automatically prepends the default language when a request omits it (unless the URI targets reserved prefixes like admin, filament, or an existing language). This keeps links consistent even when users share language-less URLs.
Template System
The CMS uses a sophisticated template hierarchy system with WordPress-like template resolution and custom slug support.
Template Hierarchy
Templates are resolved in order of specificity, checking both your application views and the package's fallback views:
1. Home Page Templates
For the home page (/{lang} after the root redirect):
1. user defined template from CMS
2. templates/home.blade.php (content slug in default language)
3. templates/singles/home.blade.php (specific home template)
4. templates/singles/front-page.blade.php (front page template)
5. templates/front-page.blade.php (front page template)
6. templates/singles/default.blade.php (default single)
7. templates/default.blade.php (global default)
2. Static Page Templates
For static pages (e.g., /en/about):
1. user defined template from CMS
2. templates/about.blade.php (content slug in default language)
3. templates/singles/about.blade.php (specific page by slug)
4. templates/singles/page.blade.php (all pages)
5. templates/page.blade.php (all pages)
6. templates/singles/default.blade.php (default single)
7. templates/default.blade.php (global default)
3. Single Content Templates
For single content items with custom slug support (e.g., /en/fasilitas/pool-area when registering the facilities example above):
1. user defined template from CMS
2. templates/pool-area.blade.php (content slug in default language)
3. templates/singles/fasilitas-pool-area.blade.php (specific content by slug)
4. templates/singles/fasilitas.blade.php (all content of this type by slug)
5. templates/fasilitas.blade.php (all content of this type)
6. templates/singles/facility-pool-area.blade.php (fallback by config key)
7. templates/singles/facility.blade.php (fallback by config key)
8. templates/facility.blade.php (fallback by config key)
9. templates/singles/default.blade.php (default single)
10. templates/default.blade.php (global default)
4. Archive Templates
For content archives (e.g., /en/posts or /en/fasilitas for the custom example):
1. templates/archives/archive-fasilitas.blade.php (specific archive by slug)
2. templates/archive-fasilitas.blade.php (specific archive by slug)
3. templates/archives/archive.blade.php (default archive)
4. templates/archive.blade.php (default archive)
5. Taxonomy Templates
For taxonomy archives (e.g., /en/categories/technology):
1. user defined template from CMS
2. templates/archives/categories-technology.blade.php (specific taxonomy-term)
3. templates/archives/categories.blade.php (all terms in taxonomy)
4. templates/categories-technology.blade.php (specific taxonomy-term)
5. templates/categories.blade.php (all terms in taxonomy)
6. templates/archives/archive.blade.php (default archive)
7. templates/archive.blade.php (default archive)
Template Structure
Create your templates in resources/views/templates/:
templates/
|- default.blade.php # Global fallback
|- home.blade.php # Home page
|- page.blade.php # All static pages
|- custom-hero-layout.blade.php # User-defined template
|- custom-about-layout.blade.php # User-defined template
|- about.blade.php # Content slug template
|- contact.blade.php # Content slug template
|- singles/
| |- default.blade.php # Default single template
| |- page.blade.php # All static pages
| |- page-about.blade.php # Specific page
| |- post.blade.php # All posts
| |- post-featured.blade.php # Specific post
| |- fasilitas.blade.php # Custom slug content type
| |- facility.blade.php # Fallback for original key
|- archives/
|- archive.blade.php # Default archive
|- archive-posts.blade.php # Posts archive
|- archive-fasilitas.blade.php # Custom slug archive
|- categories.blade.php # Category taxonomy
|- categories-technology.blade.php # Specific category
Template Context
Each template receives specific variables:
All Templates
$lang // Current language
$bodyClasses // Generated CSS classes
Single Content Templates
$item // The record from CMS
$content_type // Content type slug
$content_slug // Content slug
$title // Content title
Archive Templates
$items // Paginated collection
$record // Record from static page CMS assigned as archive
$archive // Archive object with metadata
$post_type // Content type slug
$title // Archive title
Taxonomy Templates
$items // Related content (paginated)
$taxonomy // Taxonomy key
$taxonomy_slug // Taxonomy slug
$record // Taxonomy record from CMS
$title // Taxonomy title
Template Body Classes
The system automatically generates CSS classes for styling:
// Example body classes
"lang-en type-post slug-my-post-title"
"lang-id type-fasilitas slug-pool-area"
"lang-en archive-posts archive-page"
"lang-id taxonomy-categories term-technology"
Use these in your CSS:
.lang-en .post { /* English posts */ }
.lang-id .fasilitas { /* Indonesian facilities */ }
.archive-posts { /* Posts archive styling */ }
.taxonomy-categories { /* Category taxonomy styling */ }
Performance Optimization
The template system includes several performance optimizations:
- Cached Route Resolution: Routes are cached for 24 hours
- Cached Config Lookups: Content model configs are cached
- Eager Loading: Automatically loads configured relationships
- Template Caching: Laravel's view caching applies to all templates
To clear caches:
# Clear all CMS caches
php artisan cms:routes-clear
# Clear view cache
php artisan view:clear
Advanced Features
Comments System
The CMS includes a powerful hierarchical comments system with the following features:
Admin Management
Comments Resource: Manage all comments from a centralized location with:
- Bulk status updates (approve, reject, pending)
- Content moderation tools
- User information tracking
- Hierarchical relationship viewing
Relation Managers: Each commentable model automatically gets a comments relation manager for inline comment management:
// Automatically available in your Filament resources
public static function getRelations(): array
{
return [
RelationManagers\CommentsRelationManager::class,
];
}
Model Integration
Add comments to any model:
use Littleboy130491\Sumimasen\Traits\HasComments;
class Article extends Model
{
use HasComments;
// Now your model has comments relationship
}
Access comments in your code:
// Get all comments
$article->comments
// Get only approved comments
$article->approvedComments
// Get Filament edit URL (if resource exists)
$article->getFilamentEditUrl()
Frontend Integration
Display comments in your templates:
{{-- Show approved comments --}}
@foreach($post->approvedComments as $comment)
<div class="comment">
<h5>{{ $comment->name }}</h5>
<p>{{ $comment->content }}</p>
<small>{{ $comment->created_at->diffForHumans() }}</small>
{{-- Show replies --}}
@if($comment->replies->count())
<div class="replies ml-4">
@foreach($comment->replies as $reply)
<div class="reply">
<h6>{{ $reply->name }}</h6>
<p>{{ $reply->content }}</p>
</div>
@endforeach
</div>
@endif
</div>
@endforeach
Dynamic Components
Create reusable content blocks:
- Create Component in Admin: Add a new component with a unique name
- Create Blade Template:
resources/views/components/dynamic/{name}.blade.php - Use in Templates:
<x-component-loader name="your-component" />
Example component template:
{{-- resources/views/components/dynamic/hero-slider.blade.php --}}
@foreach ($componentData->blocks as $block)
@if ($block['type'] === 'slide')
<div class="slide">
<h2>{{ $block['data']['heading'] }}</h2>
<p>{{ $block['data']['description'] }}</p>
@if(isset($block['data']['image_url']))
<img src="https://raw.githubusercontent.com/littleboy130491/sumimasen/HEAD/{{ $block['data']['image_url'] }}" alt="{{ $block['data']['heading'] }}">
@endif
</div>
@endif
@endforeach
Livewire Components
Built-in interactive components:
{{-- Like button with real-time updates --}}
<livewire:sumimasen-cms.like-button :content="$post" />
{{-- Contact form with reCAPTCHA --}}
<livewire:sumimasen-cms.submission-form />
{{-- Comment form (if implementing frontend comments) --}}
<livewire:sumimasen-cms.comment-form :commentable="$post" />
Settings Management
Access site settings in templates:
@php
$settings = app(\App\Settings\GeneralSettings::class);
@endphp
<footer>
<p>{{ $settings->site_name }}</p>
<p>Email: {{ $settings->email }}</p>
<p>Phone: {{ $settings->phone_1 }}</p>
</footer>
SEO Features
Automatic SEO optimization:
- Meta titles and descriptions
- Open Graph tags
- Structured data
- XML sitemap generation
- Multilingual hreflang tags
Debug Mode
Enable comprehensive debugging in development:
CMS_DEBUG_MODE_ENABLED=true
APP_ENV=local
Provides detailed HTML comments with:
- Request information
- Database queries
- View data
- Performance metrics
Scheduled Tasks
Set up cron job for automated features:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
Automated tasks include:
- Publishing scheduled content (every 30 minutes)
- Refreshing Instagram tokens (monthly)
- Other maintenance tasks
Security Features
- CSRF protection on all forms
- XSS prevention with input sanitization
- Role-based access control
- reCAPTCHA integration
- Secure file uploads
- Input validation and filtering
- Comment moderation system
Performance Optimization
- Query optimization with eager loading
- Response caching support
- Image optimization with Curator
- Queue support for heavy operations
- Database indexing
- Asset minification
- Optimized comment queries with relationship loading
- Cached route resolution for custom slugs
Customization
Extending Models
Add traits to your models:
use Littleboy130491\Sumimasen\Traits\HasPageViews;
use Littleboy130491\Sumimasen\Traits\HasPageLikes;
use Littleboy130491\Sumimasen\Traits\HasComments;
class CustomModel extends Model
{
use HasPageViews, HasPageLikes, HasComments;
}
Custom Resources
Override default resources:
SumimasenPlugin::make()
->resources([
CustomPostResource::class,
CustomCommentResource::class,
// ... other resources
])
Debug Mode
Enable debug mode for detailed error information:
CMS_DEBUG_MODE_ENABLED=true
APP_DEBUG=true
Extending Content Blocks in Your Main App
Step 1: Create a Content Blocks Class
Create a CustomContentBlocks class in your main app at app/Support/CustomContentBlocks.php.
Then edit the file to add your custom content blocks:
<?php
namespace App\Support;
use Filament\Forms\Components\Builder as FormsBuilder;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Textarea;
use Awcodes\Curator\Components\Forms\CuratorPicker;
class CustomContentBlocks
{
/**
* Get all custom blocks to be added to resources using HasContentBlocks trait
*/
public static function getCustomBlocks(): array
{
return [
static::getCustomBlock(),
static::getAnotherCustomBlock(),
static::getTestimonialBlock(),
// Add more custom blocks here
];
}
private static function getCustomBlock(): FormsBuilder\Block
{
return FormsBuilder\Block::make('custom')
->label('Custom Block')
->schema([
TextInput::make('block_id')
->label('Block ID')
->helperText('Identifier for the block')
->columnSpanFull(),
TextInput::make('custom_field')
->label('Custom Field'),
Textarea::make('custom_description')
->label('Custom Description')
->columnSpanFull(),
])
->columns(2);
}
private static function getAnotherCustomBlock(): FormsBuilder\Block
{
return FormsBuilder\Block::make('another_custom')
->label('Another Custom Block')
->schema([
TextInput::make('block_id')
->label('Block ID')
->columnSpanFull(),
TextInput::make('another_field')
->label('Another Field'),
TextInput::make('extra_field')
->label('Extra Field'),
])
->columns(2);
}
private static function getTestimonialBlock(): FormsBuilder\Block
{
return FormsBuilder\Block::make('testimonial')
->label('Testimonial')
->schema([
TextInput::make('block_id')
->label('Block ID')
->columnSpanFull(),
TextInput::make('author_name')
->label('Author Name'),
TextInput::make('author_title')
->label('Author Title'),
Textarea::make('quote')
->label('Testimonial Quote')
->columnSpanFull(),
CuratorPicker::make('author_image')
->label('Author Photo')
->acceptedFileTypes(['image/*'])
->preserveFilenames(),
])
->columns(2);
}
}
Contributing
Please see CONTRIBUTING for details on how to contribute to this project.
Security
If you discover any security vulnerabilities, please email security@yourproject.com instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.
Support
Built with <3 using Laravel, Filament, and modern PHP practices.