fix: force dark mode on auth/home, add grid texture and glow to homepage
Docker Build / Build and Push Docker Image (push) Successful in 4m3s

This commit is contained in:
2026-06-14 17:27:06 +08:00
parent 5eeb3c9f18
commit 1ddffd236c
3 changed files with 99 additions and 30 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ export function AuthLayout({ children }: AuthLayoutProps) {
const { systemName, logo, loading } = useSystemConfig()
return (
<div className='relative grid h-svh max-w-none bg-[#0A0E14]'>
<div className='dark relative grid h-svh max-w-none bg-[#0A0E14]'>
<Link
to='/'
className='absolute top-4 left-4 z-10 flex items-center gap-2 transition-opacity hover:opacity-80 sm:top-8 sm:left-8'
+93 -26
View File
@@ -17,7 +17,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
For commercial licensing, please contact admin@modelstoken.com
*/
import { Link } from '@tanstack/react-router'
import { ArrowRight } from 'lucide-react'
import { ArrowRight, Zap, Shield, Layers, BarChart3, Key, GitBranch } from 'lucide-react'
import { useTranslation } from 'react-i18next'
import { useStatus } from '@/hooks/use-status'
import { Button } from '@/components/ui/button'
@@ -32,6 +32,7 @@ const T = {
surface: '#0F1419',
border: '#1A1F29',
accent: '#00D2FF',
accentDim: '#0099BB',
green: '#28C840',
yellow: '#FEBC2E',
gray: '#5C6370',
@@ -40,6 +41,15 @@ const T = {
red: '#FF5F57',
}
const features = [
{ icon: Zap, title: 'Multi-model Routing', desc: 'Intelligent routing with automatic failover and load balancing' },
{ icon: Key, title: 'Key Management', desc: 'Centralized API key lifecycle management with usage tracking' },
{ icon: Shield, title: 'Access Control', desc: 'Fine-grained permissions, rate limiting, and token policies' },
{ icon: BarChart3, title: 'Real-time Monitoring', desc: 'Live dashboards with request latency and cost analytics' },
{ icon: Layers, title: 'OpenAI Compatible', desc: 'Drop-in replacement for OpenAI API with zero code changes' },
{ icon: GitBranch, title: 'Model Mapping', desc: 'Map model names and customize per-channel behavior' },
]
export function Hero(props: HeroProps) {
const { t } = useTranslation()
const { status } = useStatus()
@@ -49,22 +59,33 @@ export function Hero(props: HeroProps) {
return (
<section className='relative overflow-hidden' style={{ backgroundColor: T.bg }}>
{/* Subtle top glow */}
{/* Grid background texture */}
<div
aria-hidden
className='pointer-events-none absolute inset-0 opacity-[0.03]'
style={{
backgroundImage:
'linear-gradient(rgba(0,210,255,0.5) 1px, transparent 1px), linear-gradient(90deg, rgba(0,210,255,0.5) 1px, transparent 1px)',
backgroundSize: '64px 64px',
}}
/>
{/* Top glow */}
<div
aria-hidden
className='pointer-events-none absolute inset-0'
style={{
background:
'radial-gradient(ellipse 40% 25% at 50% 0%, rgba(0,210,255,0.06) 0%, transparent 70%)',
'radial-gradient(ellipse 50% 40% at 50% 0%, rgba(0,210,255,0.08) 0%, transparent 70%)',
}}
/>
<div className='relative mx-auto max-w-4xl px-6'>
<div className='relative mx-auto max-w-5xl px-6'>
{/* ── Hero ── */}
<div className='flex min-h-[calc(100svh-3rem)] flex-col items-center justify-center py-20 text-center'>
{/* Headline */}
<h1
className='max-w-xl text-[clamp(2.4rem,7vw,4.5rem)] leading-[1] font-bold tracking-[-0.04em]'
className='max-w-2xl text-[clamp(2.2rem,6vw,4.2rem)] leading-[1.05] font-bold tracking-[-0.03em]'
style={{ color: T.white }}
>
{t('Unified LLM')}{' '}
@@ -72,12 +93,12 @@ export function Hero(props: HeroProps) {
</h1>
{/* Subtitle */}
<p className='mt-6 max-w-sm text-[15px] leading-relaxed' style={{ color: T.grayLight }}>
<p className='mt-5 max-w-md text-[15px] leading-relaxed' style={{ color: T.grayLight }}>
{t('One endpoint for all models. OpenAI-compatible, switch and go.')}
</p>
{/* CTA */}
<div className='mt-10 flex items-center gap-4'>
<div className='mt-9 flex items-center gap-4'>
{props.isAuthenticated ? (
<Button
className='group h-11 rounded-lg px-7 text-sm font-semibold hover:opacity-90'
@@ -112,43 +133,43 @@ export function Hero(props: HeroProps) {
</div>
{/* ── Terminal demo ── */}
<div className='-mt-4 pb-28'>
<div className='-mt-6 pb-24'>
<div
className='mx-auto w-full max-w-xl overflow-hidden rounded-xl border'
style={{ borderColor: T.border, backgroundColor: T.surface }}
className='mx-auto w-full max-w-2xl overflow-hidden rounded-xl border'
style={{ borderColor: T.border, backgroundColor: T.surface, boxShadow: '0 0 80px -20px rgba(0,210,255,0.1)' }}
>
{/* Terminal header */}
<div className='flex items-center gap-2 border-b px-4 py-2' style={{ borderColor: T.border }}>
<div className='flex items-center gap-2 border-b px-4 py-2.5' style={{ borderColor: T.border }}>
<div className='flex gap-1.5'>
<div className='size-2 rounded-full' style={{ backgroundColor: T.red }} />
<div className='size-2 rounded-full' style={{ backgroundColor: T.yellow }} />
<div className='size-2 rounded-full' style={{ backgroundColor: T.green }} />
<div className='size-2.5 rounded-full' style={{ backgroundColor: T.red }} />
<div className='size-2.5 rounded-full' style={{ backgroundColor: T.yellow }} />
<div className='size-2.5 rounded-full' style={{ backgroundColor: T.green }} />
</div>
<span className='ml-2 text-[10px]' style={{ color: T.gray }}>bash</span>
<span className='ml-2 text-[11px]' style={{ color: T.gray }}>bash api</span>
</div>
{/* Terminal content */}
<div className='p-4 font-mono text-[12px] leading-[2]'>
<div className='p-5 font-mono text-[13px] leading-[1.85]'>
<div>
<span style={{ color: T.accent }}>$</span>{' '}
<span style={{ color: T.white }}>curl</span>{' '}
<span style={{ color: T.accent }}>{serverAddress}/v1/chat/completions</span>{' '}
<span style={{ color: T.gray }}>\</span>
</div>
<div className='pl-4'>
<div className='pl-5'>
<span style={{ color: T.gray }}>-H</span>{' '}
<span style={{ color: T.yellow }}>"Authorization: Bearer sk-..."</span>{' '}
<span style={{ color: T.gray }}>\</span>
</div>
<div className='pl-4'>
<div className='pl-5'>
<span style={{ color: T.gray }}>-d</span>{' '}
<span style={{ color: T.yellow }}>{"'{ \"model\": \"gpt-4o\" }'"}</span>
<span style={{ color: T.yellow }}>{"'{ \"model\": \"gpt-4o\", \"messages\": [...] }'"}</span>
</div>
<div className='mt-4 border-t pt-3' style={{ borderColor: T.border }}>
<div className='flex items-center gap-2 mb-2'>
<div className='mt-5 border-t pt-4' style={{ borderColor: T.border }}>
<div className='flex items-center gap-2 mb-3'>
<span className='inline-block size-1.5 rounded-full' style={{ backgroundColor: T.green }} />
<span className='text-[10px] font-medium' style={{ color: T.gray }}>200</span>
<span className='text-[10px]' style={{ color: T.gray }}>312ms</span>
<span className='text-[11px] font-medium' style={{ color: T.gray }}>200 OK</span>
<span className='text-[11px]' style={{ color: T.gray }}>312ms</span>
</div>
<div>
<span style={{ color: T.gray }}>{"{"}</span>
@@ -158,17 +179,63 @@ export function Hero(props: HeroProps) {
<span style={{ color: T.gray }}>,</span>
<span style={{ color: T.accent }}> "usage"</span>
<span style={{ color: T.gray }}>:</span>
<span style={{ color: T.gray }}> {"{...}"} </span>
<span style={{ color: T.gray }}> {"{ \"prompt_tokens\": 12, \"completion_tokens\": 47 }"}</span>
<span style={{ color: T.gray }}>{"}"}</span>
</div>
</div>
<div className='mt-2'>
<div className='mt-3'>
<span style={{ color: T.accent }}>$</span>
<span className='ml-1 inline-block h-3 w-[6px] animate-pulse align-middle' style={{ backgroundColor: T.accent }} />
<span className='ml-1 inline-block h-3.5 w-[7px] animate-pulse align-middle' style={{ backgroundColor: T.accent }} />
</div>
</div>
</div>
</div>
{/* ── Features ── */}
<div className='pb-28'>
<div className='mb-14 text-center'>
<h2 className='text-xl font-semibold tracking-tight' style={{ color: T.white }}>
{t('Full-featured gateway')}
</h2>
<p className='mt-2 text-sm' style={{ color: T.grayLight }}>
{t('Everything you need to manage, route, and monitor LLM API traffic')}
</p>
</div>
<div className='grid gap-4 sm:grid-cols-2 lg:grid-cols-3'>
{features.map((feature) => (
<div
key={feature.title}
className='group rounded-lg border p-5 transition-all duration-200'
style={{
borderColor: T.border,
backgroundColor: T.surface,
}}
onMouseEnter={(e) => {
e.currentTarget.style.borderColor = T.accentDim
e.currentTarget.style.boxShadow = '0 0 24px -8px rgba(0,210,255,0.15)'
}}
onMouseLeave={(e) => {
e.currentTarget.style.borderColor = T.border
e.currentTarget.style.boxShadow = 'none'
}}
>
<div
className='mb-3 flex size-9 items-center justify-center rounded-md'
style={{ backgroundColor: `${T.accent}10` }}
>
<feature.icon className='size-4' style={{ color: T.accent }} />
</div>
<h3 className='text-sm font-semibold' style={{ color: T.white }}>
{t(feature.title)}
</h3>
<p className='mt-1.5 text-[13px] leading-relaxed' style={{ color: T.gray }}>
{t(feature.desc)}
</p>
</div>
))}
</div>
</div>
</div>
</section>
)
+5 -3
View File
@@ -62,8 +62,10 @@ export function Home() {
return (
<PublicLayout showMainContainer={false}>
<Hero isAuthenticated={isAuthenticated} />
<Footer />
</PublicLayout>
<div className='dark'>
<Hero isAuthenticated={isAuthenticated} />
<Footer />
</div>
</PublicLayout>
)
}