10-04-2026
This commit is contained in:
parent
4d6b4930b2
commit
4bb89aad8c
836 changed files with 52961 additions and 5950 deletions
493
packages/flux-cms/SETUP.md
Normal file
493
packages/flux-cms/SETUP.md
Normal file
|
|
@ -0,0 +1,493 @@
|
|||
# Flux CMS — Schritt-für-Schritt Setup-Anleitung
|
||||
|
||||
Diese Anleitung beschreibt die Integration von Flux CMS in ein neues Laravel-Projekt.
|
||||
|
||||
> **Migrierst du ein bestehendes Projekt?** Dann nutze stattdessen die kompakte **[MIGRATION.md](MIGRATION.md)** Checkliste.
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
- Laravel 11+ oder 12
|
||||
- Livewire 4 mit Volt
|
||||
- Flux UI (Free oder Pro)
|
||||
- `spatie/laravel-translatable` (wird vom Package mitgebracht)
|
||||
- `intervention/image` v3 (für Bildoptimierung)
|
||||
- Tailwind CSS v4
|
||||
- Heroicons (via `blade-ui-kit/blade-heroicons`)
|
||||
- Mehrsprachige `lang/`-Dateien (DE/EN oder andere)
|
||||
|
||||
---
|
||||
|
||||
## 1. Package installieren
|
||||
|
||||
### 1.1 Repository registrieren
|
||||
|
||||
```json
|
||||
// composer.json
|
||||
{
|
||||
"repositories": [
|
||||
{ "type": "path", "url": "package/flux-cms/core" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 1.2 Dependencies hinzufügen
|
||||
|
||||
```bash
|
||||
composer require flux-cms/core:@dev
|
||||
composer require intervention/image
|
||||
```
|
||||
|
||||
### 1.3 Konfiguration publizieren
|
||||
|
||||
```bash
|
||||
php artisan vendor:publish --tag=flux-cms-config
|
||||
```
|
||||
|
||||
### 1.4 Migrations ausführen
|
||||
|
||||
```bash
|
||||
php artisan migrate
|
||||
```
|
||||
|
||||
Dies erstellt folgende Tabellen:
|
||||
- `flux_cms_contents` — Alle Seiteninhalte (Key-Value mit Übersetzungen)
|
||||
- `flux_cms_news_items` — Nachrichteneinträge
|
||||
- `flux_cms_industries` — Branchen-Band
|
||||
- `flux_cms_faqs` — FAQ-Einträge
|
||||
- `flux_cms_downloads` — Downloads (PDFs, etc.)
|
||||
- `flux_cms_linkedin_posts` — LinkedIn-Posts
|
||||
- `flux_cms_media` — Medienbibliothek (Bilder, PDFs)
|
||||
|
||||
**Hinweis:** Je nach Projekt-Erweiterung können zusätzliche Migrations nötig sein (z.B. für erweiterte Downloads mit Highlights/Checkpoints).
|
||||
|
||||
---
|
||||
|
||||
## 2. Helper-Funktionen einrichten
|
||||
|
||||
### 2.1 Datei erstellen
|
||||
|
||||
Erstelle `app/helpers.php`:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use FluxCms\Core\Models\CmsMedia;
|
||||
use FluxCms\Core\Services\CmsContentService;
|
||||
|
||||
if (! function_exists('cms')) {
|
||||
function cms(string $key, array $replace = [], ?string $locale = null): mixed
|
||||
{
|
||||
return app(CmsContentService::class)->get($key, $replace, $locale);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('tcms')) {
|
||||
function tcms(string $key, array $replace = [], ?string $locale = null): string
|
||||
{
|
||||
$text = cms($key, $replace, $locale);
|
||||
return is_string($text) ? $text : (string) $text;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('cms_media_url')) {
|
||||
/**
|
||||
* Resolve a CmsContent key (type=image) to a full media URL.
|
||||
* Falls back to asset('assets/images/...') if not found in media library.
|
||||
*/
|
||||
function cms_media_url(string $key, string $profile = ''): string
|
||||
{
|
||||
$filename = cms($key);
|
||||
if (! $filename || ! is_string($filename) || $filename === $key) {
|
||||
$fallback = str_replace('.', '/', $key);
|
||||
return asset('assets/images/' . basename($fallback));
|
||||
}
|
||||
return media_url($filename, $profile);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('media_url')) {
|
||||
/**
|
||||
* Resolve a CmsMedia filename to its full storage URL.
|
||||
* Uses in-memory cache to avoid repeated DB queries.
|
||||
*/
|
||||
function media_url(?string $filename, string $profile = ''): string
|
||||
{
|
||||
if (! $filename || $filename === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
static $resolved = [];
|
||||
$cacheKey = $filename . '|' . $profile;
|
||||
|
||||
if (isset($resolved[$cacheKey])) {
|
||||
return $resolved[$cacheKey];
|
||||
}
|
||||
|
||||
$media = CmsMedia::where('filename', $filename)->first();
|
||||
if (! $media) {
|
||||
$resolved[$cacheKey] = asset('assets/images/' . $filename);
|
||||
return $resolved[$cacheKey];
|
||||
}
|
||||
|
||||
if ($profile && $media->hasConversion($profile)) {
|
||||
$resolved[$cacheKey] = $media->getConversionUrl($profile);
|
||||
} else {
|
||||
$resolved[$cacheKey] = $media->getUrl();
|
||||
}
|
||||
|
||||
return $resolved[$cacheKey];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 Autoload registrieren
|
||||
|
||||
```json
|
||||
// composer.json → autoload
|
||||
{
|
||||
"autoload": {
|
||||
"files": ["app/helpers.php"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
composer dump-autoload
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Admin-Oberfläche einrichten
|
||||
|
||||
### 3.1 Layout erstellen
|
||||
|
||||
Kopiere `core/resources/views/admin-reference/layout-cms.blade.php` nach `resources/views/components/layouts/cms.blade.php`.
|
||||
|
||||
Passe die Sidebar-Navigation an:
|
||||
- Branding/Logo
|
||||
- Navigationspunkte: Dashboard, Inhalte, Medienbibliothek, News, Industries, Downloads, Team, FAQs, LinkedIn
|
||||
- Benutzer-Menü
|
||||
|
||||
**Wichtig:** Das Layout muss `<flux:toast />` enthalten für die Benachrichtigungen.
|
||||
|
||||
### 3.2 Admin Views kopieren
|
||||
|
||||
```bash
|
||||
mkdir -p resources/views/livewire/admin/cms/
|
||||
|
||||
cp package/flux-cms/core/resources/views/admin-reference/cms/*.blade.php \
|
||||
resources/views/livewire/admin/cms/
|
||||
```
|
||||
|
||||
| View | Datei | Beschreibung |
|
||||
|------|-------|-------------|
|
||||
| Dashboard | `dashboard-index.blade.php` | Übersicht mit Statistiken |
|
||||
| Inhalte | `content-index.blade.php` | Haupteditor (Text/HTML/Image/JSON) |
|
||||
| Medienbibliothek | `media-index.blade.php` | Zentrale Medienverwaltung (Grid+Liste) |
|
||||
| News | `news-index.blade.php` | CRUD mit MediaPicker für Bild + PDF |
|
||||
| Industries | `industries-index.blade.php` | CRUD mit Sortierung |
|
||||
| FAQs | `faqs-index.blade.php` | CRUD nach Kategorien |
|
||||
| LinkedIn | `linkedin-index.blade.php` | CRUD mit MediaPicker |
|
||||
| Downloads | `downloads-index.blade.php` | CRUD für Case Studies/Capabilities/Stories |
|
||||
| Team | `team-index.blade.php` | CRUD mit MediaPicker für Profilbilder |
|
||||
| Suchindex | `search-index.blade.php` | Seitensuche: Keywords, Kategorien, Vorschau |
|
||||
|
||||
### 3.3 Livewire-Komponenten einrichten
|
||||
|
||||
Funktionale Volt-Komponenten können kein `WithFileUploads` verwenden. Daher gibt es class-based Livewire-Komponenten:
|
||||
|
||||
```bash
|
||||
# Multi-File Upload
|
||||
cp package/flux-cms/core/src/Helpers/MediaLibraryUploader.php \
|
||||
app/Livewire/Admin/Cms/MediaLibraryUploader.php
|
||||
|
||||
# Medienauswahl-Modal
|
||||
cp package/flux-cms/core/src/Helpers/MediaPicker.php \
|
||||
app/Livewire/Admin/Cms/MediaPicker.php
|
||||
```
|
||||
|
||||
Namespace in beiden Dateien anpassen:
|
||||
```php
|
||||
namespace App\Livewire\Admin\Cms;
|
||||
```
|
||||
|
||||
### 3.4 Blade-Views für Livewire-Komponenten
|
||||
|
||||
```bash
|
||||
# MediaLibraryUploader View
|
||||
cp package/flux-cms/core/resources/views/admin-reference/cms/media-library-uploader.blade.php \
|
||||
resources/views/livewire/admin/cms/media-library-uploader.blade.php
|
||||
|
||||
# MediaPicker View
|
||||
cp package/flux-cms/core/resources/views/admin-reference/cms/media-picker.blade.php \
|
||||
resources/views/livewire/admin/cms/media-picker.blade.php
|
||||
```
|
||||
|
||||
### 3.5 Routes registrieren
|
||||
|
||||
```php
|
||||
// routes/web.php
|
||||
use Livewire\Volt\Volt;
|
||||
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Volt::route('admin/cms', 'admin.cms.dashboard-index')->name('cms.dashboard');
|
||||
Volt::route('admin/cms/content', 'admin.cms.content-index')->name('cms.content.index');
|
||||
Volt::route('admin/cms/media', 'admin.cms.media-index')->name('cms.media.index');
|
||||
Volt::route('admin/cms/news', 'admin.cms.news-index')->name('cms.news.index');
|
||||
Volt::route('admin/cms/industries', 'admin.cms.industries-index')->name('cms.industries.index');
|
||||
Volt::route('admin/cms/faqs', 'admin.cms.faqs-index')->name('cms.faqs.index');
|
||||
Volt::route('admin/cms/linkedin', 'admin.cms.linkedin-index')->name('cms.linkedin.index');
|
||||
Volt::route('admin/cms/downloads', 'admin.cms.downloads-index')->name('cms.downloads.index');
|
||||
Volt::route('admin/cms/team', 'admin.cms.team-index')->name('cms.team.index');
|
||||
Volt::route('admin/cms/search-index', 'admin.cms.search-index')->name('cms.search-index');
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Medienbibliothek einrichten
|
||||
|
||||
### 4.1 Storage-Link
|
||||
|
||||
```bash
|
||||
php artisan storage:link
|
||||
```
|
||||
|
||||
### 4.2 Storage-Verzeichnisse
|
||||
|
||||
Die Verzeichnisse werden automatisch erstellt beim ersten Upload:
|
||||
- `storage/app/public/cms/media/originals/` — Original-Uploads
|
||||
- `storage/app/public/cms/media/conversions/` — Generierte Bildgrößen
|
||||
- `storage/app/public/cms/media/thumbnails/` — Auto-Thumbnails
|
||||
|
||||
### 4.3 Bildprofile konfigurieren
|
||||
|
||||
In `config/flux-cms.php` die Conversion-Profile an dein Projekt anpassen:
|
||||
|
||||
```php
|
||||
'media' => [
|
||||
'max_upload_size' => 20480, // KB
|
||||
'allowed_types' => ['jpg', 'jpeg', 'png', 'webp', 'gif', 'svg', 'pdf', 'doc', 'docx'],
|
||||
'storage_disk' => 'public',
|
||||
'profiles' => [
|
||||
'hero' => ['width' => 1920, 'height' => 800, 'format' => 'webp', 'quality' => 85],
|
||||
'card' => ['width' => 768, 'height' => 512, 'format' => 'webp', 'quality' => 80],
|
||||
'thumbnail' => ['width' => 400, 'height' => 300, 'format' => 'webp', 'quality' => 75],
|
||||
'avatar' => ['width' => 400, 'height' => 400, 'format' => 'webp', 'quality' => 80],
|
||||
'news' => ['width' => 1200, 'height' => 630, 'format' => 'webp', 'quality' => 80],
|
||||
'thumb' => ['width' => 200, 'height' => 200, 'format' => 'webp', 'quality' => 70],
|
||||
],
|
||||
],
|
||||
```
|
||||
|
||||
### 4.4 HTTPS / Proxy
|
||||
|
||||
Falls hinter einem Reverse Proxy, in `bootstrap/app.php`:
|
||||
|
||||
```php
|
||||
->withMiddleware(function (Middleware $middleware) {
|
||||
$middleware->trustProxies(at: '*');
|
||||
})
|
||||
```
|
||||
|
||||
Und in `AppServiceProvider::boot()`:
|
||||
|
||||
```php
|
||||
if (request()->header('X-Forwarded-Proto') === 'https' || app()->environment('production')) {
|
||||
URL::forceScheme('https');
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Inhalte importieren (Seeder)
|
||||
|
||||
### 5.1 Seeders kopieren & anpassen
|
||||
|
||||
```bash
|
||||
cp package/flux-cms/core/database/seeders-reference/*.php database/seeders/
|
||||
```
|
||||
|
||||
### 5.2 CmsContentSeeder anpassen
|
||||
|
||||
```php
|
||||
protected array $skipFiles = [
|
||||
'faqs', 'sections', 'validation', 'auth', 'passwords', 'pagination',
|
||||
];
|
||||
|
||||
protected array $skipKeys = [
|
||||
'components' => ['news_band', 'industries_band'],
|
||||
];
|
||||
```
|
||||
|
||||
### 5.3 CmsMediaSeeder erstellen
|
||||
|
||||
Erstelle einen Seeder, der alle hochgeladenen Medien und die `CmsContent`-Einträge vom Typ `image` wiederherstellt. Dieser wird nach dem `CmsContentSeeder` ausgeführt, um Image-Keys zu erzeugen (z.B. `welcome.hero.image` → Dateiname).
|
||||
|
||||
### 5.4 CmsDownloadSeeder erstellen (optional)
|
||||
|
||||
Falls du Downloads (Case Studies, Capabilities, Success Stories) verwendest, erstelle einen Seeder mit den vollständigen Inline-Daten.
|
||||
|
||||
### 5.5 DatabaseSeeder registrieren
|
||||
|
||||
```php
|
||||
public function run(): void
|
||||
{
|
||||
$this->call([
|
||||
CmsContentSeeder::class,
|
||||
CmsMediaSeeder::class,
|
||||
CmsNewsItemSeeder::class,
|
||||
CmsIndustrySeeder::class,
|
||||
CmsFaqSeeder::class,
|
||||
CmsLinkedinPostSeeder::class,
|
||||
CmsDownloadSeeder::class,
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
||||
### 5.6 Seeding ausführen
|
||||
|
||||
```bash
|
||||
php artisan db:seed
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Frontend umstellen
|
||||
|
||||
### 6.1 `__()` durch `cms()` ersetzen
|
||||
|
||||
```diff
|
||||
- {{ __('welcome.hero.heading') }}
|
||||
+ {{ cms('welcome.hero.heading') }}
|
||||
```
|
||||
|
||||
### 6.2 Bilder über Medienbibliothek laden
|
||||
|
||||
```diff
|
||||
- <img src="{{ asset('assets/images/keyvisual.webp') }}" />
|
||||
+ <img src="{{ cms_media_url('welcome.hero.image', 'hero') }}" />
|
||||
```
|
||||
|
||||
Oder direkt über Dateiname:
|
||||
```blade
|
||||
<img src="{{ media_url($item['image'], 'card') }}" />
|
||||
```
|
||||
|
||||
### 6.3 Downloads über CmsDownload
|
||||
|
||||
```blade
|
||||
@foreach (CmsDownload::published()->byCategory('case_study')->ordered()->get() as $dl)
|
||||
<x-download-article-card :article="$dl->toFrontendArray()" :index="$loop->index" />
|
||||
@endforeach
|
||||
```
|
||||
|
||||
### 6.4 News über CmsNewsItem
|
||||
|
||||
```blade
|
||||
@php
|
||||
$items = CmsNewsItem::published()->ordered()->get()
|
||||
->map(fn($i) => $i->toFrontendArray())->toArray();
|
||||
@endphp
|
||||
```
|
||||
|
||||
### 6.5 :highlight Pattern
|
||||
|
||||
```blade
|
||||
{!! cms('welcome.solutions.heading', [
|
||||
'highlight' => '<span class="text-gradient-premium">'
|
||||
. cms('welcome.solutions.heading_highlight') . '</span>',
|
||||
]) !!}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Tests einrichten
|
||||
|
||||
### 7.1 Test-Dateien kopieren
|
||||
|
||||
```bash
|
||||
cp -r package/flux-cms/core/tests-reference/Feature/Cms tests/Feature/Cms
|
||||
```
|
||||
|
||||
### 7.2 Tests ausführen
|
||||
|
||||
```bash
|
||||
php artisan test --filter=Cms
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Anpassungen für dein Projekt
|
||||
|
||||
### Sprachen hinzufügen
|
||||
|
||||
`config/flux-cms.php`:
|
||||
```php
|
||||
'locales' => [
|
||||
'de' => 'Deutsch',
|
||||
'en' => 'English',
|
||||
'fr' => 'Français',
|
||||
],
|
||||
```
|
||||
|
||||
### Neue Content-Typen
|
||||
|
||||
1. Migration + Model mit `HasTranslations`
|
||||
2. Admin-View als Volt-Komponente
|
||||
3. Route registrieren, Sidebar-Link hinzufügen
|
||||
4. `toFrontendArray()` Methode für Frontend-Integration
|
||||
5. Seeder erstellen
|
||||
|
||||
### Editor-Toolbar
|
||||
|
||||
- **Standard** (`bold italic`): Normale Texte
|
||||
- **Voll** (`heading | bold italic underline strike | bullet ordered blockquote | link`): Impressum, Datenschutz, News-Body
|
||||
|
||||
### Icon-Auswahl (Performance)
|
||||
|
||||
Die Icon-Auswahl nutzt Blade Heroicons. Nur der Name wird im Dropdown angezeigt, das SVG nur als Vorschau neben dem Select-Feld — damit werden nicht 2800+ SVGs gerendert.
|
||||
|
||||
---
|
||||
|
||||
## Verzeichnisstruktur nach Installation
|
||||
|
||||
```
|
||||
dein-projekt/
|
||||
├── app/
|
||||
│ ├── helpers.php # cms(), tcms(), cms_media_url(), media_url()
|
||||
│ └── Livewire/Admin/Cms/
|
||||
│ ├── MediaLibraryUploader.php # Multi-File Upload
|
||||
│ └── MediaPicker.php # Medienauswahl-Modal
|
||||
├── config/
|
||||
│ └── flux-cms.php # CMS + Media Konfiguration
|
||||
├── database/
|
||||
│ ├── migrations/
|
||||
│ │ └── *_create_flux_cms_*.php # Automatisch vom Package
|
||||
│ └── seeders/
|
||||
│ ├── CmsContentSeeder.php # Lang → DB
|
||||
│ ├── CmsMediaSeeder.php # Medien + Image-Content
|
||||
│ ├── CmsDownloadSeeder.php # Case Studies etc.
|
||||
│ ├── CmsNewsItemSeeder.php
|
||||
│ ├── CmsIndustrySeeder.php
|
||||
│ ├── CmsFaqSeeder.php
|
||||
│ └── CmsLinkedinPostSeeder.php
|
||||
├── package/flux-cms/core/ # Das Package
|
||||
├── resources/views/
|
||||
│ ├── components/layouts/
|
||||
│ │ └── cms.blade.php # Admin-Layout
|
||||
│ └── livewire/admin/cms/
|
||||
│ ├── content-index.blade.php # Content-Editor
|
||||
│ ├── media-index.blade.php # Medienbibliothek
|
||||
│ ├── media-library-uploader.blade.php
|
||||
│ ├── media-picker.blade.php
|
||||
│ ├── news-index.blade.php
|
||||
│ ├── downloads-index.blade.php
|
||||
│ ├── team-index.blade.php
|
||||
│ ├── linkedin-index.blade.php
|
||||
│ ├── industries-index.blade.php
|
||||
│ ├── faqs-index.blade.php
|
||||
│ ├── search-index.blade.php # Suchindex-Verwaltung
|
||||
│ └── dashboard.blade.php # CMS-Dashboard
|
||||
└── routes/web.php # CMS-Routes
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue