Table of Contents
Architecture
CMS Page Structure
Content editors create pages in Filament Admin (/admin
) using the Fabricator Page Builder. Pages are stored in the pages` ` table with a blocks JSON column. Fabricator automatically routes pages based on their slugs—for example, the slug de/faq` ` is routed to /de/faq .
Pages support hierarchical parent-child relationships viaparent_id
(self-referential foreign key with cascade delete).
Existing Page Blocks
| Block | Class | Fields |
|---|---|---|
rich-text |
||
RichTextBlock |
||
heading |
||
,content |
||
image |
||
ImageBlock |
||
image |
||
,alt |
||
,caption |
||
,align |
||
- RichTextBlock: Heading (optional), Content (RichEditor with file attachments). Output is filtered by an HTML sanitizer (Symfony HtmlSanitizer) with a strict allowlist — scripts, event handlers, and
data:URIs are removed; links automatically receiverel="noopener noreferrer". - ImageBlock: Image (JPEG/PNG/GIF/WEBP, max 10 MB), alt text, caption (optional), alignment (left/center/right) with XSS validation.
Add a new page block
-
Create a class in
app/Filament/Fabricator/PageBlocks/(extendsPageBlock) -
Define form fields in
getBlockSchema() -
Optionally override
mutateData()for post-processing -
Create a Blade view in
resources/views/components/filament-fabricator/page-blocks/ -
Fabricator automatically registers the block
Multilingual Support
- URL-based routing: Pages with
/deor/enprefix - Client-side locale detection in the Blade layout: Extracts language from URL segment
- Dynamic language switch button with label dictionaries (18+ keys per language)
- Seeder: Creates parallel de/en page trees with localized content (~15 pages per language)
- Note: No Laravel translation files — labels are currently hardcoded in the Blade template
Registration Counter
API endpoint at/api/regcount
(rate-limited: 30 requests/min), which retrieves the registration count from the external SpringFurCon registration page:
- Primary: Regex pattern matching on “Reg-Counter”
- Fallback: DOM-based XPath search
- Caching: 5 minutes with distributed lock (Thundering Herd protection)
- Graceful Degradation: In case of error, the last cached value is returned
- Pages integrate the counter via the
<span data-regcount>placeholder
Crawl Route
GET /crawl/{path?}
serves static HTML files from acrawl/
directory:
- Path traversal protection with
realpath()and prefix validation - Directories are automatically resolved to
index.html
-Cache-Control: no-cache, no-store, must-revalidate
- Purpose: Hosting of externally crawled/cached content (images, static pages from an external CMS)
Custom Artisan Commands
- **
admin:create**: Creates or promotes users to admin- Email-based search
- Interactive password prompt with auto-generation (16 characters)
- Validation: Email format, min. 8-character password
- Uses
is_adminBoolean flag
Routing
-GET /
— Redirect to/de
-GET /crawl/{path?}
— Static HTML fromcrawl/
-GET /api/regcount
— Registration counter API
- All other pages via Fabricator slug routing
- Admin panel at
/admin(Filament, session auth)
Directory structure
app/
├── Console/Commands/AdminCreateCommand.php Admin-Erstellung
├── Filament/Fabricator/PageBlocks/ Block-Definitionen mit Sanitizer
├── Filament/Fabricator/Layouts/ Layout-Definitionen
├── Http/Controllers/RegcountController.php Registrierungs-Counter API
└── Providers/Filament/AdminPanelProvider.php Filament-Konfiguration (Emerald Theme)
resources/views/
├── components/filament-fabricator/ Blade-Views der Blocks + Layouts
└── *.blade.php Statische Templates
database/
├── migrations/ Users, Pages, Cache, Jobs
└── seeders/FabricatorPageSeeder.php Bilingualer Content (~1600 Zeilen)
Uploads
Uploaded files are located atstorage/app/public/
:
-page-images/
— Images from ImageBlock
-page-attachments/
— File attachments from RichTextBlock
The storage symlink (php artisan storage:link
) must be created before the first upload.
Tests
11 test files:
- RichTextBlockTest (13 tests): HTML sanitization, XSS prevention, allowed tags
- ImageBlockTest (6 tests): Alignment validation, data mutation
- ImageBlockRenderTest (6 tests): Page rendering with images, captions, alignment classes
- RegcountExtractionTest (8 tests): Regex and DOM extraction, edge cases
Test configuration: SQLite:memory:
, array cache, sync queue.