# 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! 🚀
