diff --git a/src/context/ThemeContext.jsx b/src/context/ThemeContext.jsx
index ec6d2fc..d1e4511 100644
--- a/src/context/ThemeContext.jsx
+++ b/src/context/ThemeContext.jsx
@@ -21,6 +21,14 @@ const themeRegistry = {
Home: React.lazy(() => import('../themes/minimal/Home')),
Layout: React.lazy(() => import('../themes/minimal/Layout')),
},
+ clean: {
+ Home: React.lazy(() => import('../themes/clean/Home')),
+ Layout: React.lazy(() => import('../themes/clean/Layout')),
+ },
+ corporate: {
+ Home: React.lazy(() => import('../themes/corporate/Home')),
+ Layout: React.lazy(() => import('../themes/corporate/Layout')),
+ },
};
// Full-screen loading spinner shown while site info is being fetched
diff --git a/src/themes/clean/Home.jsx b/src/themes/clean/Home.jsx
new file mode 100644
index 0000000..52c6933
--- /dev/null
+++ b/src/themes/clean/Home.jsx
@@ -0,0 +1,231 @@
+import React, { useState, useEffect } from 'react';
+import { Link } from 'react-router-dom';
+import { useTranslation } from 'react-i18next';
+import { useAuth } from '../../context/AuthContext';
+import { useSite } from '../../context/SiteContext';
+import { getSiteModels, getSitePackages } from '../../api';
+import CountUp from '../../components/bits/CountUp';
+import FadeContent from '../../components/bits/FadeContent';
+
+export default function CleanHome() {
+ const { t } = useTranslation();
+ const { user } = useAuth();
+ const { site } = useSite();
+ const [models, setModels] = useState([]);
+ const [packages, setPackages] = useState([]);
+
+ useEffect(() => {
+ getSiteModels().then(r => { if (r.data.success) setModels(r.data.data || []); }).catch(() => {});
+ getSitePackages().then(r => { if (r.data.success) setPackages(r.data.data || []); }).catch(() => {});
+ }, []);
+
+ const enabledModels = models.filter(m => m.enabled !== false);
+
+ return (
+
+ {/* Hero */}
+
+
+
+
+
+ {t('home.lightningFast')}
+
+
+
+ {site?.name || t('home.defaultHeroTitle')}
+
+
+
+ {t('home.heroSubtitle')}
+
+
+
+ {user ? (
+
+ {t('home.goToDashboard')} →
+
+ ) : (
+ <>
+
+ {t('home.getStarted')} →
+
+
+ {t('home.viewPricing')}
+
+ >
+ )}
+
+
+
+
+ {/* Stats */}
+
+
+
+
+ +
+
+
{t('home.aiModels')}
+
+
+
+ %
+
+
{t('home.uptime')}
+
+
+
+ <ms
+
+
{t('home.latency')}
+
+
+
+
+
+ {/* Features */}
+
+
+
+
+
{t('home.whyChooseUs')}
+
{t('home.whyChooseUsDesc')}
+
+
+
+
+
+
{t('home.lightningFast')}
+
{t('home.lightningFastDesc')}
+
+
+
+
+
{t('home.securePrivate')}
+
{t('home.securePrivateDesc')}
+
+
+
+
+
{t('home.payAsYouGo')}
+
{t('home.payAsYouGoDesc')}
+
+
+
+
+
+
+ {/* Models */}
+ {enabledModels.length > 0 && (
+
+
+
+
{t('home.availableModels')}
+
{t('home.availableModelsDesc', { count: enabledModels.length })}
+
+
+
+ {enabledModels.slice(0, 12).map((m, i) => (
+
+
+
+ {m.display_name || m.model_name}
+
+
+ ))}
+
+
+ {enabledModels.length > 12 && (
+
+
+ {t('home.viewAllModels', { count: enabledModels.length })} →
+
+
+ )}
+
+
+ )}
+
+ {/* Packages */}
+ {packages.length > 0 && (
+
+
+
+
+
{t('home.plansPackages')}
+
{t('home.choosePlan')}
+
+
+
+ {packages.filter(p => p.enabled).slice(0, 3).map((pkg, i) => (
+
+ {i === 1 &&
Popular}
+
{pkg.name}
+ {pkg.description &&
{pkg.description}
}
+
+
+ ${pkg.price}
+ {pkg.original_price > pkg.price && (
+ ${pkg.original_price}
+ )}
+
+ {pkg.duration > 0 &&
{t('home.days', { count: pkg.duration })}
}
+
+
+ {user ? t('home.subscribe') : t('home.getStarted')}
+
+
+ ))}
+
+
+
+
+ )}
+
+ {/* CTA */}
+
+
+
+
{t('home.readyToStart')}
+
{t('home.readyToStartDesc')}
+
+ {user ? (
+
+ {t('home.goToDashboard')}
+
+ ) : (
+ <>
+
+ {t('home.createFreeAccount')}
+
+
+ {t('home.signIn')}
+
+ >
+ )}
+
+
+
+
+
+ );
+}
diff --git a/src/themes/clean/Layout.jsx b/src/themes/clean/Layout.jsx
new file mode 100644
index 0000000..a5496eb
--- /dev/null
+++ b/src/themes/clean/Layout.jsx
@@ -0,0 +1,148 @@
+import React, { useState } from 'react';
+import { Outlet, Link, useNavigate, useLocation } from 'react-router-dom';
+import { useTranslation } from 'react-i18next';
+import { useAuth } from '../../context/AuthContext';
+import { useSite } from '../../context/SiteContext';
+import LanguageSwitch from '../../components/LanguageSwitch';
+
+export default function CleanLayout() {
+ const { t } = useTranslation();
+ const { user, logout } = useAuth();
+ const { site } = useSite();
+ const navigate = useNavigate();
+ const location = useLocation();
+ const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
+
+ const siteName = site?.name || 'AI Platform';
+
+ const navItems = [
+ { to: '/', label: t('nav.home'), auth: false },
+ { to: '/pricing', label: t('nav.pricing'), auth: false },
+ { to: '/packages', label: t('nav.packages'), auth: false },
+ { to: '/dashboard', label: t('nav.dashboard'), auth: true },
+ { to: '/tokens', label: t('nav.apiKeys'), auth: true },
+ ...(site?.enable_topup ? [{ to: '/topup', label: t('nav.topup'), auth: true }] : []),
+ ];
+
+ const visibleNavItems = navItems.filter((n) => !n.auth || user);
+
+ return (
+
+ {/* Announcement */}
+ {site?.announcement && (
+
+ )}
+
+ {/* Header */}
+
+
+
+
+
+
+ );
+}
diff --git a/src/themes/corporate/Home.jsx b/src/themes/corporate/Home.jsx
new file mode 100644
index 0000000..75afe86
--- /dev/null
+++ b/src/themes/corporate/Home.jsx
@@ -0,0 +1,251 @@
+import React, { useState, useEffect } from 'react';
+import { Link } from 'react-router-dom';
+import { useTranslation } from 'react-i18next';
+import { useAuth } from '../../context/AuthContext';
+import { useSite } from '../../context/SiteContext';
+import { getSiteModels, getSitePackages } from '../../api';
+import CountUp from '../../components/bits/CountUp';
+import FadeContent from '../../components/bits/FadeContent';
+
+export default function CorporateHome() {
+ const { t } = useTranslation();
+ const { user } = useAuth();
+ const { site } = useSite();
+ const [models, setModels] = useState([]);
+ const [packages, setPackages] = useState([]);
+
+ useEffect(() => {
+ getSiteModels().then(r => { if (r.data.success) setModels(r.data.data || []); }).catch(() => {});
+ getSitePackages().then(r => { if (r.data.success) setPackages(r.data.data || []); }).catch(() => {});
+ }, []);
+
+ const enabledModels = models.filter(m => m.enabled !== false);
+
+ return (
+
+ {/* Hero */}
+
+
+
+
+
+
+
+
+ {t('home.lightningFast')}
+
+
+
+ {site?.name || t('home.defaultHeroTitle')}
+
+
+
+ {t('home.heroSubtitle')}
+
+
+
+ {user ? (
+
+ {t('home.goToDashboard')}
+
+
+ ) : (
+ <>
+
+ {t('home.getStarted')}
+
+
+
+ {t('home.viewPricing')}
+
+ >
+ )}
+
+
+
+
+ {/* Stats bar */}
+
+
+
+
+ +
+
+
{t('home.aiModels')}
+
+
+
+ %
+
+
{t('home.uptime')}
+
+
+
+ <ms
+
+
{t('home.latency')}
+
+
+
+
+
+
+ {/* Features */}
+
+
+
+
+
{t('home.whyChooseUs')}
+
{t('home.whyChooseUsDesc')}
+
+
+
+
+
+
{t('home.lightningFast')}
+
{t('home.lightningFastDesc')}
+
+
+
+
+
{t('home.securePrivate')}
+
{t('home.securePrivateDesc')}
+
+
+
+
+
{t('home.payAsYouGo')}
+
{t('home.payAsYouGoDesc')}
+
+
+
+
+
+
+ {/* Models */}
+ {enabledModels.length > 0 && (
+
+
+
+
{t('home.availableModels')}
+
{t('home.availableModelsDesc', { count: enabledModels.length })}
+
+
+
+ {enabledModels.slice(0, 12).map((m, i) => (
+
+
+
+ {m.display_name || m.model_name}
+
+
+ ))}
+
+
+ {enabledModels.length > 12 && (
+
+
+ {t('home.viewAllModels', { count: enabledModels.length })}
+
+
+
+ )}
+
+
+ )}
+
+ {/* Packages */}
+ {packages.length > 0 && (
+
+
+
+
+
{t('home.plansPackages')}
+
{t('home.choosePlan')}
+
+
+
+ {packages.filter(p => p.enabled).slice(0, 3).map((pkg, i) => (
+
+ {i === 1 && (
+
+ Popular
+
+ )}
+
+
{pkg.name}
+ {pkg.description &&
{pkg.description}
}
+
+
+ ${pkg.price}
+ {pkg.original_price > pkg.price && (
+ ${pkg.original_price}
+ )}
+
+ {pkg.duration > 0 &&
{t('home.days', { count: pkg.duration })}
}
+
+
+
+
+ {user ? t('home.subscribe') : t('home.getStarted')}
+
+
+
+ ))}
+
+
+
+
+ )}
+
+ {/* CTA */}
+
+
+
+
+
+
{t('home.readyToStart')}
+
{t('home.readyToStartDesc')}
+
+ {user ? (
+
+ {t('home.goToDashboard')}
+
+
+ ) : (
+ <>
+
+ {t('home.createFreeAccount')}
+
+
+
+ {t('home.signIn')}
+
+ >
+ )}
+
+
+
+
+
+
+ );
+}
diff --git a/src/themes/corporate/Layout.jsx b/src/themes/corporate/Layout.jsx
new file mode 100644
index 0000000..524f498
--- /dev/null
+++ b/src/themes/corporate/Layout.jsx
@@ -0,0 +1,155 @@
+import React, { useState } from 'react';
+import { Outlet, Link, useNavigate, useLocation } from 'react-router-dom';
+import { useTranslation } from 'react-i18next';
+import { useAuth } from '../../context/AuthContext';
+import { useSite } from '../../context/SiteContext';
+import LanguageSwitch from '../../components/LanguageSwitch';
+
+export default function CorporateLayout() {
+ const { t } = useTranslation();
+ const { user, logout } = useAuth();
+ const { site } = useSite();
+ const navigate = useNavigate();
+ const location = useLocation();
+ const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
+
+ const siteName = site?.name || 'AI Platform';
+
+ const navItems = [
+ { to: '/', label: t('nav.home'), auth: false },
+ { to: '/pricing', label: t('nav.pricing'), auth: false },
+ { to: '/packages', label: t('nav.packages'), auth: false },
+ { to: '/dashboard', label: t('nav.dashboard'), auth: true },
+ { to: '/tokens', label: t('nav.apiKeys'), auth: true },
+ ...(site?.enable_topup ? [{ to: '/topup', label: t('nav.topup'), auth: true }] : []),
+ ];
+
+ const visibleNavItems = navItems.filter((n) => !n.auth || user);
+
+ return (
+
+ {/* Announcement */}
+ {site?.announcement && (
+
+ )}
+
+ {/* Header */}
+
+
+
+ {site?.logo ? (
+

+ ) : (
+
+ {siteName.charAt(0)}
+
+ )}
+
+ {siteName}
+
+
+
+
+
+
+
+
+ {user ? (
+
+
+ {user.display_name || user.username}
+
+
+
+ ) : (
+ <>
+
+ {t('nav.login')}
+
+
+ {t('nav.signUp')}
+
+ >
+ )}
+
+
+
+
+
+ {mobileMenuOpen && (
+
+
+
+ )}
+
+
+
+
+
+
+ );
+}