premium-frontend-design by kv0906/cc-skills
npx skills add https://github.com/kv0906/cc-skills --skill premium-frontend-design本技能指导创建生产级前端界面,使其感觉充满活力——不通用、不复制粘贴,而是真正精心打造、让用户难忘的体验。
"优秀界面与令人难忘界面之间的区别在于对每个像素的刻意设计。"
本技能框架灵活。根据用户偏好和项目需求选择包。
pnpm add three @react-three/fiber @react-three/drei
| 库 | 最适合 | 复杂度 | 包大小 |
|---|---|---|---|
| CSS/Tailwind | 简单过渡、微交互 | 低 | 0KB |
| Framer Motion | React-native 感觉、布局动画、手势 | 中 | ~30KB |
| GSAP | 复杂时间线、滚动触发、文本效果 |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 高 |
| ~60KB |
| GSAP + Club | SplitText、ScrollTrigger、MorphSVG | 高 | ~80KB |
# Framer Motion(更简单,符合 React 习惯)
pnpm add framer-motion
# GSAP(功能强大,基于时间线)
pnpm add gsap @gsap/react
# 注意:SplitText、ScrollTrigger 需要 GSAP Club 许可证
决策指南:
# 网格渐变(用于 mesh-gradient-hero)
pnpm add @paper-design/shaders-react
# 图标
pnpm add lucide-react
# 图表/迷你图(用于仪表板)
pnpm add recharts
# 或轻量级:pnpm add @visx/shape @visx/scale
backdrop-filter:Firefox < 103 不支持(添加后备背景)@starting-style:Chrome 117+、Safari 17.4+(渐进增强)当界面具备以下特点时,会感觉充满活力:
在编写任何代码之前,回答以下问题:
目的:这解决了什么问题?谁使用它?
基调:选择一个极端方向(不要混合):
核心亮点:用户会记住哪个单一元素?每个优秀界面都有一个标志性时刻。
约束条件:框架、性能预算、无障碍性要求。
关键:大胆的极致主义和精致的简约主义都有效。关键是刻意性,而非强度。一个完美执行的动画胜过 50 个平庸的动画。
当需求模糊或需要证明设计决策时使用此框架。目标是有目的的惊艳效果。
英雄区(狂野) → 内容块(平静) → 证明区(平静) → CTA(高亮)。bg-black/70 或 bg-slate-950/70 遮罩。cubic-bezier(0.34, 1.56, 0.64, 1)。prefers-reduced-motion 开启或用户滚动过英雄区时,禁用非必要动画。| 情况 | 默认 | 可选升级 |
|---|---|---|
| 用户只说"简洁的 SaaS" | mesh-gradient-hero + bento-grid | 如果他们后来要求"更多能量",将英雄背景替换为 CPPN |
| 用户说"仪表板"但没有亮点 | bento-grid + dashboard-widgets + CSS 发光药丸 | 仅在数据可视化确认后添加 digital-liquid 着色器 |
| 用户说"英雄区"但没其他说明 | 文本优先布局 + CSS 渐变 | 提供着色器/地球作为建议,而非默认 |
如果提示未明确提及 WebGL,则假设CSS 优先,仅在用户接受成本时选择着色器。
❌ 白色/浅色背景作为默认(深色模式才是高级感) ❌ 通用渐变(白色背景上的紫到蓝渐变是 AI 垃圾) ❌ 均匀分布、胆怯的调色板 ❌ 静态、无生气的背景 ❌ 千篇一律的组件布局 ❌ 缺少加载/过渡状态 ❌ 突兀、无缓动的动画
❌ 标题使用 Inter、Roboto、Arial、系统字体 ❌ 所有内容使用相同字体 ❌ 默认行高和字母间距 ❌ 无聊、可预测的字号比例
❌ 内联样式随机分散 ❌ 没有用于主题的 CSS 变量 ❌ 动画没有 will-change 或 GPU 加速 ❌ Canvas/WebGL 没有 requestAnimationFrame ❌ useEffect 中缺少清理函数
规则:一种主导强调色,其他所有颜色都支持它。
// 高级深色主题(默认)
const colors = {
// 背景(从最深到最浅的图层)
bg: {
void: '#000000', // 纯黑色以获得最大对比度
primary: '#050505', // 主背景
elevated: '#0a0a0a', // 卡片、模态框
subtle: '#111111', // 悬停状态
},
// 玻璃表面
glass: {
bg: 'rgba(255, 255, 255, 0.03)',
border: 'rgba(255, 255, 255, 0.08)',
hover: 'rgba(255, 255, 255, 0.06)',
},
// 文本层级
text: {
primary: '#ffffff',
secondary: '#a1a1aa', // zinc-400
muted: '#71717a', // zinc-500
ghost: '#3f3f46', // zinc-700
},
// 强调色(每个项目选择一种)
accent: '#ff4d00', // 霓虹橙
// accent: '#00f3ff', // 霓虹青
// accent: '#ccff00', // 霓虹酸橙绿
// accent: '#F5E445', // 高级黄
// accent: '#a855f7', // 电光紫
}
强调色使用规则:
规则:展示字体用于冲击力,正文字体用于阅读,等宽字体用于数据。
/* 第 1 层:展示/标题 - 大胆、有个性 */
--font-display: 'Chakra Petch', 'Orbitron', 'Bebas Neue', 'Playfair Display';
/* 第 2 层:标题 - 几何、现代 */
--font-heading: 'Manrope', 'Outfit', 'Syne', 'Space Grotesk';
/* 第 3 层:正文 - 简洁、高度易读 */
--font-body: 'Plus Jakarta Sans', 'DM Sans', 'Satoshi', 'General Sans';
/* 第 4 层:数据/代码 - 始终使用等宽字体 */
--font-mono: 'JetBrains Mono', 'Fira Code', 'IBM Plex Mono';
排版模式:
/* 英雄标题:巨大、紧凑、有冲击力 */
.headline {
font-family: var(--font-display);
font-size: clamp(3rem, 12vw, 10rem);
font-weight: 800;
line-height: 0.9;
letter-spacing: -0.03em;
text-transform: uppercase;
}
/* 章节标题 */
.section-title {
font-family: var(--font-heading);
font-size: clamp(1.5rem, 4vw, 3rem);
font-weight: 700;
letter-spacing: -0.02em;
}
/* 技术标签 */
.label {
font-family: var(--font-mono);
font-size: 0.75rem;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--text-muted);
}
/* 数据显示 */
.data {
font-family: var(--font-mono);
font-variant-numeric: tabular-nums;
}
规则:不对称创造趣味。网格是起点,而非牢笼。
/* 间距比例(一致使用) */
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.75rem; /* 12px */
--space-4: 1rem; /* 16px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
--space-12: 3rem; /* 48px */
--space-16: 4rem; /* 64px */
--space-24: 6rem; /* 96px */
--space-32: 8rem; /* 128px */
/* 容器使用充足的填充 */
.container {
padding-inline: clamp(1rem, 5vw, 4rem);
}
/* 英雄区需要呼吸空间 */
.hero {
min-height: 100vh;
padding-block: var(--space-32);
}
Bento 网格模式(用于仪表板):
.bento {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(150px, auto);
gap: var(--space-4);
}
/* 功能卡片跨度 */
.card-hero { grid-column: span 2; grid-row: span 2; }
.card-wide { grid-column: span 2; }
.card-tall { grid-row: span 2; }
.glass {
background: rgba(255, 255, 255, 0.03);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 12px;
}
/* 提升的玻璃态(用于模态框、下拉菜单) */
.glass-elevated {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.4),
inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.scanlines::before {
content: '';
position: fixed;
inset: 0;
background: repeating-linear-gradient(
0deg,
rgba(0, 0, 0, 0.1) 0px,
rgba(0, 0, 0, 0.1) 1px,
transparent 1px,
transparent 2px
);
pointer-events: none;
z-index: 9999;
}
.grain::before {
content: '';
position: fixed;
inset: 0;
opacity: 0.03;
pointer-events: none;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
}
.tech-grid {
background-image:
linear-gradient(rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 60px 60px;
}
/* 文本发光 */
.neon-text {
text-shadow:
0 0 10px currentColor,
0 0 20px currentColor,
0 0 40px currentColor,
0 0 80px currentColor;
}
/* 盒子发光 */
.neon-box {
box-shadow:
0 0 20px var(--accent-alpha-40),
0 0 40px var(--accent-alpha-20),
inset 0 0 20px var(--accent-alpha-10);
}
/* 边框发光 */
.neon-border {
border: 1px solid var(--accent);
box-shadow:
0 0 10px var(--accent-alpha-50),
inset 0 0 10px var(--accent-alpha-20);
}
| 需求 | 使用 | 原因 |
|---|---|---|
| 悬停/焦点状态 | CSS | 零 JS,即时 |
| 简单入场 | CSS 关键帧 | 轻量级 |
| 布局动画 | Framer Motion | layout 属性的魔力 |
| 基于手势 | Framer Motion | 内置拖拽/平移 |
| 滚动触发 | GSAP ScrollTrigger | 最强大 |
| 文本分割 | GSAP SplitText | 行业标准 |
| 复杂时间线 | GSAP | 精确控制 |
| SVG 变形 | GSAP MorphSVG | 无替代方案 |
默认使用更简单的解决方案。仅在需要时增加复杂度。
@keyframes fade-up {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes scale-in {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
@keyframes slide-in-right {
from { opacity: 0; transform: translateX(20px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes pulse-glow {
0%, 100% { opacity: 1; }
50% { opacity: 0.6; }
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
@keyframes rotate-slow {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes scan-line {
0% { transform: translateY(-100%); }
100% { transform: translateY(100vh); }
}
.stagger-container > * {
opacity: 0;
animation: fade-up 0.6s ease-out forwards;
}
.stagger-container > *:nth-child(1) { animation-delay: 0.1s; }
.stagger-container > *:nth-child(2) { animation-delay: 0.2s; }
.stagger-container > *:nth-child(3) { animation-delay: 0.3s; }
.stagger-container > *:nth-child(4) { animation-delay: 0.4s; }
.stagger-container > *:nth-child(5) { animation-delay: 0.5s; }
/* 视图过渡入场(Chrome 111+, Safari 18+) */
@supports (view-transition-name: none) {
.card {
view-transition-name: card;
}
::view-transition-old(card),
::view-transition-new(card) {
animation-duration: 0.3s;
}
}
/* 滚动驱动动画(Chrome 115+) */
@supports (animation-timeline: scroll()) {
.parallax-bg {
animation: parallax linear;
animation-timeline: scroll();
}
@keyframes parallax {
from { transform: translateY(0); }
to { transform: translateY(-30%); }
}
}
/* 具有弹簧感的悬停效果 */
.spring-hover {
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.spring-hover:hover {
transform: scale(1.05);
}
/* 发光脉冲 */
.glow-pulse {
animation: glow-pulse 2s ease-in-out infinite;
}
@keyframes glow-pulse {
0%, 100% { box-shadow: 0 0 20px var(--accent-alpha-40); }
50% { box-shadow: 0 0 40px var(--accent-alpha-60); }
}
// 滚动时的交错入场
gsap.from('.card', {
scrollTrigger: {
trigger: '.cards-section',
start: 'top 80%',
},
y: 60,
opacity: 0,
duration: 0.8,
stagger: 0.1,
ease: 'power3.out',
});
// 文本混乱效果
const scrambleText = (el: HTMLElement, text: string) => {
const chars = '!<>-_\\/[]{}—=+*^?#';
let iteration = 0;
const interval = setInterval(() => {
el.innerText = text
.split('')
.map((char, i) =>
i < iteration ? char : chars[Math.floor(Math.random() * chars.length)]
)
.join('');
if (iteration >= text.length) clearInterval(interval);
iteration += 1/3;
}, 30);
};
// 平滑视差
gsap.to('.parallax-bg', {
scrollTrigger: {
scrub: 1,
},
y: '-30%',
ease: 'none',
});
// 页面过渡
<AnimatePresence mode="wait">
<motion.div
key={page}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.3 }}
/>
</AnimatePresence>
// 悬停发光效果
<motion.div
whileHover={{
scale: 1.02,
boxShadow: '0 0 30px rgba(255, 77, 0, 0.4)',
}}
transition={{ type: 'spring', stiffness: 300 }}
/>
// 交错子元素
<motion.div
initial="hidden"
animate="visible"
variants={{
hidden: {},
visible: { transition: { staggerChildren: 0.1 } },
}}
>
{items.map(item => (
<motion.div
key={item.id}
variants={{
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 },
}}
/>
))}
</motion.div>
npm install three @react-three/fiber @react-three/drei
import { Canvas } from '@react-three/fiber';
import { Stars, Float, MeshDistortMaterial } from '@react-three/drei';
const Scene = () => (
<Canvas
camera={{ position: [0, 0, 5], fov: 75 }}
style={{ position: 'fixed', inset: 0, zIndex: -1 }}
>
<ambientLight intensity={0.2} />
<pointLight position={[10, 10, 10]} color="#ff4d00" />
<Stars radius={100} depth={50} count={3000} />
{/* 你的 3D 内容 */}
</Canvas>
);
const ParticleSphere = ({ count = 3000, color = '#ff4d00' }) => {
const ref = useRef<THREE.Points>(null);
const positions = useMemo(() => {
const pos = new Float32Array(count * 3);
for (let i = 0; i < count; i++) {
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(Math.random() * 2 - 1);
const r = 2;
pos[i * 3] = r * Math.sin(phi) * Math.cos(theta);
pos[i * 3 + 1] = r * Math.sin(phi) * Math.sin(theta);
pos[i * 3 + 2] = r * Math.cos(phi);
}
return pos;
}, [count]);
useFrame(() => {
if (ref.current) ref.current.rotation.y += 0.001;
});
return (
<points ref={ref}>
<bufferGeometry>
<bufferAttribute
attach="attributes-position"
count={count}
array={positions}
itemSize={3}
/>
</bufferGeometry>
<pointsMaterial size={0.02} color={color} transparent opacity={0.8} />
</points>
);
};
const SentientCore = () => (
<Float speed={2} rotationIntensity={0.5}>
<mesh>
<sphereGeometry args={[1.5, 64, 64]} />
<MeshDistortMaterial
color="#00f3ff"
wireframe
distort={0.4}
speed={2}
/>
</mesh>
</Float>
);
useFrame 使用 requestAnimationFramewindow.innerWidth)useMemo 进行几何/位置计算useEffect 返回中清理动画transparent 和 opacity 以进行深度排序默认(除非用户另有要求,否则使用此方案):
可选电影模式(仅当用户想要叙事式启动序列且有时间/预算时):
<nav className="fixed top-4 left-1/2 -translate-x-1/2 z-50">
<div className="glass rounded-full px-6 py-3 flex items-center gap-8">
<Logo />
<NavLinks />
<ThemeToggle />
<CTA />
</div>
</nav>
const Terminal = ({ logs }) => {
const scrollRef = useRef();
useEffect(() => {
scrollRef.current?.scrollTo(0, scrollRef.current.scrollHeight);
}, [logs]);
return (
<div className="glass font-mono text-xs">
<header className="border-b border-white/10 px-4 py-2">
<span className="text-accent">></span> 系统日志
<span className="ml-auto w-2 h-2 bg-green-500 rounded-full animate-pulse" />
</header>
<div ref={scrollRef} className="h-64 overflow-y-auto p-4">
{logs.map(log => (
<div key={log.id}>
<span className="text-zinc-600">{log.time}</span>
<span className={levelColor[log.level]}>[{log.level}]</span>
<span>{log.message}</span>
</div>
))}
</div>
</div>
);
};
const StatCard = ({ icon, label, value, change, trend }) => (
<motion.div
whileHover={{ scale: 1.02, boxShadow: '0 0 30px var(--accent-alpha-30)' }}
className="glass p-4"
>
<div className="flex justify-between">
<div className="p-2 rounded-lg bg-accent/10 text-accent">{icon}</div>
<span className={change > 0 ? 'text-green-400' : 'text-red-400'}>
{change > 0 ? '+' : ''}{change}%
</span>
</div>
<div className="mt-4 font-mono text-2xl font-bold">{value}</div>
<div className="text-xs text-zinc-500 uppercase">{label}</div>
<Sparkline data={trend} className="mt-2 h-8" />
</motion.div>
);
发布前,验证:
useEffect 中的清理函数优秀的设计是包容的。这些不是可选的。
/* 始终尊重用户偏好 */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
// 用于运动偏好的 React 钩子
const usePrefersReducedMotion = () => {
const [prefersReduced, setPrefersReduced] = useState(false);
useEffect(() => {
const mq = window.matchMedia('(prefers-reduced-motion: reduce)');
setPrefersReduced(mq.matches);
const handler = (e: MediaQueryListEvent) => setPrefersReduced(e.matches);
mq.addEventListener('change', handler);
return () => mq.removeEventListener('change', handler);
}, []);
return prefersReduced;
};
// 用法
const shouldAnimate = !usePrefersReducedMotion();
// 始终将装饰性 3D 标记为隐藏
<div aria-hidden="true" className="pointer-events-none">
<Canvas>{/* 装饰性背景 */}</Canvas>
</div>
// 为有意义的 3D 提供文本替代
<div role="img" aria-label="全球网络连接的 3D 可视化">
<Canvas>{/* 数据可视化 */}</Canvas>
</div>
| 元素 | 最小比例 | 目标 |
|---|---|---|
| 正文文本 | 4.5:1 | 7:1 |
| 大文本(18px+) | 3:1 | 4.5:1 |
| UI 组件 | 3:1 | 4.5:1 |
| 装饰性 | N/A | N/A |
/* 深色背景上的安全文本颜色 */
--text-primary: #ffffff; /* ✓ 在 #000 上为 21:1 */
--text-secondary: #a1a1aa; /* ✓ 在 #000 上为 7.2:1 */
--text-muted: #71717a; /* ✓ 在 #000 上为 4.6:1 */
--text-ghost: #52525b; /* ⚠ 在 #000 上为 3.2:1 - 仅用于装饰 */
// 交互式 3D 元素需要键盘支持
<mesh
tabIndex={0}
onKeyDown={(e) => e.key === 'Enter' && handleClick()}
onClick={handleClick}
/>
// 玻璃组件的焦点指示器
.glass:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
高级体验应优雅地适应。不要仅仅缩小——重新构想。
// 检测低功耗设备
const useIsLowPowerDevice = () => {
const [isLowPower, setIsLowPower] = useState(false);
useEffect(() => {
const isLow =
window.innerWidth < 768 ||
navigator.hardwareConcurrency <= 4 ||
/Android|iPhone|iPad/.test(navigator.userAgent);
setIsLowPower(isLow);
}, []);
return isLowPower;
};
// 在英雄组件中的用法
const HeroBackground = () => {
const isLowPower = useIsLowPowerDevice();
if (isLowPower) {
return <CSSGradientFallback />; // 更轻量的替代方案
}
return <WebGLBackground />;
};
| 设备 | JS 预算 | 动画目标 |
|---|---|---|
| 桌面 | < 500KB | 60fps WebGL |
| 平板 | < 300KB | 30fps 或仅 CSS |
| 移动端 | < 150KB | 仅 CSS,无 WebGL |
// 在移动端用点击/长按替换悬停
<motion.div
whileHover={{ scale: 1.02 }} // 桌面
whileTap={{ scale: 0.98 }} // 移动端
onTouchStart={handleTouch}
/>
// 增加触摸目标
.button {
min-height: 44px; /* Apple HIG */
min-width: 44px;
padding: 12px 24px;
}
/* 流体字号比例 */
--text-hero: clamp(2.5rem, 8vw, 7rem);
--text-h1: clamp(2rem, 5vw, 4rem);
--
This skill guides creation of production-grade frontend interfaces that feel ALIVE — not generic, not copy-paste, but genuinely crafted experiences that users remember.
"The difference between a good interface and an unforgettable one is intentionality in every pixel."
This skill is framework-flexible. Pick packages based on user preference and project needs.
pnpm add three @react-three/fiber @react-three/drei
| Library | Best For | Complexity | Bundle Size |
|---|---|---|---|
| CSS/Tailwind | Simple transitions, micro-interactions | Low | 0KB |
| Framer Motion | React-native feel, layout animations, gestures | Medium | ~30KB |
| GSAP | Complex timelines, scroll-triggered, text effects | High | ~60KB |
| GSAP + Club | SplitText, ScrollTrigger, MorphSVG | High | ~80KB |
# Framer Motion (simpler, React-idiomatic)
pnpm add framer-motion
# GSAP (powerful, timeline-based)
pnpm add gsap @gsap/react
# Note: SplitText, ScrollTrigger require GSAP Club license
Decision Guide:
# Mesh gradients (for mesh-gradient-hero)
pnpm add @paper-design/shaders-react
# Icons
pnpm add lucide-react
# Charts/Sparklines (for dashboards)
pnpm add recharts
# or lightweight: pnpm add @visx/shape @visx/scale
backdrop-filter: Not supported in Firefox < 103 (add fallback bg)@starting-style: Chrome 117+, Safari 17.4+ (progressive enhancement)An interface feels alive when:
Before writing a single line, answer these:
Purpose : What problem does this solve? Who uses it?
Tone : Pick ONE extreme direction (not a blend):
The One Thing : What single element will someone remember? Every great interface has a signature moment.
Constraints : Framework, performance budgets, accessibility requirements.
CRITICAL : Bold maximalism and refined minimalism both work. The key is intentionality, not intensity. A single, perfectly-executed animation beats 50 mediocre ones.
Use this whenever the brief is vague or when you need to justify design decisions. The goal is wow factor with purpose.
Hero (wild) → Content blocks (calm) → Proof (calm) → CTA (highlighted).bg-black/70 or bg-slate-950/70 scrim behind text.cubic-bezier(0.34, 1.56, 0.64, 1).prefers-reduced-motion is on OR when user scrolls past hero.| Situation | Default | Optional Upgrade |
|---|---|---|
| User only says “clean SaaS” | mesh-gradient-hero + bento-grid | Swap hero background for CPPN if they later ask for “more energy” |
| User says “dashboard” with no flair | bento-grid + dashboard-widgets + CSS glow pills | Add digital-liquid shader only after data viz is signed off |
| User says “hero section” but nothing else | Text-first layout + CSS gradient | Offer shader/globe as a suggestion, never as default |
If the prompt does not explicitly mention WebGL, assume CSS-first and opt-in to shaders only when the user embraces the cost.
❌ White/light backgrounds as default (dark mode is premium) ❌ Generic gradients (purple-to-blue on white is AI slop) ❌ Evenly-distributed, timid color palettes ❌ Static, lifeless backgrounds ❌ Cookie-cutter component layouts ❌ Missing loading/transition states ❌ Jarring, un-eased animations
❌ Inter, Roboto, Arial, system fonts for headlines ❌ Same font for everything ❌ Default line-heights and letter-spacing ❌ Boring, predictable type scales
❌ Inline styles scattered randomly ❌ No CSS variables for theming ❌ Animations without will-change or GPU acceleration ❌ Canvas/WebGL without requestAnimationFrame ❌ Missing cleanup in useEffect
Rule: ONE dominant accent, everything else supports it.
// Premium Dark Theme (Default)
const colors = {
// Backgrounds (layer from darkest to lightest)
bg: {
void: '#000000', // True black for maximum contrast
primary: '#050505', // Main background
elevated: '#0a0a0a', // Cards, modals
subtle: '#111111', // Hover states
},
// Glass surfaces
glass: {
bg: 'rgba(255, 255, 255, 0.03)',
border: 'rgba(255, 255, 255, 0.08)',
hover: 'rgba(255, 255, 255, 0.06)',
},
// Text hierarchy
text: {
primary: '#ffffff',
secondary: '#a1a1aa', // zinc-400
muted: '#71717a', // zinc-500
ghost: '#3f3f46', // zinc-700
},
// Accent (choose ONE per project)
accent: '#ff4d00', // Neon Orange
// accent: '#00f3ff', // Neon Cyan
// accent: '#ccff00', // Neon Lime
// accent: '#F5E445', // Premium Yellow
// accent: '#a855f7', // Electric Purple
}
Accent Usage Rules :
Rule: Display font for impact, Body font for reading, Mono for data.
/* Tier 1: Display/Headlines - BOLD, characterful */
--font-display: 'Chakra Petch', 'Orbitron', 'Bebas Neue', 'Playfair Display';
/* Tier 2: Headings - Geometric, modern */
--font-heading: 'Manrope', 'Outfit', 'Syne', 'Space Grotesk';
/* Tier 3: Body - Clean, highly legible */
--font-body: 'Plus Jakarta Sans', 'DM Sans', 'Satoshi', 'General Sans';
/* Tier 4: Data/Code - ALWAYS monospace */
--font-mono: 'JetBrains Mono', 'Fira Code', 'IBM Plex Mono';
Typography Patterns :
/* Hero Headlines: Massive, tight, aggressive */
.headline {
font-family: var(--font-display);
font-size: clamp(3rem, 12vw, 10rem);
font-weight: 800;
line-height: 0.9;
letter-spacing: -0.03em;
text-transform: uppercase;
}
/* Section Titles */
.section-title {
font-family: var(--font-heading);
font-size: clamp(1.5rem, 4vw, 3rem);
font-weight: 700;
letter-spacing: -0.02em;
}
/* Technical Labels */
.label {
font-family: var(--font-mono);
font-size: 0.75rem;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--text-muted);
}
/* Data Display */
.data {
font-family: var(--font-mono);
font-variant-numeric: tabular-nums;
}
Rule: Asymmetry creates interest. Grids are starting points, not prisons.
/* Spacing scale (use consistently) */
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.75rem; /* 12px */
--space-4: 1rem; /* 16px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
--space-12: 3rem; /* 48px */
--space-16: 4rem; /* 64px */
--space-24: 6rem; /* 96px */
--space-32: 8rem; /* 128px */
/* Use generous padding on containers */
.container {
padding-inline: clamp(1rem, 5vw, 4rem);
}
/* Hero sections need breathing room */
.hero {
min-height: 100vh;
padding-block: var(--space-32);
}
Bento Grid Pattern (for dashboards):
.bento {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(150px, auto);
gap: var(--space-4);
}
/* Feature card spans */
.card-hero { grid-column: span 2; grid-row: span 2; }
.card-wide { grid-column: span 2; }
.card-tall { grid-row: span 2; }
.glass {
background: rgba(255, 255, 255, 0.03);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 12px;
}
/* Elevated glass (for modals, dropdowns) */
.glass-elevated {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.4),
inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.scanlines::before {
content: '';
position: fixed;
inset: 0;
background: repeating-linear-gradient(
0deg,
rgba(0, 0, 0, 0.1) 0px,
rgba(0, 0, 0, 0.1) 1px,
transparent 1px,
transparent 2px
);
pointer-events: none;
z-index: 9999;
}
.grain::before {
content: '';
position: fixed;
inset: 0;
opacity: 0.03;
pointer-events: none;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
}
.tech-grid {
background-image:
linear-gradient(rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 60px 60px;
}
/* Text glow */
.neon-text {
text-shadow:
0 0 10px currentColor,
0 0 20px currentColor,
0 0 40px currentColor,
0 0 80px currentColor;
}
/* Box glow */
.neon-box {
box-shadow:
0 0 20px var(--accent-alpha-40),
0 0 40px var(--accent-alpha-20),
inset 0 0 20px var(--accent-alpha-10);
}
/* Border glow */
.neon-border {
border: 1px solid var(--accent);
box-shadow:
0 0 10px var(--accent-alpha-50),
inset 0 0 10px var(--accent-alpha-20);
}
| Need | Use | Why |
|---|---|---|
| Hover/focus states | CSS | Zero JS, instant |
| Simple entrance | CSS keyframes | Lightweight |
| Layout animations | Framer Motion | layout prop magic |
| Gesture-based | Framer Motion | Built-in drag/pan |
| Scroll-triggered | GSAP ScrollTrigger | Most powerful |
| Text splitting | GSAP SplitText | Industry standard |
| Complex timelines | GSAP | Precise control |
| SVG morphing | GSAP MorphSVG | No alternative |
Default to simpler solutions. Escalate complexity only when needed.
@keyframes fade-up {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes scale-in {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
@keyframes slide-in-right {
from { opacity: 0; transform: translateX(20px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes pulse-glow {
0%, 100% { opacity: 1; }
50% { opacity: 0.6; }
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
@keyframes rotate-slow {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes scan-line {
0% { transform: translateY(-100%); }
100% { transform: translateY(100vh); }
}
.stagger-container > * {
opacity: 0;
animation: fade-up 0.6s ease-out forwards;
}
.stagger-container > *:nth-child(1) { animation-delay: 0.1s; }
.stagger-container > *:nth-child(2) { animation-delay: 0.2s; }
.stagger-container > *:nth-child(3) { animation-delay: 0.3s; }
.stagger-container > *:nth-child(4) { animation-delay: 0.4s; }
.stagger-container > *:nth-child(5) { animation-delay: 0.5s; }
/* View transition entrance (Chrome 111+, Safari 18+) */
@supports (view-transition-name: none) {
.card {
view-transition-name: card;
}
::view-transition-old(card),
::view-transition-new(card) {
animation-duration: 0.3s;
}
}
/* Scroll-driven animations (Chrome 115+) */
@supports (animation-timeline: scroll()) {
.parallax-bg {
animation: parallax linear;
animation-timeline: scroll();
}
@keyframes parallax {
from { transform: translateY(0); }
to { transform: translateY(-30%); }
}
}
/* Hover with spring-like feel */
.spring-hover {
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.spring-hover:hover {
transform: scale(1.05);
}
/* Glow pulse */
.glow-pulse {
animation: glow-pulse 2s ease-in-out infinite;
}
@keyframes glow-pulse {
0%, 100% { box-shadow: 0 0 20px var(--accent-alpha-40); }
50% { box-shadow: 0 0 40px var(--accent-alpha-60); }
}
// Stagger entrance on scroll
gsap.from('.card', {
scrollTrigger: {
trigger: '.cards-section',
start: 'top 80%',
},
y: 60,
opacity: 0,
duration: 0.8,
stagger: 0.1,
ease: 'power3.out',
});
// Text scramble effect
const scrambleText = (el: HTMLElement, text: string) => {
const chars = '!<>-_\\/[]{}—=+*^?#';
let iteration = 0;
const interval = setInterval(() => {
el.innerText = text
.split('')
.map((char, i) =>
i < iteration ? char : chars[Math.floor(Math.random() * chars.length)]
)
.join('');
if (iteration >= text.length) clearInterval(interval);
iteration += 1/3;
}, 30);
};
// Smooth parallax
gsap.to('.parallax-bg', {
scrollTrigger: {
scrub: 1,
},
y: '-30%',
ease: 'none',
});
// Page transitions
<AnimatePresence mode="wait">
<motion.div
key={page}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.3 }}
/>
</AnimatePresence>
// Hover glow effect
<motion.div
whileHover={{
scale: 1.02,
boxShadow: '0 0 30px rgba(255, 77, 0, 0.4)',
}}
transition={{ type: 'spring', stiffness: 300 }}
/>
// Stagger children
<motion.div
initial="hidden"
animate="visible"
variants={{
hidden: {},
visible: { transition: { staggerChildren: 0.1 } },
}}
>
{items.map(item => (
<motion.div
key={item.id}
variants={{
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 },
}}
/>
))}
</motion.div>
npm install three @react-three/fiber @react-three/drei
import { Canvas } from '@react-three/fiber';
import { Stars, Float, MeshDistortMaterial } from '@react-three/drei';
const Scene = () => (
<Canvas
camera={{ position: [0, 0, 5], fov: 75 }}
style={{ position: 'fixed', inset: 0, zIndex: -1 }}
>
<ambientLight intensity={0.2} />
<pointLight position={[10, 10, 10]} color="#ff4d00" />
<Stars radius={100} depth={50} count={3000} />
{/* Your 3D content */}
</Canvas>
);
const ParticleSphere = ({ count = 3000, color = '#ff4d00' }) => {
const ref = useRef<THREE.Points>(null);
const positions = useMemo(() => {
const pos = new Float32Array(count * 3);
for (let i = 0; i < count; i++) {
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(Math.random() * 2 - 1);
const r = 2;
pos[i * 3] = r * Math.sin(phi) * Math.cos(theta);
pos[i * 3 + 1] = r * Math.sin(phi) * Math.sin(theta);
pos[i * 3 + 2] = r * Math.cos(phi);
}
return pos;
}, [count]);
useFrame(() => {
if (ref.current) ref.current.rotation.y += 0.001;
});
return (
<points ref={ref}>
<bufferGeometry>
<bufferAttribute
attach="attributes-position"
count={count}
array={positions}
itemSize={3}
/>
</bufferGeometry>
<pointsMaterial size={0.02} color={color} transparent opacity={0.8} />
</points>
);
};
const SentientCore = () => (
<Float speed={2} rotationIntensity={0.5}>
<mesh>
<sphereGeometry args={[1.5, 64, 64]} />
<MeshDistortMaterial
color="#00f3ff"
wireframe
distort={0.4}
speed={2}
/>
</mesh>
</Float>
);
requestAnimationFrame via useFramewindow.innerWidth)useMemo for geometry/position calculationsuseEffect returntransparent and opacity for depth sortingDefault (ship this unless user asks otherwise):
Optional Cinematic Mode (only when the user wants a narrative boot sequence and there's time/budget):
<nav className="fixed top-4 left-1/2 -translate-x-1/2 z-50">
<div className="glass rounded-full px-6 py-3 flex items-center gap-8">
<Logo />
<NavLinks />
<ThemeToggle />
<CTA />
</div>
</nav>
const Terminal = ({ logs }) => {
const scrollRef = useRef();
useEffect(() => {
scrollRef.current?.scrollTo(0, scrollRef.current.scrollHeight);
}, [logs]);
return (
<div className="glass font-mono text-xs">
<header className="border-b border-white/10 px-4 py-2">
<span className="text-accent">></span> System Logs
<span className="ml-auto w-2 h-2 bg-green-500 rounded-full animate-pulse" />
</header>
<div ref={scrollRef} className="h-64 overflow-y-auto p-4">
{logs.map(log => (
<div key={log.id}>
<span className="text-zinc-600">{log.time}</span>
<span className={levelColor[log.level]}>[{log.level}]</span>
<span>{log.message}</span>
</div>
))}
</div>
</div>
);
};
const StatCard = ({ icon, label, value, change, trend }) => (
<motion.div
whileHover={{ scale: 1.02, boxShadow: '0 0 30px var(--accent-alpha-30)' }}
className="glass p-4"
>
<div className="flex justify-between">
<div className="p-2 rounded-lg bg-accent/10 text-accent">{icon}</div>
<span className={change > 0 ? 'text-green-400' : 'text-red-400'}>
{change > 0 ? '+' : ''}{change}%
</span>
</div>
<div className="mt-4 font-mono text-2xl font-bold">{value}</div>
<div className="text-xs text-zinc-500 uppercase">{label}</div>
<Sparkline data={trend} className="mt-2 h-8" />
</motion.div>
);
Before shipping, verify:
Great design is inclusive. These aren't optional.
/* ALWAYS respect user preferences */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
// React hook for motion preference
const usePrefersReducedMotion = () => {
const [prefersReduced, setPrefersReduced] = useState(false);
useEffect(() => {
const mq = window.matchMedia('(prefers-reduced-motion: reduce)');
setPrefersReduced(mq.matches);
const handler = (e: MediaQueryListEvent) => setPrefersReduced(e.matches);
mq.addEventListener('change', handler);
return () => mq.removeEventListener('change', handler);
}, []);
return prefersReduced;
};
// Usage
const shouldAnimate = !usePrefersReducedMotion();
// Always mark decorative 3D as hidden
<div aria-hidden="true" className="pointer-events-none">
<Canvas>{/* decorative background */}</Canvas>
</div>
// Provide text alternatives for meaningful 3D
<div role="img" aria-label="3D visualization of global network connections">
<Canvas>{/* data visualization */}</Canvas>
</div>
| Element | Minimum Ratio | Target |
|---|---|---|
| Body text | 4.5:1 | 7:1 |
| Large text (18px+) | 3:1 | 4.5:1 |
| UI components | 3:1 | 4.5:1 |
| Decorative | N/A | N/A |
/* Safe text colors on dark backgrounds */
--text-primary: #ffffff; /* ✓ 21:1 on #000 */
--text-secondary: #a1a1aa; /* ✓ 7.2:1 on #000 */
--text-muted: #71717a; /* ✓ 4.6:1 on #000 */
--text-ghost: #52525b; /* ⚠ 3.2:1 - decorative only */
// Interactive 3D elements need keyboard support
<mesh
tabIndex={0}
onKeyDown={(e) => e.key === 'Enter' && handleClick()}
onClick={handleClick}
/>
// Focus indicators for glass components
.glass:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
Premium experiences adapt gracefully. Don't just shrink — reimagine.
// Detect low-power devices
const useIsLowPowerDevice = () => {
const [isLowPower, setIsLowPower] = useState(false);
useEffect(() => {
const isLow =
window.innerWidth < 768 ||
navigator.hardwareConcurrency <= 4 ||
/Android|iPhone|iPad/.test(navigator.userAgent);
setIsLowPower(isLow);
}, []);
return isLowPower;
};
// Usage in hero components
const HeroBackground = () => {
const isLowPower = useIsLowPowerDevice();
if (isLowPower) {
return <CSSGradientFallback />; // Lighter alternative
}
return <WebGLBackground />;
};
| Device | JS Budget | Animation Target |
|---|---|---|
| Desktop | < 500KB | 60fps WebGL |
| Tablet | < 300KB | 30fps or CSS-only |
| Mobile | < 150KB | CSS-only, no WebGL |
// Replace hover with tap/long-press on mobile
<motion.div
whileHover={{ scale: 1.02 }} // Desktop
whileTap={{ scale: 0.98 }} // Mobile
onTouchStart={handleTouch}
/>
// Increase touch targets
.button {
min-height: 44px; /* Apple HIG */
min-width: 44px;
padding: 12px 24px;
}
/* Fluid type scale */
--text-hero: clamp(2.5rem, 8vw, 7rem);
--text-h1: clamp(2rem, 5vw, 4rem);
--text-h2: clamp(1.5rem, 3vw, 2.5rem);
--text-body: clamp(1rem, 2vw, 1.125rem);
/* Reduce letter-spacing on mobile */
@media (max-width: 768px) {
.headline {
letter-spacing: -0.02em; /* Less aggressive than desktop */
}
}
Premium UX handles every state beautifully.
// Glass skeleton with shimmer
const Skeleton = ({ className }: { className?: string }) => (
<div
className={`relative overflow-hidden rounded-lg bg-white/5 ${className}`}
>
<div
className="absolute inset-0 -translate-x-full animate-[shimmer_2s_infinite] bg-gradient-to-r from-transparent via-white/10 to-transparent"
/>
</div>
);
// Usage
<div className="space-y-4">
<Skeleton className="h-8 w-3/4" />
<Skeleton className="h-4 w-full" />
<Skeleton className="h-4 w-5/6" />
</div>
@keyframes shimmer {
100% { transform: translateX(100%); }
}
const ErrorFallback = ({ error, resetErrorBoundary }) => (
<div className="glass p-8 text-center">
<div className="mx-auto mb-4 h-16 w-16 rounded-full bg-red-500/10 flex items-center justify-center">
<AlertTriangle className="h-8 w-8 text-red-400" />
</div>
<h2 className="text-xl font-semibold text-white mb-2">
Something went wrong
</h2>
<p className="text-zinc-400 mb-4 font-mono text-sm">
{error.message}
</p>
<button
onClick={resetErrorBoundary}
className="px-4 py-2 bg-white/10 rounded-lg hover:bg-white/20 transition"
>
Try again
</button>
</div>
);
const EmptyState = ({
icon: Icon,
title,
description,
action
}: EmptyStateProps) => (
<div className="flex flex-col items-center justify-center py-16 text-center">
<div className="mb-4 rounded-full bg-white/5 p-4">
<Icon className="h-8 w-8 text-zinc-500" />
</div>
<h3 className="text-lg font-medium text-white mb-1">{title}</h3>
<p className="text-zinc-400 mb-4 max-w-sm">{description}</p>
{action}
</div>
);
// Usage
<EmptyState
icon={Inbox}
title="No messages yet"
description="When you receive messages, they'll appear here."
action={<Button>Send your first message</Button>}
/>
// Optimistic UI with rollback
const [items, setItems] = useState(data);
const [pending, startTransition] = useTransition();
const addItem = (newItem) => {
// Optimistic update
setItems(prev => [...prev, { ...newItem, pending: true }]);
startTransition(async () => {
try {
await api.createItem(newItem);
} catch {
// Rollback on error
setItems(prev => prev.filter(i => i.id !== newItem.id));
toast.error('Failed to add item');
}
});
};
// Client boundary for WebGL components
// app/components/hero-client.tsx
'use client';
import dynamic from 'next/dynamic';
// Lazy load heavy 3D components
const WebGLHero = dynamic(() => import('./webgl-hero'), {
ssr: false,
loading: () => <HeroSkeleton />,
});
export default function HeroClient() {
return <WebGLHero />;
}
// Server component wrapper
// app/page.tsx
import HeroClient from './components/hero-client';
export default function Page() {
return (
<main>
{/* Server-rendered SEO content */}
<h1 className="sr-only">Your SEO Title</h1>
{/* Client-side 3D hero */}
<HeroClient />
</main>
);
}
// WebGL isn't crawlable - always provide text alternatives
<section aria-labelledby="hero-title">
{/* Hidden but crawlable */}
<h1 id="hero-title" className="sr-only">
AI-Powered Trading Platform
</h1>
<p className="sr-only">
{seoDescription}
</p>
{/* Visual hero (not crawled) */}
<div aria-hidden="true">
<Canvas>...</Canvas>
</div>
{/* Visible text (crawled) */}
<div className="relative z-10">
<span className="text-7xl">{visibleTitle}</span>
</div>
</section>
// Server Component with Suspense
import { Suspense } from 'react';
async function DashboardData() {
const data = await fetchDashboardData();
return <DashboardWidgets data={data} />;
}
export default function Dashboard() {
return (
<div className="bento-grid">
<Suspense fallback={<WidgetSkeleton />}>
<DashboardData />
</Suspense>
</div>
);
}
| Template | Props | WebGL | Mobile Fallback | Best Animation Lib |
|---|---|---|---|---|
cppn-hero | title, description, ctaButtons, microDetails | Yes | CSS gradient | GSAP (SplitText) |
mesh-gradient-hero | colors[], , , |
*mesh-gradient-hero uses @paper-design/shaders-react (Canvas, not WebGL)
| Goal | Baseline (Clarity-first) | Optional Wow Upgrade | Kill It If |
|---|---|---|---|
| Marketing / Waitlist | mesh-gradient-hero + glass-components + bento-grid value props | Swap hero for cppn-hero or add wave-hero band for social proof | Copy is long-form or the product is compliance-heavy |
| AI / Research Landing | cppn-hero + dashboard-widgets (metrics) + logs |
mesh-gradient-hero in CSS mode) → Navigation grid → Content area (monospace) → CTA.Each flow should have at most two high-saturation panels. If you need more energy, animate the CTA or accent borders instead of adding another shader.
| Need | Action | Notes |
|---|---|---|
| Downgrade WebGL → CSS | Replace cppn-hero with mesh-gradient-hero, keep same copy. Swap shader backgrounds for bg-gradient-to-b. | Use when user mentions “mobile-first,” “performance,” or “lightweight.” |
| Upgrade CSS → WebGL | Start from mesh-gradient-hero, then inject ShaderBackground and reuse props from cppn-hero. | Only after confirming the client wants “cinematic” or “experimental.” |
When in doubt: start with the baseline, ship usable layout, then pitch a single wow upgrade as a follow-up suggestion (“Optionally we can swap in the CPPN shader if you want a more neural vibe.”).
Use this guide to pick the right template and shader based on the user's request. Don't default to the same hero for everything — match the aesthetic to the domain.
| Industry | Hero Template | Shader | Accent Color | Tone |
|---|---|---|---|---|
| AI/ML/Neural | cppn-hero | cppn-generative | Cyan #00f3ff / Purple #a855f7 | Organic, alive, mathematical |
| Crypto/DeFi/Trading | globe-hero | data-grid |
When analyzing user requests, match keywords to templates:
User Request Analysis:
├── Contains "AI", "neural", "intelligent", "learning", "model", "GPT"
│ → cppn-hero + cppn-generative shader
│ → Organic, flowing backgrounds that feel "alive"
│
├── Contains "crypto", "blockchain", "trading", "global", "DeFi", "web3"
│ → globe-hero + data-grid shader
│ → Earth imagery, global reach, financial precision
│
├── Contains "developer", "API", "code", "build", "deploy", "ship"
│ → wave-hero + digital-liquid shader
│ → Dynamic bars, typing animations, terminal aesthetic
│
├── Contains "SaaS", "product", "waitlist", "brand", "startup", "launch"
│ → mesh-gradient-hero (no WebGL needed)
│ → Soft, fluid gradients, professional feel
│
├── Contains "futuristic", "cyber", "agency", "creative", "portfolio"
│ → hero-section (CyberpunkHero) + holographic shader
│ → Particle spheres, text scramble, scanlines
│
└── Contains "dashboard", "analytics", "metrics", "data", "monitoring"
→ bento-grid + dashboard-widgets + terminal
→ Stat cards, sparklines, live data feeds
Choose based on target audience and device constraints:
| Performance Tier | Templates | Best For |
|---|---|---|
| High-end (WebGL) | cppn-hero, wave-hero, hero-section | Desktop-first, portfolio sites, creative agencies |
| Medium (Canvas/Images) | globe-hero | Marketing sites, crypto landing pages |
| Light (CSS only) | mesh-gradient-hero, bento-grid | Mobile-first, SaaS, B2B, accessibility-focused |
| Shader | Aesthetic | Pairs Well With |
|---|---|---|
cppn-generative | Neural, organic, mathematical | AI products, generative art, research tools |
data-grid | Matrix, technical, cyberpunk | Crypto, fintech, developer tools |
digital-liquid | Flowing, dynamic, fluid | Creative tools, media platforms |
holographic | Sci-fi, iridescent, futuristic | Gaming, AR/VR, experimental projects |
Is performance critical (mobile-first)?
├── YES → mesh-gradient-hero (CSS only)
└── NO → Continue...
│
Is it AI/ML related?
├── YES → cppn-hero
└── NO → Continue...
│
Is it crypto/global/financial?
├── YES → globe-hero
└── NO → Continue...
│
Is it developer-focused?
├── YES → wave-hero
└── NO → hero-section (CyberpunkHero)
premium-frontend-skill/
├── SKILL.md # This document
├── examples/
│ ├── 01-racing-dashboard.tsx # Motorsport telemetry
│ ├── 02-cyberpunk-platform.tsx # Developer platform
│ ├── 03-bioluminescent-landing.tsx # AI agency landing
│ ├── 04-fintech-protocol.tsx # DeFi interface
│ └── 05-neural-interface.tsx # Sentient AI core
├── templates/
│ ├── preloader.tsx # Boot sequence loader
│ ├── glass-components.tsx # Glassmorphic UI elements
│ ├── terminal.tsx # Live logs display
│ ├── bento-grid.tsx # Dashboard layout system
│ ├── dashboard-widgets.tsx # Stat cards, charts, metrics
│ ├── hero-section.tsx # CyberpunkHero + StarfieldScene
│ ├── cppn-hero.tsx # Neural network shader hero
│ ├── mesh-gradient-hero.tsx # Fluid gradient hero (CSS-light)
│ ├── wave-hero.tsx # Animated wave bars hero
│ └── globe-hero.tsx # 3D globe with dashboard
└── shaders/
├── cppn-generative.glsl.ts # Neural pattern generator
├── digital-liquid.glsl.ts # Flowing noise effect
├── data-grid.glsl.ts # Matrix/grid effect
└── holographic.glsl.ts # Hologram interference
"The goal is to create interfaces that feel alive , cinematic , and unforgettable. Every pixel should be intentional. These aren't just websites—they're experiences."
Don't hold back. Show what can truly be created when thinking outside the box and committing fully to a distinctive vision.
Weekly Installs
663
Repository
GitHub Stars
11
First Seen
Jan 21, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode578
gemini-cli561
codex559
cursor527
github-copilot525
claude-code476
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
106,200 周安装
speeddistortionswirl| No* |
| Native |
| Framer Motion |
wave-hero | title, subtitle, placeholder, onPromptSubmit | Yes | Solid bg | GSAP |
globe-hero | globeImage, dashboardImage, accentColor | No | Native | Framer Motion |
hero-section | title, badge, primaryCTA, accentColor | Yes | Stars CSS | Either |
bento-grid | children (card layout) | No | Native | CSS or Framer |
dashboard-widgets | value, change, trend[] | No | Native | Framer Motion |
terminal | logs[], title | No | Native | CSS |
preloader | onComplete, messages[] | Optional | CSS version | GSAP |
glass-components | Various | No | Native | CSS |
terminalAdd holographic shader sections or globe-hero interlude |
| User needs print-friendly deliverables |
| Crypto / Finance | globe-hero + bento-grid KPIs + dashboard-widgets + CTA strip | Add data-grid shader background or rolling ticker | Performance budget < 200KB or mobile-only |
| Developer Tools | wave-hero + terminal + glass-components cards | Introduce digital-liquid shader or 3D device mock | Audience is enterprise buyers needing conservative tone |
| Product Dashboard | bento-grid + dashboard-widgets + mesh-gradient-hero (static) | Add mini WebGL module (sentient core, particle globe) | Data is dense, requires tabular clarity |
Any hero using shaders can switch to another by swapping imports (e.g., holographic ↔ digital-liquid). Keep uniform names consistent. |
| Document the new accent palette alongside the swap. |
| Content density mode | When the design needs to carry lots of text, keep hero flourish but make every subsequent section bg-black with simple borders. | Example: cppn-hero on top, then bento-grid in plain glass cards. |
| Prompt-to-template defaults | - “Clean SaaS” → Mesh gradient package - “AI platform” → CPPN hero + dashboard metrics - “Crypto trading” → Globe hero + ticker - “Developer CLI” → Wave hero + terminal | Mention these defaults directly in responses so the model doesn’t hallucinate new structures. |
Purple #9b87f5 / Amber #f59e0b |
| Global, technical, financial |
| Developer Tools/API | wave-hero | digital-liquid | Blue #1f3dbc / Orange #ff4d00 | Technical, dynamic, builder |
| SaaS/B2B/Product | mesh-gradient-hero | (CSS only) | Soft pastels | Clean, professional, trustworthy |
| Creative Agency | hero-section (CyberpunkHero) | holographic | Neon colors | Bold, experimental, artistic |
| Fintech/Dashboard | bento-grid + dashboard-widgets | data-grid | Green #10b981 / Blue #3b82f6 | Data-rich, precise, analytical |