feat(admin): add demo mode toggle in admin dashboard and rewrite 404 page for missing routes
Some checks failed
Production Build & Deploy / build-and-deploy (push) Has been cancelled

This commit is contained in:
Daniel S
2026-08-09 22:43:36 +02:00
parent 5e9b69c319
commit baa639a9b2
3 changed files with 21 additions and 3 deletions

View File

@@ -73,8 +73,15 @@ const { title, description = "Professionelles Webdesign & moderne Websites." } =
</script> </script>
</head> </head>
<body class="font-sans transition-colors duration-500 antialiased"> <body class="font-sans transition-colors duration-500 antialiased">
{(siteConfig as any).is_demo_mode && (
<div class="bg-gradient-to-r from-amber-600 via-amber-500 to-amber-600 text-slate-950 text-center py-2 px-4 text-xs font-bold font-mono tracking-wide shadow-md flex items-center justify-center gap-2">
<span>🎭 DEMO-MODUS AKTIV</span>
<span class="opacity-75 font-sans font-normal">— Dies ist eine interaktive Vorschau-Instanz der N&D WaaS Engine.</span>
</div>
)}
<slot /> <slot />
</body> </body>
</html> </html>
<style is:global> <style is:global>

View File

@@ -71,11 +71,13 @@ let page = pages.find((p: any) => {
return p.slug === currentSlug || p.slug === `/${currentSlug}`; return p.slug === currentSlug || p.slug === `/${currentSlug}`;
}); });
// 5. Zero-Crash Fallback Guard: Wenn Seite fehlt oder unveröffentlicht ist // 5. Zero-Crash Fallback Guard: Wenn Seite nicht existiert oder nicht veröffentlicht ist -> 404 Status
if (!page || (page.is_published === false && import.meta.env.PROD)) { if (!page || (page.is_published === false && !isDraft)) {
return Astro.redirect('/404'); Astro.response.status = 404;
return Astro.rewrite('/404');
} }
// 6. Dynamic Component Registry Mapping // 6. Dynamic Component Registry Mapping
const ComponentRegistry: Record<string, any> = { const ComponentRegistry: Record<string, any> = {
hero: HeroSection, hero: HeroSection,

View File

@@ -71,6 +71,13 @@ const presets = Object.values(THEME_PRESETS);
<label class="block text-xs font-bold text-slate-400 mb-1">Meta Beschreibung (SEO)</label> <label class="block text-xs font-bold text-slate-400 mb-1">Meta Beschreibung (SEO)</label>
<textarea id="metaDescription" rows="2" class="w-full glass-panel bg-slate-950/60 rounded-xl p-3 text-xs text-white focus:outline-none focus:border-sky-400 resize-none">{siteConfig.metaDescription}</textarea> <textarea id="metaDescription" rows="2" class="w-full glass-panel bg-slate-950/60 rounded-xl p-3 text-xs text-white focus:outline-none focus:border-sky-400 resize-none">{siteConfig.metaDescription}</textarea>
</div> </div>
<label class="flex items-center gap-3 pt-2 p-3 bg-amber-500/10 border border-amber-500/20 rounded-xl cursor-pointer">
<input type="checkbox" id="isDemoMode" checked={(siteConfig as any).is_demo_mode ?? false} class="rounded text-amber-400 focus:ring-0 h-4 w-4" />
<div>
<span class="text-xs text-amber-400 font-bold block">🎭 Demo-Modus aktivieren</span>
<span class="text-[10px] text-slate-400">Zeigt einen festen Demo-Hinweis für Interessenten auf der Live-Website</span>
</div>
</label>
</div> </div>
<h3 class="text-xs font-bold text-slate-400 uppercase tracking-wider pt-2 border-t border-white/10">Unternehmens-Stammdaten (Dynamic Data Binding)</h3> <h3 class="text-xs font-bold text-slate-400 uppercase tracking-wider pt-2 border-t border-white/10">Unternehmens-Stammdaten (Dynamic Data Binding)</h3>
@@ -179,6 +186,7 @@ const presets = Object.values(THEME_PRESETS);
siteConfig: { siteConfig: {
siteName: getVal('siteName'), siteName: getVal('siteName'),
metaDescription: getVal('metaDescription'), metaDescription: getVal('metaDescription'),
is_demo_mode: getBool('isDemoMode'),
site_info: { site_info: {
title: getVal('infoTitle'), title: getVal('infoTitle'),
email: getVal('infoEmail'), email: getVal('infoEmail'),
@@ -186,6 +194,7 @@ const presets = Object.values(THEME_PRESETS);
address: getVal('infoAddress') address: getVal('infoAddress')
} }
}, },
themeConfig: { themeConfig: {
activePreset: selectedPreset activePreset: selectedPreset
}, },