Implemented the dynamic theme manager and merged the supplied themes.

Included

* Standardised all six theme.json files to manifest version 2:
    * admin
    * common
    * corporate
    * saasland
    * swiss
    * welcome
* Every manifest now uses the same fields and structure.
* Separate active frontend and backend themes.
* One-click theme activation.
* Theme preview in a new browser tab without activating it.
* Theme cards showing:
    * Preview
    * Name
    * Version
    * Author
    * Description
    * Theme type
    * Active status
* Dynamic theme-specific settings.
* Support for:
    * Text
    * URL
    * Colour
    * Textarea
    * Checkbox fields
    * Variants
    * Appearance
    * Accent palettes
* Theme ZIP installation.
* Theme ZIP export.
* Asset optimisation.
* Accessibility validation.
* Safe ZIP path validation.
* Theme inheritance.
* Active themes cannot be uninstalled.
* Parent themes cannot be uninstalled while child themes depend on them.
* Stylist administration routes now require an authenticated, verified user.
* Manifest validation now restricts theme types to:
    * frontend
    * backend
    * common
* Added activation tests for independent frontend and backend theme selection.

The supplied corporate theme was incomplete, so I added the required backend entry view and placeholder asset files while preserving its supplied layout.
This commit is contained in:
Mark Gregory
2026-07-28 12:54:10 +01:00
parent f834328044
commit a433897538
12 changed files with 431 additions and 309 deletions
+12 -4
View File
@@ -1,19 +1,23 @@
{
"manifest_version": 2,
"name": "Dashboard",
"slug": "admin",
"extends": "common",
"version": "1.0.0",
"author": "ABSDEV",
"description": "Backend-only Laravel Livewire and Flux dashboard theme.",
"type": "backend",
"extends": "common",
"entry_view": "dashboard",
"stylesheet": "css/theme.css",
"script": "js/app.js",
"type": "backend",
"preview": "images/preview.webp",
"views": true,
"livewire_views": true,
"supports": {
"dark_mode": true,
"animations": false,
"privacy": false,
"terms": false,
"auth": false,
"preview": true,
"variants": true,
@@ -23,7 +27,6 @@
"accessibility_validation": true
},
"variables": {},
"preview": "images/preview.webp",
"variants": {
"light": {
"label": "Light",
@@ -38,6 +41,10 @@
}
}
},
"appearances": {},
"accents": {},
"default_appearance": null,
"default_accent": null,
"settings": {
"site_title": {
"type": "text",
@@ -54,5 +61,6 @@
"label": "Primary colour",
"default": "#2563eb"
}
}
},
"seo": {}
}
+23 -5
View File
@@ -1,19 +1,37 @@
{
"manifest_version": 2,
"name": "Common Application Theme",
"slug": "common",
"version": "1.0.0",
"author": "ABSDEV",
"description": "Application-wide layouts, authentication, settings and shared Blade components.",
"entry_view": "livewire.auth.login",
"type": "common",
"extends": null,
"entry_view": "livewire.auth.login",
"stylesheet": "css/theme.css",
"script": "js/app.js",
"preview": null,
"views": true,
"livewire_views": true,
"supports": {
"auth": true,
"settings": true,
"dark_mode": true,
"preview": false
"animations": false,
"privacy": false,
"terms": false,
"auth": true,
"preview": false,
"variants": false,
"settings": true,
"seo": false,
"export": true,
"accessibility_validation": true
},
"variables": {},
"settings": {}
"variants": {},
"appearances": {},
"accents": {},
"default_appearance": null,
"default_accent": null,
"settings": {},
"seo": {}
}
+35 -5
View File
@@ -1,7 +1,37 @@
{
"name": "Corporate",
"slug": "corporate",
"version": "1.0.0",
"parent": "common",
"type": "backend"
"manifest_version": 2,
"name": "Corporate",
"slug": "corporate",
"version": "1.0.0",
"author": "ABSDEV",
"description": "Corporate backend theme extending the common application theme.",
"type": "backend",
"extends": "common",
"entry_view": "dashboard",
"stylesheet": "css/theme.css",
"script": "js/app.js",
"preview": null,
"views": true,
"livewire_views": true,
"supports": {
"dark_mode": false,
"animations": false,
"privacy": false,
"terms": false,
"auth": false,
"preview": false,
"variants": false,
"settings": false,
"seo": false,
"export": true,
"accessibility_validation": true
},
"variables": {},
"variants": {},
"appearances": {},
"accents": {},
"default_appearance": null,
"default_accent": null,
"settings": {},
"seo": {}
}
+188 -182
View File
@@ -1,186 +1,192 @@
{
"name": "Saasland",
"slug": "saasland",
"version": "1.3.0",
"author": "ABSDEV",
"description": "Premium dark SaaS frontend with compact section spacing, responsive dashboard hero, CMS-driven content and an expanded lead-generation footer.",
"entry_view": "home",
"stylesheet": "css/theme.css",
"script": "js/app.js",
"preview": "images/preview.webp",
"type": "frontend",
"views": true,
"livewire_views": true,
"supports": {
"dark_mode": true,
"animations": true,
"privacy": true,
"terms": true,
"auth": true,
"preview": true,
"variants": true,
"settings": true,
"seo": true,
"export": true,
"accessibility_validation": true
"manifest_version": 2,
"name": "Saasland",
"slug": "saasland",
"version": "1.3.0",
"author": "ABSDEV",
"description": "Premium dark SaaS frontend with compact section spacing, responsive dashboard hero, CMS-driven content and an expanded lead-generation footer.",
"type": "frontend",
"extends": null,
"entry_view": "home",
"stylesheet": "css/theme.css",
"script": "js/app.js",
"preview": "images/preview.webp",
"views": true,
"livewire_views": true,
"supports": {
"dark_mode": true,
"animations": true,
"privacy": true,
"terms": true,
"auth": true,
"preview": true,
"variants": true,
"settings": true,
"seo": true,
"export": true,
"accessibility_validation": true
},
"variables": {
"brand-primary": "#f97316",
"brand-secondary": "#111111",
"brand-accent": "#fb923c",
"surface": "#0f0e0d",
"surface-muted": "#191714",
"text-primary": "#f7f3ef"
},
"variants": {
"light": {
"label": "Light",
"variables": {}
},
"variables": {
"brand-primary": "#f97316",
"brand-secondary": "#111111",
"brand-accent": "#fb923c",
"surface": "#0f0e0d",
"surface-muted": "#191714",
"text-primary": "#f7f3ef"
},
"variants": {
"light": {
"label": "Light",
"variables": {}
},
"dark": {
"label": "Dark",
"variables": {
"surface": "#0f172a",
"surface-muted": "#111827",
"text-primary": "#f8fafc"
}
}
},
"settings": {
"site_title": {
"type": "text",
"label": "Site title",
"default": "Abbey Software Development"
},
"site_description": {
"type": "text",
"label": "Site description",
"default": "Dark SaaS marketing theme with integrated feature, pricing, privacy and terms sections."
},
"logo_url": {
"type": "url",
"label": "Logo URL",
"default": ""
},
"--brand-primary": {
"type": "color",
"label": "Primary colour",
"default": "#f97316"
},
"hero_title": {
"type": "text",
"label": "Hero title",
"default": ""
},
"facebook_url": {
"type": "url",
"label": "Facebook URL",
"default": ""
},
"x_url": {
"type": "url",
"label": "X URL",
"default": ""
},
"linkedin_url": {
"type": "url",
"label": "LinkedIn URL",
"default": ""
},
"hero_eyebrow": {
"type": "text",
"label": "Hero eyebrow",
"default": "A better way to run your business"
},
"hero_description": {
"type": "textarea",
"label": "Hero description",
"default": "Streamline operations, boost productivity, and improve customer satisfaction with one connected platform built for modern teams."
},
"primary_cta_label": {
"type": "text",
"label": "Primary button label",
"default": "Get started free"
},
"primary_cta_url": {
"type": "text",
"label": "Primary button URL",
"default": "/register"
},
"secondary_cta_label": {
"type": "text",
"label": "Secondary button label",
"default": "Book demo"
},
"secondary_cta_url": {
"type": "text",
"label": "Secondary button URL",
"default": "#contact"
},
"show_metrics": {
"type": "checkbox",
"label": "Show performance preview",
"default": true
},
"show_features": {
"type": "checkbox",
"label": "Show features",
"default": true
},
"show_pricing": {
"type": "checkbox",
"label": "Show pricing",
"default": true
},
"show_testimonials": {
"type": "checkbox",
"label": "Show testimonials",
"default": true
},
"show_team": {
"type": "checkbox",
"label": "Show team",
"default": false
},
"show_blog": {
"type": "checkbox",
"label": "Show blog",
"default": true
},
"show_news": {
"type": "checkbox",
"label": "Show news",
"default": true
},
"show_faq": {
"type": "checkbox",
"label": "Show FAQ",
"default": true
},
"show_newsletter": {
"type": "checkbox",
"label": "Show newsletter signup",
"default": true
},
"cta_title": {
"type": "text",
"label": "Final CTA title",
"default": "Ready to transform your business?"
},
"cta_description": {
"type": "text",
"label": "Final CTA description",
"default": "Start building a faster, more connected operation today."
}
},
"seo": {
"title": "Saasland",
"description": "Dark SaaS marketing theme with integrated feature, pricing, privacy and terms sections.",
"image": "images/preview.webp",
"json_ld": {
"@context": "https://schema.org",
"@type": "WebSite",
"name": "Saasland"
}
"dark": {
"label": "Dark",
"variables": {
"surface": "#0f172a",
"surface-muted": "#111827",
"text-primary": "#f8fafc"
}
}
},
"appearances": {},
"accents": {},
"default_appearance": null,
"default_accent": null,
"settings": {
"site_title": {
"type": "text",
"label": "Site title",
"default": "Abbey Software Development"
},
"site_description": {
"type": "text",
"label": "Site description",
"default": "Dark SaaS marketing theme with integrated feature, pricing, privacy and terms sections."
},
"logo_url": {
"type": "url",
"label": "Logo URL",
"default": ""
},
"--brand-primary": {
"type": "color",
"label": "Primary colour",
"default": "#f97316"
},
"hero_title": {
"type": "text",
"label": "Hero title",
"default": ""
},
"facebook_url": {
"type": "url",
"label": "Facebook URL",
"default": ""
},
"x_url": {
"type": "url",
"label": "X URL",
"default": ""
},
"linkedin_url": {
"type": "url",
"label": "LinkedIn URL",
"default": ""
},
"hero_eyebrow": {
"type": "text",
"label": "Hero eyebrow",
"default": "A better way to run your business"
},
"hero_description": {
"type": "textarea",
"label": "Hero description",
"default": "Streamline operations, boost productivity, and improve customer satisfaction with one connected platform built for modern teams."
},
"primary_cta_label": {
"type": "text",
"label": "Primary button label",
"default": "Get started free"
},
"primary_cta_url": {
"type": "text",
"label": "Primary button URL",
"default": "/register"
},
"secondary_cta_label": {
"type": "text",
"label": "Secondary button label",
"default": "Book demo"
},
"secondary_cta_url": {
"type": "text",
"label": "Secondary button URL",
"default": "#contact"
},
"show_metrics": {
"type": "checkbox",
"label": "Show performance preview",
"default": true
},
"show_features": {
"type": "checkbox",
"label": "Show features",
"default": true
},
"show_pricing": {
"type": "checkbox",
"label": "Show pricing",
"default": true
},
"show_testimonials": {
"type": "checkbox",
"label": "Show testimonials",
"default": true
},
"show_team": {
"type": "checkbox",
"label": "Show team",
"default": false
},
"show_blog": {
"type": "checkbox",
"label": "Show blog",
"default": true
},
"show_news": {
"type": "checkbox",
"label": "Show news",
"default": true
},
"show_faq": {
"type": "checkbox",
"label": "Show FAQ",
"default": true
},
"show_newsletter": {
"type": "checkbox",
"label": "Show newsletter signup",
"default": true
},
"cta_title": {
"type": "text",
"label": "Final CTA title",
"default": "Ready to transform your business?"
},
"cta_description": {
"type": "text",
"label": "Final CTA description",
"default": "Start building a faster, more connected operation today."
}
},
"seo": {
"title": "Saasland",
"description": "Dark SaaS marketing theme with integrated feature, pricing, privacy and terms sections.",
"image": "images/preview.webp",
"json_ld": {
"@context": "https://schema.org",
"@type": "WebSite",
"name": "Saasland"
}
}
}
+103 -97
View File
@@ -1,101 +1,107 @@
{
"name": "Swiss",
"slug": "swiss",
"version": "1.1.0",
"author": "ABSDEV",
"description": "Dark Marketing Theme with integrated feature, pricing, privacy and terms sections.",
"entry_view": "home",
"stylesheet": "css/theme.css",
"script": "js/app.js",
"preview": "images/preview.webp",
"type": "frontend",
"views": true,
"livewire_views": true,
"supports": {
"dark_mode": true,
"animations": true,
"privacy": true,
"terms": true,
"auth": false,
"preview": true,
"variants": true,
"settings": true,
"seo": true,
"export": true,
"accessibility_validation": true
"manifest_version": 2,
"name": "Swiss",
"slug": "swiss",
"version": "1.1.0",
"author": "ABSDEV",
"description": "Dark Marketing Theme with integrated feature, pricing, privacy and terms sections.",
"type": "frontend",
"extends": null,
"entry_view": "home",
"stylesheet": "css/theme.css",
"script": "js/app.js",
"preview": "images/preview.webp",
"views": true,
"livewire_views": true,
"supports": {
"dark_mode": true,
"animations": true,
"privacy": true,
"terms": true,
"auth": false,
"preview": true,
"variants": true,
"settings": true,
"seo": true,
"export": true,
"accessibility_validation": true
},
"variables": {
"brand-primary": "#f97316",
"brand-secondary": "#111111",
"brand-accent": "#fb923c",
"surface": "#0f0e0d",
"surface-muted": "#191714",
"text-primary": "#f7f3ef"
},
"variants": {
"light": {
"label": "Light",
"variables": {}
},
"variables": {
"brand-primary": "#f97316",
"brand-secondary": "#111111",
"brand-accent": "#fb923c",
"surface": "#0f0e0d",
"surface-muted": "#191714",
"text-primary": "#f7f3ef"
},
"variants": {
"light": {
"label": "Light",
"variables": {}
},
"dark": {
"label": "Dark",
"variables": {
"surface": "#0f172a",
"surface-muted": "#111827",
"text-primary": "#f8fafc"
}
}
},
"settings": {
"site_title": {
"type": "text",
"label": "Site title",
"default": "Saasland"
},
"site_description": {
"type": "text",
"label": "Site description",
"default": "Dark SaaS marketing theme with integrated feature, pricing, privacy and terms sections."
},
"logo_url": {
"type": "url",
"label": "Logo URL",
"default": ""
},
"--brand-primary": {
"type": "color",
"label": "Primary colour",
"default": "#f97316"
},
"hero_title": {
"type": "text",
"label": "Hero title",
"default": ""
},
"facebook_url": {
"type": "url",
"label": "Facebook URL",
"default": ""
},
"x_url": {
"type": "url",
"label": "X URL",
"default": ""
},
"linkedin_url": {
"type": "url",
"label": "LinkedIn URL",
"default": ""
}
},
"seo": {
"title": "Saasland",
"description": "Dark SaaS marketing theme with integrated feature, pricing, privacy and terms sections.",
"image": "images/preview.webp",
"json_ld": {
"@context": "https://schema.org",
"@type": "WebSite",
"name": "Saasland"
}
"dark": {
"label": "Dark",
"variables": {
"surface": "#0f172a",
"surface-muted": "#111827",
"text-primary": "#f8fafc"
}
}
},
"appearances": {},
"accents": {},
"default_appearance": null,
"default_accent": null,
"settings": {
"site_title": {
"type": "text",
"label": "Site title",
"default": "Saasland"
},
"site_description": {
"type": "text",
"label": "Site description",
"default": "Dark SaaS marketing theme with integrated feature, pricing, privacy and terms sections."
},
"logo_url": {
"type": "url",
"label": "Logo URL",
"default": ""
},
"--brand-primary": {
"type": "color",
"label": "Primary colour",
"default": "#f97316"
},
"hero_title": {
"type": "text",
"label": "Hero title",
"default": ""
},
"facebook_url": {
"type": "url",
"label": "Facebook URL",
"default": ""
},
"x_url": {
"type": "url",
"label": "X URL",
"default": ""
},
"linkedin_url": {
"type": "url",
"label": "LinkedIn URL",
"default": ""
}
},
"seo": {
"title": "Saasland",
"description": "Dark SaaS marketing theme with integrated feature, pricing, privacy and terms sections.",
"image": "images/preview.webp",
"json_ld": {
"@context": "https://schema.org",
"@type": "WebSite",
"name": "Saasland"
}
}
}
+10 -3
View File
@@ -1,19 +1,23 @@
{
"manifest_version": 2,
"name": "Welcome",
"slug": "welcome",
"extends": "common",
"version": "1.1.2",
"author": "ABSDEV",
"description": "Laravel 13 welcome theme.",
"type": "frontend",
"extends": "common",
"entry_view": "welcome",
"stylesheet": "css/theme.css",
"script": "js/app.js",
"type": "frontend",
"preview": "images/preview.webp",
"views": true,
"livewire_views": true,
"supports": {
"dark_mode": false,
"animations": false,
"privacy": false,
"terms": false,
"auth": false,
"preview": true,
"variants": true,
@@ -30,7 +34,6 @@
"surface-muted": "#f8fafc",
"text-primary": "#0f172a"
},
"preview": "images/preview.webp",
"variants": {
"light": {
"label": "Light",
@@ -45,6 +48,10 @@
}
}
},
"appearances": {},
"accents": {},
"default_appearance": null,
"default_accent": null,
"settings": {
"site_title": {
"type": "text",