Generated Theme Images
Generated theme images give theme cards and theme selects a useful visual fallback when a theme has no manually uploaded preview image.
The feature is admin-only. It stores generated preview state on the theme’s admin JSON payload and writes a PNG into the public storage disk. It does not change frontend rendering, theme CSS, cached page HTML, or static exports.
When Generation Runs
Section titled “When Generation Runs”Theme image generation is triggered from Capell\Core\Observers\ThemeObserver after a theme is saved.
On save, the observer:
- Checks whether the theme has a manual admin image.
- If a manual image exists, deletes any old generated image metadata and file.
- If no manual image exists, calculates a generation signature from the theme name, key, colors, and admin icon.
- If the current generated image is missing or stale, deletes the old generated file, marks generation as
pending, and dispatchesGenerateThemeImageActionas a queued job.
The generated image is removed before the queued job runs. Admin UI should therefore show no generated image while the new image is pending.
Stored Metadata
Section titled “Stored Metadata”Generated image state lives in themes.admin:
| Key | Meaning |
|---|---|
generated_image | Public storage path to the generated PNG |
generated_image_signature | Hash of preview-relevant theme data |
generated_image_status | pending, ready, or failed |
generated_image_error | Short failure message when generation fails |
Manual preview images still use the existing admin image/media fields. A manual image always wins over a generated image.
Image Composition
Section titled “Image Composition”GenerateThemeImageAction creates a 1200x1200 PNG using GD. The output is a square block image made from the theme’s meta colors:
primaryfills the largest block.secondaryfills the next block.- the first remaining color fills the third block.
Only these three color tiers are used. If a theme has two colors, the image contains two fitted blocks. If it has one color, the image is a single solid square.
If the theme has an admin icon, the generator derives a short text mark from the icon name and draws it over the primary block with contrast-aware text color. This keeps the generated image simple and avoids persisting SVG or authoring markup.
Display Rules
Section titled “Display Rules”Admin preview surfaces resolve images in this order:
- Manual media/admin image.
- Ready generated image.
- No image.
pending and failed generated images are not shown. Theme cards fall back to their normal title placeholder when no displayable image exists.
Main Classes
Section titled “Main Classes”| Class | Responsibility |
|---|---|
ThemeObserver | Detects save events and queues/clears generated images |
GenerateThemeImageAction | Queued job/action that renders and stores the PNG |
InvalidateGeneratedThemeImageAction | Deletes stale generated files and marks generation pending |
ClearGeneratedThemeImageAction | Removes generated state when a manual image exists |
Theme::generatedImageSignature() | Builds the preview-relevant signature |
Theme::readyGeneratedImage() | Returns only displayable ready generated images |
ThemeCardData and ThemeSelect | Prefer manual images, then ready generated images |
Operational Notes
Section titled “Operational Notes”- The queue worker must be running for generated images to appear after save.
- The public storage disk must be writable.
- GD must be available because the generator writes PNGs directly.
- A stale queued job will not overwrite a newer signature.
- Manual image changes do not leave old generated images behind; generated state is cleared when a manual image exists.