597 lines
14 KiB
Markdown
597 lines
14 KiB
Markdown
# Flux CMS Installation Guide
|
|
|
|
This guide will walk you through installing and setting up Flux CMS in your Laravel application.
|
|
|
|
## System Requirements
|
|
|
|
- **PHP**: 8.2 or higher
|
|
- **Laravel**: 11.0 or higher
|
|
- **Livewire**: 3.0 or higher
|
|
- **Database**: MySQL 8.0+ or PostgreSQL 13+
|
|
- **Node.js**: 18+ (for asset compilation)
|
|
|
|
## Required Laravel Packages
|
|
|
|
Flux CMS requires these packages to be installed:
|
|
|
|
- `spatie/laravel-translatable`: For multilingual content
|
|
- `spatie/laravel-medialibrary`: For media management
|
|
- `spatie/laravel-tags`: For tagging blog posts
|
|
- `livewire/livewire`: For reactive components
|
|
- `livewire/flux`: For UI components (recommended)
|
|
|
|
## Step-by-Step Installation
|
|
|
|
### 1. Install Required Dependencies
|
|
|
|
```bash
|
|
# Install required packages
|
|
composer require spatie/laravel-translatable spatie/laravel-medialibrary spatie/laravel-tags
|
|
|
|
# Install Livewire if not already installed
|
|
composer require livewire/livewire
|
|
|
|
# Install Flux UI (recommended for admin interface)
|
|
composer require livewire/flux
|
|
```
|
|
|
|
### 2. Install Flux CMS Packages
|
|
|
|
```bash
|
|
# Install core package
|
|
composer require flux-cms/core
|
|
|
|
# Install components package (recommended)
|
|
composer require flux-cms/components
|
|
|
|
# Install starter components (optional)
|
|
composer require flux-cms/starter-components
|
|
```
|
|
|
|
### 3. Run Installation Command
|
|
|
|
```bash
|
|
# This will publish config, run migrations, and set up permissions
|
|
php artisan flux-cms:install
|
|
|
|
# Or with options
|
|
php artisan flux-cms:install --no-migrate --no-publish
|
|
```
|
|
|
|
The installation command will:
|
|
- ✅ Check system requirements
|
|
- 📦 Publish configuration files
|
|
- 🗃️ Run database migrations
|
|
- 🔗 Create storage link
|
|
- 📝 Create sample content (optional)
|
|
- 🔐 Set up permissions (optional)
|
|
|
|
### 4. Configure Your Application
|
|
|
|
#### Environment Variables
|
|
|
|
Add these to your `.env` file:
|
|
|
|
```env
|
|
# Flux CMS Configuration
|
|
FLUX_CMS_DEFAULT_LOCALE=de
|
|
FLUX_CMS_CACHE_ENABLED=true
|
|
FLUX_CMS_ROUTES_ENABLED=true
|
|
|
|
# Media Configuration
|
|
FLUX_CMS_MEDIA_DISK=public
|
|
FLUX_CMS_MAX_FILE_SIZE=10240
|
|
|
|
# Multi-domain (if using)
|
|
FLUX_CMS_MULTI_DOMAIN=true
|
|
FLUX_CMS_AUTO_DETECT_DOMAIN=true
|
|
```
|
|
|
|
#### Update App Configuration
|
|
|
|
```php
|
|
// config/app.php
|
|
'locale' => env('APP_LOCALE', 'de'),
|
|
'fallback_locale' => 'de',
|
|
|
|
// Add available locales
|
|
'available_locales' => ['de', 'en'],
|
|
```
|
|
|
|
### 5. Set Up Routes
|
|
|
|
#### Admin Routes
|
|
|
|
Add to your `routes/web.php` or create `routes/admin.php`:
|
|
|
|
```php
|
|
// Admin routes (protected)
|
|
Route::middleware(['web', 'auth'])->prefix('admin')->name('admin.')->group(function () {
|
|
Route::prefix('cms')->name('cms.')->group(function () {
|
|
Route::get('/', [Admin\DashboardController::class, 'index'])->name('index');
|
|
Route::resource('/pages', Admin\PageController::class)->except(['show']);
|
|
Route::get('/blog', [Admin\BlogController::class, 'index'])->name('blog.index');
|
|
Route::get('/media', [Admin\MediaController::class, 'index'])->name('media.index');
|
|
Route::get('/navigation', [Admin\NavigationController::class, 'index'])->name('navigation.index');
|
|
});
|
|
});
|
|
```
|
|
|
|
#### Frontend Routes
|
|
|
|
Add to your `routes/web.php` (MUST be at the end):
|
|
|
|
```php
|
|
// SEO routes
|
|
Route::get('/sitemap.xml', [PageController::class, 'sitemap'])->name('sitemap');
|
|
Route::get('/robots.txt', [PageController::class, 'robots'])->name('robots');
|
|
|
|
// Blog routes (if using blog)
|
|
Route::prefix('blog')->name('blog.')->group(function () {
|
|
Route::get('/', [PageController::class, 'blogIndex'])->name('index');
|
|
Route::get('/{slug}', [PageController::class, 'blogPost'])->name('show');
|
|
});
|
|
|
|
// CMS pages - MUST BE LAST!
|
|
Route::get('/{slug?}', [PageController::class, 'show'])
|
|
->where('slug', '.*')
|
|
->name('cms.page');
|
|
```
|
|
|
|
### 6. Create Controllers
|
|
|
|
#### Page Controller
|
|
|
|
```php
|
|
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use FluxCms\Core\Models\Page;
|
|
use Illuminate\Http\Request;
|
|
|
|
class PageController extends Controller
|
|
{
|
|
public function show(Request $request, string $slug = '/')
|
|
{
|
|
// Get domain key from existing domains config
|
|
$domainKey = $this->getCurrentDomainKey($request);
|
|
$locale = app()->getLocale();
|
|
|
|
// Find page
|
|
$page = Page::forDomain($domainKey)
|
|
->bySlug($slug, $locale)
|
|
->published()
|
|
->firstOrFail();
|
|
|
|
// Load components
|
|
$components = $page->components()->get();
|
|
|
|
return view('pages.show', compact('page', 'components'));
|
|
}
|
|
|
|
public function sitemap(Request $request)
|
|
{
|
|
$domainKey = $this->getCurrentDomainKey($request);
|
|
$pages = Page::forDomain($domainKey)->published()->get();
|
|
|
|
return response()->view('sitemap', compact('pages'))
|
|
->header('Content-Type', 'application/xml');
|
|
}
|
|
|
|
protected function getCurrentDomainKey(Request $request): string
|
|
{
|
|
$host = $request->getHost();
|
|
$domains = config('domains.domains', []);
|
|
|
|
foreach ($domains as $key => $config) {
|
|
if (isset($config['url']) && parse_url($config['url'], PHP_URL_HOST) === $host) {
|
|
return $key;
|
|
}
|
|
}
|
|
|
|
return config('flux-cms.domains.default_domain', 'default');
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Admin Controller
|
|
|
|
```php
|
|
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use FluxCms\Core\Models\Page;
|
|
|
|
class CmsController extends Controller
|
|
{
|
|
public function __construct()
|
|
{
|
|
$this->middleware('can:flux-cms.view');
|
|
}
|
|
|
|
public function index()
|
|
{
|
|
$stats = [
|
|
'pages' => Page::count(),
|
|
'published_pages' => Page::published()->count(),
|
|
'draft_pages' => Page::where('is_published', false)->count(),
|
|
];
|
|
|
|
return view('admin.cms.index', compact('stats'));
|
|
}
|
|
|
|
public function pages()
|
|
{
|
|
$pages = Page::with(['components'])
|
|
->orderBy('updated_at', 'desc')
|
|
->paginate(20);
|
|
|
|
return view('admin.cms.pages', compact('pages'));
|
|
}
|
|
|
|
public function editPage(Page $page)
|
|
{
|
|
$this->authorize('flux-cms.edit');
|
|
|
|
return view('admin.cms.edit-page', compact('page'));
|
|
}
|
|
}
|
|
```
|
|
|
|
### 7. Create Views
|
|
|
|
#### Frontend Page Template
|
|
|
|
```blade
|
|
{{-- resources/views/pages/show.blade.php --}}
|
|
@extends('layouts.app')
|
|
|
|
@section('title', $page->getSeoTitle())
|
|
@section('description', $page->getSeoDescription())
|
|
|
|
@push('meta')
|
|
<meta property="og:title" content="{{ $page->getTranslation('title') }}">
|
|
<meta property="og:description" content="{{ $page->getSeoDescription() }}">
|
|
<meta property="og:url" content="{{ request()->url() }}">
|
|
@if($page->getTranslation('og_image'))
|
|
<meta property="og:image" content="{{ $page->getTranslation('og_image') }}">
|
|
@endif
|
|
@endpush
|
|
|
|
@section('content')
|
|
<main class="cms-page">
|
|
@foreach($components as $component)
|
|
@if($component->canRender())
|
|
<div class="cms-component" data-component="{{ class_basename($component->component_class) }}">
|
|
@livewire($component->component_class, [
|
|
'content' => $component->getTranslations('content')
|
|
], key('component-' . $component->id))
|
|
</div>
|
|
@endif
|
|
@endforeach
|
|
</main>
|
|
@endsection
|
|
```
|
|
|
|
#### Admin Views
|
|
|
|
```blade
|
|
{{-- resources/views/admin/cms/edit-page.blade.php --}}
|
|
@extends('layouts.admin')
|
|
|
|
@section('title', 'Edit Page: ' . $page->getTranslation('title'))
|
|
|
|
@section('content')
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
@livewire('flux-cms::page-editor', ['page' => $page])
|
|
</div>
|
|
@endsection
|
|
|
|
@push('scripts')
|
|
<script>
|
|
// Enable drag & drop sorting
|
|
Livewire.on('components-reordered', (orderedIds) => {
|
|
// Handle reordering feedback
|
|
console.log('Components reordered:', orderedIds);
|
|
});
|
|
|
|
// Preview functionality
|
|
Livewire.on('open-preview', (url) => {
|
|
window.open(url, '_blank');
|
|
});
|
|
</script>
|
|
@endpush
|
|
```
|
|
|
|
### 8. Set Up Permissions
|
|
|
|
If you're using Spatie Laravel Permission:
|
|
|
|
```php
|
|
// database/seeders/CmsPermissionSeeder.php
|
|
<?php
|
|
|
|
namespace Database\Seeders;
|
|
|
|
use Illuminate\Database\Seeder;
|
|
use Spatie\Permission\Models\Permission;
|
|
use Spatie\Permission\Models\Role;
|
|
|
|
class CmsPermissionSeeder extends Seeder
|
|
{
|
|
public function run()
|
|
{
|
|
// Create permissions
|
|
$permissions = [
|
|
'flux-cms.view',
|
|
'flux-cms.edit',
|
|
'flux-cms.publish',
|
|
'flux-cms.delete',
|
|
'flux-cms.admin',
|
|
];
|
|
|
|
foreach ($permissions as $permission) {
|
|
Permission::firstOrCreate(['name' => $permission]);
|
|
}
|
|
|
|
// Create CMS role
|
|
$cmsRole = Role::firstOrCreate(['name' => 'flux-cms']);
|
|
$cmsRole->syncPermissions($permissions);
|
|
|
|
// Assign to users
|
|
// User::find(1)->assignRole('flux-cms');
|
|
}
|
|
}
|
|
```
|
|
|
|
Run the seeder:
|
|
|
|
```bash
|
|
php artisan db:seed --class=CmsPermissionSeeder
|
|
```
|
|
|
|
### 9. Configure Multi-Domain (Optional)
|
|
|
|
If you're using multi-domain setup, ensure your `config/domains.php` is configured:
|
|
|
|
```php
|
|
// config/domains.php
|
|
return [
|
|
'domains' => [
|
|
'main' => [
|
|
'name' => 'Main Site',
|
|
'url' => env('APP_URL', 'https://example.com'),
|
|
'theme' => 'default',
|
|
],
|
|
'blog' => [
|
|
'name' => 'Blog Site',
|
|
'url' => 'https://blog.example.com',
|
|
'theme' => 'blog',
|
|
],
|
|
],
|
|
];
|
|
```
|
|
|
|
Update Flux CMS config:
|
|
|
|
```php
|
|
// config/flux-cms.php
|
|
'domains' => [
|
|
'enabled' => true,
|
|
'config_source' => 'domains', // Use domains.php config
|
|
'auto_detect' => true,
|
|
],
|
|
```
|
|
|
|
### 10. Create Your First Component
|
|
|
|
Generate a new component:
|
|
|
|
```bash
|
|
php artisan make:livewire Components/WelcomeHero
|
|
```
|
|
|
|
Update the component:
|
|
|
|
```php
|
|
<?php
|
|
|
|
namespace App\Livewire\Components;
|
|
|
|
use Livewire\Component;
|
|
use FluxCms\Core\FieldTypes\TextField;
|
|
use FluxCms\Core\FieldTypes\WysiwygField;
|
|
|
|
class WelcomeHero extends Component
|
|
{
|
|
public array $content = [];
|
|
|
|
public function mount(array $content = [])
|
|
{
|
|
$this->content = $content;
|
|
}
|
|
|
|
public static function getCmsName(): string
|
|
{
|
|
return 'Welcome Hero';
|
|
}
|
|
|
|
public static function getCmsCategory(): string
|
|
{
|
|
return 'Content';
|
|
}
|
|
|
|
public static function getCmsFields(): array
|
|
{
|
|
return [
|
|
TextField::make('headline', 'Headline')
|
|
->translatable()
|
|
->required(),
|
|
|
|
WysiwygField::make('description', 'Description')
|
|
->translatable(),
|
|
];
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.components.welcome-hero');
|
|
}
|
|
}
|
|
```
|
|
|
|
Create the view:
|
|
|
|
```blade
|
|
{{-- resources/views/livewire/components/welcome-hero.blade.php --}}
|
|
<section class="hero bg-gradient-to-r from-blue-500 to-purple-600 text-white py-20">
|
|
<div class="container mx-auto px-4 text-center">
|
|
@if($headline = $this->content['headline'][app()->getLocale()] ?? '')
|
|
<h1 class="text-5xl font-bold mb-6">{{ $headline }}</h1>
|
|
@endif
|
|
|
|
@if($description = $this->content['description'][app()->getLocale()] ?? '')
|
|
<div class="text-xl prose prose-lg prose-invert mx-auto">
|
|
{!! $description !!}
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</section>
|
|
```
|
|
|
|
### 11. Create Your First Page
|
|
|
|
```php
|
|
// database/seeders/CmsContentSeeder.php
|
|
<?php
|
|
|
|
namespace Database\Seeders;
|
|
|
|
use Illuminate\Database\Seeder;
|
|
use FluxCms\Core\Models\Page;
|
|
|
|
class CmsContentSeeder extends Seeder
|
|
{
|
|
public function run()
|
|
{
|
|
$homepage = Page::create([
|
|
'domain_key' => 'main',
|
|
'title' => [
|
|
'de' => 'Startseite',
|
|
'en' => 'Homepage'
|
|
],
|
|
'slug' => [
|
|
'de' => '/',
|
|
'en' => '/'
|
|
],
|
|
'meta_description' => [
|
|
'de' => 'Willkommen auf unserer Website',
|
|
'en' => 'Welcome to our website'
|
|
],
|
|
'is_published' => true,
|
|
]);
|
|
|
|
// Add welcome hero component
|
|
$homepage->allComponents()->create([
|
|
'component_class' => \App\Livewire\Components\WelcomeHero::class,
|
|
'order' => 1,
|
|
'content' => [
|
|
'headline' => [
|
|
'de' => 'Willkommen bei Flux CMS',
|
|
'en' => 'Welcome to Flux CMS'
|
|
],
|
|
'description' => [
|
|
'de' => 'Das moderne Content Management System für Laravel.',
|
|
'en' => 'The modern Content Management System for Laravel.'
|
|
]
|
|
],
|
|
]);
|
|
}
|
|
}
|
|
```
|
|
|
|
Run the seeder:
|
|
|
|
```bash
|
|
php artisan db:seed --class=CmsContentSeeder
|
|
```
|
|
|
|
## Verification
|
|
|
|
After installation, verify everything works:
|
|
|
|
1. **Visit admin interface**: `/admin/cms`
|
|
2. **Edit a page**: Click on your homepage
|
|
3. **Add components**: Try adding components to your page
|
|
4. **Check frontend**: Visit your homepage
|
|
5. **Test translations**: Switch languages if configured
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
#### 1. Component Registry Empty
|
|
|
|
```bash
|
|
# Clear cache and refresh
|
|
php artisan flux-cms:clear-cache
|
|
php artisan cache:clear
|
|
```
|
|
|
|
#### 2. Permission Denied
|
|
|
|
```bash
|
|
# Check if user has CMS role
|
|
php artisan tinker
|
|
> User::find(1)->assignRole('flux-cms');
|
|
```
|
|
|
|
#### 3. Media Files Not Loading
|
|
|
|
```bash
|
|
# Ensure storage link exists
|
|
php artisan storage:link
|
|
|
|
# Check disk configuration
|
|
php artisan tinker
|
|
> Storage::disk('public')->exists('test.txt');
|
|
```
|
|
|
|
#### 4. Routes Not Working
|
|
|
|
- Ensure CMS routes are at the **end** of `routes/web.php`
|
|
- Check middleware and permissions
|
|
- Verify domain configuration if using multi-domain
|
|
|
|
### Debug Mode
|
|
|
|
Enable debug mode in config:
|
|
|
|
```php
|
|
// config/flux-cms.php
|
|
'development' => [
|
|
'debug_mode' => true,
|
|
'show_component_info' => true,
|
|
'log_queries' => true,
|
|
],
|
|
```
|
|
|
|
### Getting Help
|
|
|
|
- 📖 **Documentation**: Check the full documentation
|
|
- 💬 **Community**: Join GitHub Discussions
|
|
- 🐛 **Issues**: Report bugs on GitHub
|
|
- 📧 **Support**: Contact support team
|
|
|
|
## Next Steps
|
|
|
|
1. **Create custom components** for your specific needs
|
|
2. **Set up navigation** using the navigation manager
|
|
3. **Configure domains** if using multi-domain
|
|
4. **Customize styling** to match your brand
|
|
5. **Set up deployment** with proper caching
|
|
|
|
You're now ready to start building amazing content with Flux CMS! 🚀
|